diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 0000000000000000000000000000000000000000..34ffd2287588e48bdee09fbb746bd143f7d61b5f --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,11 @@ +# Changes here will be overwritten by Copier +_commit: v0.1.6 +_src_path: https://gitlab.softwareheritage.org/swh/devel/swh-py-template.git +description: Software Heritage data model +distribution_name: swh-model +have_cli: true +have_workers: false +package_root: swh/model +project_name: swh.model +python_minimal_version: '3.7' +readme_format: rst diff --git a/.gitignore b/.gitignore index 68708728197a5774d0b68cdd676cd092103aa1fe..d44f090faaff2efa7c3dfa14d2a402ae0d6b4eaf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,16 @@ -*~ -build -/.coverage -/.coverage.* -dist *.egg-info/ +*.pyc +.coverage .eggs/ .hypothesis -*.pyc -__pycache__ -.pytest_cache -*.sw? +.mypy_cache .tox -version.txt -.mypy_cache/ +__pycache__ +build/ +dist/ +# these are symlinks created by a hook in swh-docs' main sphinx conf.py +docs/README.rst +docs/README.md +# this should be a symlink for people who want to build the sphinx doc +# without using tox, generally created by the swh-env/bin/update script +docs/Makefile.sphinx diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 33a226de603535a6347f7fd1c5a5ec7f4a7e8765..8957bec6128b471c890816598b471a0116b18f7e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,13 +1,23 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.4.0 hooks: - id: trailing-whitespace - id: check-json - id: check-yaml + - repo: https://github.com/python/black + rev: 23.1.0 + hooks: + - id: black + + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + - repo: https://github.com/pycqa/flake8 - rev: 5.0.4 + rev: 6.0.0 hooks: - id: flake8 additional_dependencies: [flake8-bugbear==22.9.23] @@ -18,6 +28,9 @@ repos: - id: codespell name: Check source code spelling stages: [commit] + - id: codespell + name: Check commit message spelling + stages: [commit-msg] - repo: local hooks: @@ -29,12 +42,3 @@ repos: language: system types: [python] - - repo: https://github.com/PyCQA/isort - rev: 5.11.5 - hooks: - - id: isort - - - repo: https://github.com/python/black - rev: 22.10.0 - hooks: - - id: black diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index caa4b690c5fefc3b25112d1e63359adb6f8d48ef..0000000000000000000000000000000000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -include README.md -include Makefile -include requirements*.txt -include version.txt -recursive-include swh/model/tests/data *.tgz -recursive-include swh py.typed diff --git a/PKG-INFO b/PKG-INFO index 2b39d445071a74288e1f17dd61eb9983142f4d28..3a5db5f62b9644ca76fa6a426b9450a389a637a4 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,14 +1,13 @@ Metadata-Version: 2.1 Name: swh.model -Version: 6.9.1 +Version: 6.10.0 Summary: Software Heritage data model -Home-page: https://forge.softwareheritage.org/diffusion/DMOD/ -Author: Software Heritage developers -Author-email: swh-devel@inria.fr -Project-URL: Bug Reports, https://forge.softwareheritage.org/maniphest +Author-email: Software Heritage developers <swh-devel@inria.fr> +Project-URL: Homepage, https://gitlab.softwareheritage.org/swh/devel/swh-model +Project-URL: Bug Reports, https://gitlab.softwareheritage.org/swh/devel/swh-model/-/issues Project-URL: Funding, https://www.softwareheritage.org/donate -Project-URL: Source, https://forge.softwareheritage.org/source/swh-model Project-URL: Documentation, https://docs.softwareheritage.org/devel/swh-model/ +Project-URL: Source, https://gitlab.softwareheritage.org/swh/devel/swh-model.git Classifier: Programming Language :: Python :: 3 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) @@ -29,15 +28,10 @@ Provides-Extra: cli Requires-Dist: swh.core>=0.3; extra == "cli" Requires-Dist: Click; extra == "cli" Requires-Dist: dulwich; extra == "cli" -Provides-Extra: testing-minimal -Requires-Dist: aiohttp; extra == "testing-minimal" -Requires-Dist: click; extra == "testing-minimal" -Requires-Dist: pytest; extra == "testing-minimal" -Requires-Dist: pytz; extra == "testing-minimal" -Requires-Dist: types-click; extra == "testing-minimal" -Requires-Dist: types-python-dateutil; extra == "testing-minimal" -Requires-Dist: types-pytz; extra == "testing-minimal" Provides-Extra: testing +Requires-Dist: swh.core>=0.3; extra == "testing" +Requires-Dist: Click; extra == "testing" +Requires-Dist: dulwich; extra == "testing" Requires-Dist: aiohttp; extra == "testing" Requires-Dist: click; extra == "testing" Requires-Dist: pytest; extra == "testing" @@ -45,9 +39,14 @@ Requires-Dist: pytz; extra == "testing" Requires-Dist: types-click; extra == "testing" Requires-Dist: types-python-dateutil; extra == "testing" Requires-Dist: types-pytz; extra == "testing" -Requires-Dist: swh.core>=0.3; extra == "testing" -Requires-Dist: Click; extra == "testing" -Requires-Dist: dulwich; extra == "testing" +Provides-Extra: testing-minimal +Requires-Dist: aiohttp; extra == "testing-minimal" +Requires-Dist: click; extra == "testing-minimal" +Requires-Dist: pytest; extra == "testing-minimal" +Requires-Dist: pytz; extra == "testing-minimal" +Requires-Dist: types-click; extra == "testing-minimal" +Requires-Dist: types-python-dateutil; extra == "testing-minimal" +Requires-Dist: types-pytz; extra == "testing-minimal" Software Heritage - Data model ============================== diff --git a/docs/Makefile b/docs/Makefile index b97c7532e5b946df72b8641f22f6e3e2ba84602c..5e57d15d9e950b11d45d4f1241e9eadc67ecbd38 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,2 +1,2 @@ -include ../../swh-docs/Makefile.sphinx +include Makefile.sphinx -include Makefile.local diff --git a/mypy.ini b/mypy.ini index d411c51089c58ee654ae210c90af17e8bb388e1a..2f09ec1206332b62139f5d945e5fabbe1c165d2b 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,6 +1,13 @@ [mypy] namespace_packages = True warn_unused_ignores = True +explicit_package_bases = True +# ^ Needed for mypy to detect py.typed from swh packages installed +# in editable mode # 3rd party libraries without stubs (yet) +[mypy-pkg_resources.*] +ignore_missing_imports = True +# [mypy-add_your_lib_here.*] +# ignore_missing_imports = True diff --git a/pyproject.toml b/pyproject.toml index 69b8f4dd830abf638e624eeea85dbc580c862538..dc4a8fdbcfa318a976278be5dac404f5fde26591 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,52 @@ +[project] +name = "swh.model" +authors = [ + {name="Software Heritage developers", email="swh-devel@inria.fr"}, +] + +description = "Software Heritage data model" +readme = {file = "README.rst", content-type = "text/x-rst"} +requires-python = ">=3.7" +classifiers = [ + "Programming Language :: Python :: 3", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Operating System :: OS Independent", + "Development Status :: 5 - Production/Stable", +] +dynamic = ["version", "dependencies", "optional-dependencies"] + +[tool.setuptools.packages.find] +include = ["swh.*"] + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} + +[tool.setuptools.dynamic.optional-dependencies] +cli = {file = "requirements-cli.txt"} +testing = {file = ["requirements-cli.txt", "requirements-test.txt"]} +testing_minimal = {file = "requirements-test.txt"} + +[project.entry-points.console_scripts] +"swh.identify" = "swh.model.cli:identify" + +[project.entry-points."swh.cli.subcommands"] +"swh.model" = "swh.model.cli" + +[project.urls] +"Homepage" = "https://gitlab.softwareheritage.org/swh/devel/swh-model" +"Bug Reports" = "https://gitlab.softwareheritage.org/swh/devel/swh-model/-/issues" +"Funding" = "https://www.softwareheritage.org/donate" +"Documentation" = "https://docs.softwareheritage.org/devel/swh-model/" +"Source" = "https://gitlab.softwareheritage.org/swh/devel/swh-model.git" + +[build-system] +requires = ["setuptools", "setuptools-scm"] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +fallback_version = "0.0.1" + [tool.black] target-version = ['py37'] @@ -9,3 +58,4 @@ use_parentheses = true ensure_newline_before_comments = true line_length = 88 force_sort_within_sections = true +known_first_party = ['swh'] diff --git a/pytest.ini b/pytest.ini index 10242f24f0323cac877764b3d4db78b11aa182f7..1782940443bf7d2776787ba40c5344c1989ff032 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,8 +1,12 @@ [pytest] -addopts = --doctest-modules -p no:pytest_swh_core norecursedirs = build docs .* +asyncio_mode = strict +# There is not --import-mode=importlib below because it is incompatible +# with the tox-in-tox hack we use for now to run tests. +addopts = + --doctest-modules + -p no:pytest_swh_core + markers = fs: tests that involve filesystem ios requires_optional_deps: tests in test_cli.py that should not run if optional dependencies are not installed - -asyncio_mode = strict diff --git a/setup.py b/setup.py deleted file mode 100755 index 8698ecc1975a5ffe4091d738cb9407c2bc443bf5..0000000000000000000000000000000000000000 --- a/setup.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (C) 2015-2020 The Software Heritage developers -# See the AUTHORS file at the top-level directory of this distribution -# License: GNU General Public License version 3, or any later version -# See top-level LICENSE file for more information - -from io import open -from os import path - -from setuptools import find_packages, setup - -here = path.abspath(path.dirname(__file__)) - -# Get the long description from the README file -with open(path.join(here, "README.rst"), encoding="utf-8") as f: - long_description = f.read() - - -def parse_requirements(name=None): - if name: - reqf = "requirements-%s.txt" % name - else: - reqf = "requirements.txt" - - requirements = [] - if not path.exists(reqf): - return requirements - - with open(reqf) as f: - for line in f.readlines(): - line = line.strip() - if not line or line.startswith("#"): - continue - requirements.append(line) - return requirements - - -setup( - name="swh.model", - description="Software Heritage data model", - long_description=long_description, - long_description_content_type="text/x-rst", - python_requires=">=3.7", - author="Software Heritage developers", - author_email="swh-devel@inria.fr", - url="https://forge.softwareheritage.org/diffusion/DMOD/", - packages=find_packages(), - setup_requires=["setuptools-scm"], - use_scm_version=True, - install_requires=parse_requirements() + parse_requirements("swh"), - extras_require={ - "cli": parse_requirements("cli"), - "testing-minimal": parse_requirements("test"), - "testing": parse_requirements("test") + parse_requirements("cli"), - }, - include_package_data=True, - entry_points=""" - [console_scripts] - swh-identify=swh.model.cli:identify - [swh.cli.subcommands] - identify=swh.model.cli - """, - classifiers=[ - "Programming Language :: Python :: 3", - "Intended Audience :: Developers", - "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", - "Operating System :: OS Independent", - "Development Status :: 5 - Production/Stable", - ], - project_urls={ - "Bug Reports": "https://forge.softwareheritage.org/maniphest", - "Funding": "https://www.softwareheritage.org/donate", - "Source": "https://forge.softwareheritage.org/source/swh-model", - "Documentation": "https://docs.softwareheritage.org/devel/swh-model/", - }, -) diff --git a/swh.model.egg-info/PKG-INFO b/swh.model.egg-info/PKG-INFO index 2b39d445071a74288e1f17dd61eb9983142f4d28..3a5db5f62b9644ca76fa6a426b9450a389a637a4 100644 --- a/swh.model.egg-info/PKG-INFO +++ b/swh.model.egg-info/PKG-INFO @@ -1,14 +1,13 @@ Metadata-Version: 2.1 Name: swh.model -Version: 6.9.1 +Version: 6.10.0 Summary: Software Heritage data model -Home-page: https://forge.softwareheritage.org/diffusion/DMOD/ -Author: Software Heritage developers -Author-email: swh-devel@inria.fr -Project-URL: Bug Reports, https://forge.softwareheritage.org/maniphest +Author-email: Software Heritage developers <swh-devel@inria.fr> +Project-URL: Homepage, https://gitlab.softwareheritage.org/swh/devel/swh-model +Project-URL: Bug Reports, https://gitlab.softwareheritage.org/swh/devel/swh-model/-/issues Project-URL: Funding, https://www.softwareheritage.org/donate -Project-URL: Source, https://forge.softwareheritage.org/source/swh-model Project-URL: Documentation, https://docs.softwareheritage.org/devel/swh-model/ +Project-URL: Source, https://gitlab.softwareheritage.org/swh/devel/swh-model.git Classifier: Programming Language :: Python :: 3 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) @@ -29,15 +28,10 @@ Provides-Extra: cli Requires-Dist: swh.core>=0.3; extra == "cli" Requires-Dist: Click; extra == "cli" Requires-Dist: dulwich; extra == "cli" -Provides-Extra: testing-minimal -Requires-Dist: aiohttp; extra == "testing-minimal" -Requires-Dist: click; extra == "testing-minimal" -Requires-Dist: pytest; extra == "testing-minimal" -Requires-Dist: pytz; extra == "testing-minimal" -Requires-Dist: types-click; extra == "testing-minimal" -Requires-Dist: types-python-dateutil; extra == "testing-minimal" -Requires-Dist: types-pytz; extra == "testing-minimal" Provides-Extra: testing +Requires-Dist: swh.core>=0.3; extra == "testing" +Requires-Dist: Click; extra == "testing" +Requires-Dist: dulwich; extra == "testing" Requires-Dist: aiohttp; extra == "testing" Requires-Dist: click; extra == "testing" Requires-Dist: pytest; extra == "testing" @@ -45,9 +39,14 @@ Requires-Dist: pytz; extra == "testing" Requires-Dist: types-click; extra == "testing" Requires-Dist: types-python-dateutil; extra == "testing" Requires-Dist: types-pytz; extra == "testing" -Requires-Dist: swh.core>=0.3; extra == "testing" -Requires-Dist: Click; extra == "testing" -Requires-Dist: dulwich; extra == "testing" +Provides-Extra: testing-minimal +Requires-Dist: aiohttp; extra == "testing-minimal" +Requires-Dist: click; extra == "testing-minimal" +Requires-Dist: pytest; extra == "testing-minimal" +Requires-Dist: pytz; extra == "testing-minimal" +Requires-Dist: types-click; extra == "testing-minimal" +Requires-Dist: types-python-dateutil; extra == "testing-minimal" +Requires-Dist: types-pytz; extra == "testing-minimal" Software Heritage - Data model ============================== diff --git a/swh.model.egg-info/SOURCES.txt b/swh.model.egg-info/SOURCES.txt index e835209099f5b62c794fd0f8ddde6eb5bd602c23..e7c1502139a4ff80f2c4bf578489a4722799019e 100644 --- a/swh.model.egg-info/SOURCES.txt +++ b/swh.model.egg-info/SOURCES.txt @@ -1,3 +1,4 @@ +.copier-answers.yml .git-blame-ignore-revs .gitignore .pre-commit-config.yaml @@ -5,7 +6,6 @@ AUTHORS CODE_OF_CONDUCT.md CONTRIBUTORS LICENSE -MANIFEST.in Makefile Makefile.local README.rst @@ -16,7 +16,6 @@ requirements-cli.txt requirements-test.txt requirements.txt setup.cfg -setup.py tox.ini bin/git-revhash bin/swh-hashtree @@ -35,7 +34,6 @@ docs/_templates/.placeholder docs/images/.gitignore docs/images/Makefile docs/images/swh-merkle-dag.dia -swh/__init__.py swh.model.egg-info/PKG-INFO swh.model.egg-info/SOURCES.txt swh.model.egg-info/dependency_links.txt diff --git a/swh.model.egg-info/entry_points.txt b/swh.model.egg-info/entry_points.txt index 4e29a6a9f180b72d0492d92a68223c4afae58c83..086c813cb88693d1a78a390eb534950953067d88 100644 --- a/swh.model.egg-info/entry_points.txt +++ b/swh.model.egg-info/entry_points.txt @@ -1,5 +1,5 @@ [console_scripts] -swh-identify = swh.model.cli:identify +swh.identify = swh.model.cli:identify [swh.cli.subcommands] -identify = swh.model.cli +swh.model = swh.model.cli diff --git a/swh.model.egg-info/requires.txt b/swh.model.egg-info/requires.txt index 39f740b37efe9a654ae1762e2cde95e53e487434..f10fca8983487e0ae01fabb44eedfbdbdc5d402b 100644 --- a/swh.model.egg-info/requires.txt +++ b/swh.model.egg-info/requires.txt @@ -12,6 +12,9 @@ Click dulwich [testing] +swh.core>=0.3 +Click +dulwich aiohttp click pytest @@ -19,11 +22,8 @@ pytz types-click types-python-dateutil types-pytz -swh.core>=0.3 -Click -dulwich -[testing-minimal] +[testing_minimal] aiohttp click pytest diff --git a/swh/__init__.py b/swh/__init__.py deleted file mode 100644 index b36383a61027f0875a3cb103edc8f2a4528a3289..0000000000000000000000000000000000000000 --- a/swh/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from pkgutil import extend_path - -__path__ = extend_path(__path__, __name__) diff --git a/swh/model/cli.py b/swh/model/cli.py index 6508602110672049403ed507b5274549527d14dc..7fd99ed0a1c51407fae814786ff2deb6aed72537 100644 --- a/swh/model/cli.py +++ b/swh/model/cli.py @@ -20,10 +20,12 @@ except ImportError: exit(1) try: - from swh.core.cli import swh as swh_cli_group + import swh.core.cli + + cli_command = swh.core.cli.swh.command except ImportError: # stub so that swh-identify can be used when swh-core isn't installed - swh_cli_group = click # type: ignore + cli_command = click.command from swh.model.from_disk import Directory from swh.model.swhids import CoreSWHID @@ -175,7 +177,7 @@ def identify_object( return swhid -@swh_cli_group.command(context_settings=CONTEXT_SETTINGS) +@cli_command(context_settings=CONTEXT_SETTINGS) @click.option( "--dereference/--no-dereference", "follow_symlinks", @@ -304,7 +306,7 @@ def identify( click.echo("SWHID mismatch: %s != %s" % (verify, swhid)) sys.exit(1) else: - for (obj, swhid) in results: + for obj, swhid in results: msg = swhid if show_filename: msg = "%s\t%s" % (swhid, os.fsdecode(obj)) diff --git a/swh/model/collections.py b/swh/model/collections.py index d7150fa9c2477d2297c175bee37d67da2a5f8408..35314ca06c3b925982fa0a544d6532d6f17d7a9e 100644 --- a/swh/model/collections.py +++ b/swh/model/collections.py @@ -45,7 +45,7 @@ class ImmutableDict(Mapping, Generic[KT, VT]): return self._data[key] def __iter__(self): - for (k, v) in self.data: + for k, v in self.data: yield k def __len__(self): @@ -61,5 +61,5 @@ class ImmutableDict(Mapping, Generic[KT, VT]): """Returns a copy of this ImmutableDict without the given key, as well as the value associated to the key.""" new_items = copy.deepcopy(self._data) - popped_value = new_items.pop(popped_key, None) # type: ignore + popped_value: Optional[VT] = new_items.pop(popped_key, None) return (popped_value, ImmutableDict(new_items)) diff --git a/tox.ini b/tox.ini index 15d0702f8e538a5c4f57fd2a94a2505859507f17..394f961c9cf461ed145ea3cc2df876b7b9b10b56 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,10 @@ [tox] -minversion=4 -envlist=black,flake8,mypy,py3-{minimal,full-cover} +minversion = 4 +envlist = + black + flake8 + mypy + py3-{minimal,full-cover} [testenv] extras = @@ -14,6 +18,8 @@ commands = full: {envsitepackagesdir}/swh/model \ minimal: {envsitepackagesdir}/swh/model/tests/test_cli.py -m 'not requires_optional_deps' \ {posargs} +# --rootdir and --import-mode must NOT be used here due to the (hack-ish) way of +# executing tests (using tox-in-tox); see below [testenv:py3{,7,8,9,10,11,12,13},pypy3{,5,6,7,8,9,10,11,12,13}] skip_install = true @@ -25,7 +31,7 @@ commands = [testenv:black] skip_install = true deps = - black==22.10.0 + black==23.1.0 commands = {envpython} -m black --check swh @@ -42,7 +48,7 @@ commands = extras = testing deps = - mypy==1.0.1 + mypy>1.4 commands = mypy swh @@ -51,32 +57,14 @@ commands = # breaking doc build [testenv:sphinx] allowlist_externals = make -usedevelop = true extras = testing deps = - # fetch and install swh-docs in develop mode - -e git+https://gitlab.softwareheritage.org/swh/devel/swh-docs.git\#egg=swh.docs + # fetch and install swh-docs + git+https://gitlab.softwareheritage.org/swh/devel/swh-docs.git\#egg=swh.docs setenv = SWH_PACKAGE_DOC_TOX_BUILD = 1 # turn warnings into errors SPHINXOPTS = -W commands = - make -I ../.tox/sphinx/src/swh-docs/swh/ -C docs - -# build documentation only inside swh-environment using local state -# of swh-docs package -[testenv:sphinx-dev] -allowlist_externals = make -usedevelop = true -extras = - testing -deps = - # install swh-docs in develop mode - -e ../swh-docs -setenv = - SWH_PACKAGE_DOC_TOX_BUILD = 1 - # turn warnings into errors - SPHINXOPTS = -W -commands = - make -I ../.tox/sphinx-dev/src/swh-docs/swh/ -C docs + make -I {env_dir}/share/swh-docs -C docs