Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-ansible-compat for openSUSE:Factory checked in at 2022-06-23 10:23:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-ansible-compat (Old) and /work/SRC/openSUSE:Factory/.python-ansible-compat.new.1548 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ansible-compat" Thu Jun 23 10:23:39 2022 rev:4 rq:984255 version:2.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-ansible-compat/python-ansible-compat.changes 2022-05-30 12:44:19.800420844 +0200 +++ /work/SRC/openSUSE:Factory/.python-ansible-compat.new.1548/python-ansible-compat.changes 2022-06-23 10:23:59.707722043 +0200 @@ -1,0 +2,11 @@ +Tue Jun 14 21:02:38 UTC 2022 - Sebastian Wagner <sebix+novell....@sebix.at> + +- Update to version 2.1.0: + - Minor Changes + - Add module to work with schemas (#143) @ssbarnea + - Bugfixes + - Expose role_name_check in prepare_environment (#147) @zhan9san + - Install role in cache dir (#135) @zhan9san + - Prevent occasional FileExistsError with symlink recreation (#145) @ssbarnea + +------------------------------------------------------------------- Old: ---- ansible-compat-2.0.4.tar.gz New: ---- ansible-compat-2.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-ansible-compat.spec ++++++ --- /var/tmp/diff_new_pack.OiAti3/_old 2022-06-23 10:24:00.127722500 +0200 +++ /var/tmp/diff_new_pack.OiAti3/_new 2022-06-23 10:24:00.135722508 +0200 @@ -19,7 +19,7 @@ # only works with the python version which the package 'ansible' uses %define pythons python3 Name: python-ansible-compat -Version: 2.0.4 +Version: 2.1.0 Release: 0 Summary: Compatibility shim for Ansible 2.9 and newer License: MIT @@ -35,6 +35,7 @@ BuildRequires: %{python_module pytest} BuildRequires: %{python_module PyYAML} BuildRequires: %{python_module flaky} +BuildRequires: %{python_module jsonschema >= 4.5.1} BuildRequires: %{python_module pytest-mock} BuildRequires: %{python_module subprocess-tee} BuildRequires: ansible ++++++ ansible-compat-2.0.4.tar.gz -> ansible-compat-2.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/.github/CODEOWNERS new/ansible-compat-2.1.0/.github/CODEOWNERS --- old/ansible-compat-2.0.4/.github/CODEOWNERS 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/.github/CODEOWNERS 2022-05-23 18:11:08.000000000 +0200 @@ -1,2 +1 @@ -* @ssbarnea -* @webknjaz +* @ansible/devtools diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/.pre-commit-config.yaml new/ansible-compat-2.1.0/.pre-commit-config.yaml --- old/ansible-compat-2.0.4/.pre-commit-config.yaml 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/.pre-commit-config.yaml 2022-05-23 18:11:08.000000000 +0200 @@ -10,7 +10,6 @@ skip: # https://github.com/pre-commit-ci/issues/issues/55 - pip-compile - - pip-compile-docs default_language_version: # Needed in order to make pip-compile output predictable. python: python3.9 @@ -92,6 +91,7 @@ - subprocess-tee>=0.3.5 - types-PyYAML - types-pkg_resources + - types-jsonschema - repo: https://github.com/pycqa/pylint rev: v2.13.8 hooks: @@ -106,38 +106,20 @@ hooks: - id: pip-compile-upgrade # To run it execute: `pre-commit run pip-compile-upgrade --hook-stage manual` - name: Upgrade contraints files and requirements - files: ^(setup\.py|setup\.cfg|constraints\.txt)$ + name: Upgrade constraints files and requirements + files: ^(setup\.py|setup\.cfg|requirements\.txt)$ language: python - entry: python -m piptools compile --upgrade -q --extra test --output-file=constraints.txt setup.cfg - pass_filenames: false - stages: - - manual - additional_dependencies: - - pip-tools>=6.5.1 - - id: pip-compile-docs-upgrade - name: Upgrade contraints files and requirements for docs - files: ^(setup\.py|setup\.cfg|docs\/requirements\.(txt|in))$ - language: python - entry: python -m piptools compile --upgrade -q docs/requirements.in --output-file=docs/requirements.txt setup.cfg + entry: python -m piptools compile --upgrade -q --extra docs --extra test --output-file=requirements.txt setup.cfg pass_filenames: false stages: - manual additional_dependencies: - pip-tools>=6.5.1 - id: pip-compile - name: Check contraints files and requirements - files: ^(setup\.py|setup\.cfg|constraints\.txt)$ - language: python - entry: python -m piptools compile -q --extra test --output-file=constraints.txt setup.cfg - pass_filenames: false - additional_dependencies: - - pip-tools>=6.5.1 - - id: pip-compile-docs - name: Check contraints files and requirements for docs - files: ^(setup\.py|setup\.cfg|docs\/requirements\.(txt|in))$ + name: Check constraints files and requirements + files: ^(setup\.py|setup\.cfg|requirements\.txt)$ language: python - entry: python -m piptools compile -q docs/requirements.in --output-file=docs/requirements.txt setup.cfg + entry: python -m piptools compile -q --extra docs --extra test --output-file=requirements.txt setup.cfg pass_filenames: false additional_dependencies: - pip-tools>=6.5.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/.readthedocs.yml new/ansible-compat-2.1.0/.readthedocs.yml --- old/ansible-compat-2.0.4/.readthedocs.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible-compat-2.1.0/.readthedocs.yml 2022-05-23 18:11:08.000000000 +0200 @@ -0,0 +1,45 @@ +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html +# for details + +--- +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + # keep dirhtml for nice URLs without .html extension + builder: dirhtml + configuration: docs/conf.py + fail_on_warning: true + +# Build documentation with MkDocs +#mkdocs: +# configuration: mkdocs.yml +# fail_on_warning: true + +# Optionally build your docs in additional formats +# such as PDF and ePub +formats: [] + +submodules: + include: all # [] + exclude: [] + recursive: true + +build: + image: latest + +# Optionally set the version of Python and requirements required +# to build docs +python: + version: "3.8" + install: + # On https://readthedocs.org/dashboard/ansible-lint/environmentvariables/ we + # do have PIP_CONSTRAINTS=requirements.txt which ensures we install only + # pinned requirements that that we know to be working. + - method: pip + path: . + extra_requirements: + - docs + system_packages: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/PKG-INFO new/ansible-compat-2.1.0/PKG-INFO --- old/ansible-compat-2.0.4/PKG-INFO 2022-05-16 18:24:46.884977600 +0200 +++ new/ansible-compat-2.1.0/PKG-INFO 2022-05-23 18:11:29.260798700 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ansible-compat -Version: 2.0.4 +Version: 2.1.0 Summary: Ansible compatibility goodies Home-page: https://github.com/ansible-community/ansible-compat Author: Sorin Sbarnea @@ -35,6 +35,7 @@ Classifier: Topic :: Utilities Requires-Python: >=3.8 Description-Content-Type: text/markdown +Provides-Extra: docs Provides-Extra: test License-File: LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/constraints.txt new/ansible-compat-2.1.0/constraints.txt --- old/ansible-compat-2.0.4/constraints.txt 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/constraints.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,58 +0,0 @@ -# -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: -# -# pip-compile --extra=test --output-file=constraints.txt setup.cfg -# -attrs==21.4.0 - # via pytest -click==8.1.3 - # via pip-tools -commonmark==0.9.1 - # via pytest-markdown -coverage==6.3.3 - # via ansible-compat (setup.cfg) -flaky==3.7.0 - # via ansible-compat (setup.cfg) -iniconfig==1.1.1 - # via pytest -more-itertools==8.13.0 - # via pytest-plus -packaging==21.3 - # via pytest -pep517==0.12.0 - # via pip-tools -pip-tools==6.6.1 - # via ansible-compat (setup.cfg) -pluggy==1.0.0 - # via pytest -py==1.11.0 - # via pytest -pyparsing==3.0.9 - # via packaging -pytest==6.2.5 - # via - # ansible-compat (setup.cfg) - # pytest-markdown - # pytest-mock - # pytest-plus -pytest-markdown==1.0.2 - # via ansible-compat (setup.cfg) -pytest-mock==3.7.0 - # via ansible-compat (setup.cfg) -pytest-plus==0.2 - # via ansible-compat (setup.cfg) -pyyaml==6.0 - # via ansible-compat (setup.cfg) -subprocess-tee==0.3.5 - # via ansible-compat (setup.cfg) -toml==0.10.2 - # via pytest -tomli==2.0.1 - # via pep517 -wheel==0.37.1 - # via pip-tools - -# The following packages are considered to be unsafe in a requirements file: -# pip -# setuptools diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/docs/requirements.in new/ansible-compat-2.1.0/docs/requirements.in --- old/ansible-compat-2.0.4/docs/requirements.in 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/docs/requirements.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -sphinx-autobuild>=0.7.1,<1.0 -sphinx>=4.2.0,<5.0 -sphinx_ansible_theme -myst_parser diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/docs/requirements.txt new/ansible-compat-2.1.0/docs/requirements.txt --- old/ansible-compat-2.0.4/docs/requirements.txt 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/docs/requirements.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,110 +0,0 @@ -# -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: -# -# pip-compile --output-file=docs/requirements.txt docs/requirements.in setup.cfg -# -alabaster==0.7.12 - # via sphinx -ansible-pygments==0.1.1 - # via sphinx-ansible-theme -argh==0.26.2 - # via sphinx-autobuild -babel==2.10.1 - # via sphinx -certifi==2021.10.8 - # via requests -charset-normalizer==2.0.12 - # via requests -docutils==0.17.1 - # via - # myst-parser - # sphinx - # sphinx-rtd-theme -idna==3.3 - # via requests -imagesize==1.3.0 - # via sphinx -importlib-metadata==4.11.3 - # via sphinx -jinja2==3.1.2 - # via - # myst-parser - # sphinx -livereload==2.6.3 - # via sphinx-autobuild -markdown-it-py==2.1.0 - # via - # mdit-py-plugins - # myst-parser -markupsafe==2.1.1 - # via jinja2 -mdit-py-plugins==0.3.0 - # via myst-parser -mdurl==0.1.1 - # via markdown-it-py -myst-parser==0.17.2 - # via -r docs/requirements.in -packaging==21.3 - # via sphinx -pathtools==0.1.2 - # via sphinx-autobuild -port-for==0.3.1 - # via sphinx-autobuild -pygments==2.12.0 - # via - # ansible-pygments - # sphinx -pyparsing==3.0.9 - # via packaging -pytz==2022.1 - # via babel -pyyaml==6.0 - # via - # ansible-compat (setup.cfg) - # myst-parser - # sphinx-autobuild -requests==2.27.1 - # via sphinx -six==1.16.0 - # via livereload -snowballstemmer==2.2.0 - # via sphinx -sphinx==4.5.0 - # via - # -r docs/requirements.in - # myst-parser - # sphinx-ansible-theme - # sphinx-rtd-theme -sphinx-ansible-theme==0.9.1 - # via -r docs/requirements.in -sphinx-autobuild==0.7.1 - # via -r docs/requirements.in -sphinx-rtd-theme==1.0.0 - # via sphinx-ansible-theme -sphinxcontrib-applehelp==1.0.2 - # via sphinx -sphinxcontrib-devhelp==1.0.2 - # via sphinx -sphinxcontrib-htmlhelp==2.0.0 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==1.0.3 - # via sphinx -sphinxcontrib-serializinghtml==1.1.5 - # via sphinx -subprocess-tee==0.3.5 - # via ansible-compat (setup.cfg) -tornado==6.1 - # via - # livereload - # sphinx-autobuild -typing-extensions==4.2.0 - # via myst-parser -urllib3==1.26.9 - # via requests -watchdog==2.1.8 - # via sphinx-autobuild -zipp==3.8.0 - # via importlib-metadata diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/requirements.txt new/ansible-compat-2.1.0/requirements.txt --- old/ansible-compat-2.0.4/requirements.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible-compat-2.1.0/requirements.txt 2022-05-23 18:11:08.000000000 +0200 @@ -0,0 +1,162 @@ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# pip-compile --extra=docs --extra=test --output-file=requirements.txt setup.cfg +# +alabaster==0.7.12 + # via sphinx +ansible-pygments==0.1.1 + # via sphinx-ansible-theme +argh==0.26.2 + # via sphinx-autobuild +attrs==21.4.0 + # via + # jsonschema + # pytest +babel==2.10.1 + # via sphinx +certifi==2022.5.18.1 + # via requests +charset-normalizer==2.0.12 + # via requests +click==8.1.3 + # via pip-tools +commonmark==0.9.1 + # via pytest-markdown +coverage==6.3.3 + # via ansible-compat (setup.cfg) +docutils==0.17.1 + # via + # myst-parser + # sphinx + # sphinx-rtd-theme +flaky==3.7.0 + # via ansible-compat (setup.cfg) +idna==3.3 + # via requests +imagesize==1.3.0 + # via sphinx +importlib-metadata==4.11.3 + # via sphinx +iniconfig==1.1.1 + # via pytest +jinja2==3.1.2 + # via + # myst-parser + # sphinx +jsonschema==4.5.1 + # via ansible-compat (setup.cfg) +livereload==2.6.3 + # via sphinx-autobuild +markdown-it-py==2.1.0 + # via + # mdit-py-plugins + # myst-parser +markupsafe==2.1.1 + # via jinja2 +mdit-py-plugins==0.3.0 + # via myst-parser +mdurl==0.1.1 + # via markdown-it-py +more-itertools==8.13.0 + # via pytest-plus +myst-parser==0.17.2 + # via ansible-compat (setup.cfg) +packaging==21.3 + # via + # pytest + # sphinx +pathtools==0.1.2 + # via sphinx-autobuild +pep517==0.12.0 + # via pip-tools +pip-tools==6.6.1 + # via ansible-compat (setup.cfg) +pluggy==1.0.0 + # via pytest +port-for==0.3.1 + # via sphinx-autobuild +py==1.11.0 + # via pytest +pygments==2.12.0 + # via + # ansible-pygments + # sphinx +pyparsing==3.0.9 + # via packaging +pyrsistent==0.18.1 + # via jsonschema +pytest==6.2.5 + # via + # ansible-compat (setup.cfg) + # pytest-markdown + # pytest-mock + # pytest-plus +pytest-markdown==1.0.2 + # via ansible-compat (setup.cfg) +pytest-mock==3.7.0 + # via ansible-compat (setup.cfg) +pytest-plus==0.2 + # via ansible-compat (setup.cfg) +pytz==2022.1 + # via babel +pyyaml==6.0 + # via + # ansible-compat (setup.cfg) + # myst-parser + # sphinx-autobuild +requests==2.27.1 + # via sphinx +six==1.16.0 + # via livereload +snowballstemmer==2.2.0 + # via sphinx +sphinx==4.5.0 + # via + # ansible-compat (setup.cfg) + # myst-parser + # sphinx-ansible-theme + # sphinx-rtd-theme +sphinx-ansible-theme==0.9.1 + # via ansible-compat (setup.cfg) +sphinx-autobuild==0.7.1 + # via ansible-compat (setup.cfg) +sphinx-rtd-theme==1.0.0 + # via sphinx-ansible-theme +sphinxcontrib-applehelp==1.0.2 + # via sphinx +sphinxcontrib-devhelp==1.0.2 + # via sphinx +sphinxcontrib-htmlhelp==2.0.0 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.3 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 + # via sphinx +subprocess-tee==0.3.5 + # via ansible-compat (setup.cfg) +toml==0.10.2 + # via pytest +tomli==2.0.1 + # via pep517 +tornado==6.1 + # via + # livereload + # sphinx-autobuild +typing-extensions==4.2.0 + # via myst-parser +urllib3==1.26.9 + # via requests +watchdog==2.1.8 + # via sphinx-autobuild +wheel==0.37.1 + # via pip-tools +zipp==3.8.0 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/setup.cfg new/ansible-compat-2.1.0/setup.cfg --- old/ansible-compat-2.0.4/setup.cfg 2022-05-16 18:24:46.884977600 +0200 +++ new/ansible-compat-2.1.0/setup.cfg 2022-05-23 18:11:29.260798700 +0200 @@ -56,8 +56,14 @@ install_requires = PyYAML subprocess-tee >= 0.3.5 + jsonschema >= 4.5.1 [options.extras_require] +docs = + sphinx-autobuild>=0.7.1,<1.0 + sphinx>=4.2.0,<5.0 + sphinx_ansible_theme + myst_parser test = coverage flaky diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/src/ansible_compat/runtime.py new/ansible-compat-2.1.0/src/ansible_compat/runtime.py --- old/ansible-compat-2.0.4/src/ansible_compat/runtime.py 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/src/ansible_compat/runtime.py 2022-05-23 18:11:08.000000000 +0200 @@ -302,6 +302,7 @@ retry: bool = False, install_local: bool = False, offline: bool = False, + role_name_check: int = 0, ) -> None: """Make dependencies available if needed.""" if required_collections is None: @@ -342,7 +343,9 @@ self.install_collection_from_disk("../..", destination=destination) else: # no collection, try to recognize and install a standalone role - self._install_galaxy_role(self.project_dir, ignore_errors=True) + self._install_galaxy_role( + self.project_dir, role_name_check=role_name_check, ignore_errors=True + ) def require_collection( # noqa: C901 self, @@ -447,6 +450,20 @@ if roles_path != self.config.default_roles_path: self._update_env("ANSIBLE_ROLES_PATH", roles_path) + def _get_roles_path(self) -> pathlib.Path: + """Return roles installation path. + + If `self.isolated` is set to `True`, `self.cache_dir` would be + created, then it returns the `self.cache_dir/roles`. When `self.isolated` is + not mentioned or set to `False`, it returns the first path in + `default_roles_path`. + """ + if self.cache_dir: + path = pathlib.Path(f"{self.cache_dir}/roles") + else: + path = pathlib.Path(os.path.expanduser(self.config.default_roles_path[0])) + return path + def _install_galaxy_role( self, project_dir: str, role_name_check: int = 0, ignore_errors: bool = False ) -> None: @@ -495,16 +512,19 @@ fqrn = f"{role_namespace}{role_name}" else: fqrn = pathlib.Path(project_dir).absolute().name - path = pathlib.Path(os.path.expanduser(self.config.default_roles_path[0])) + path = self._get_roles_path() path.mkdir(parents=True, exist_ok=True) link_path = path / fqrn # despite documentation stating that is_file() reports true for symlinks, # it appears that is_dir() reports true instead, so we rely on exists(). target = pathlib.Path(project_dir).absolute() - exists = link_path.exists() or link_path.is_symlink() - if not exists or os.readlink(link_path) != str(target): - if link_path.exists(): - link_path.unlink() + if not link_path.exists() or ( + link_path.is_symlink() and os.readlink(link_path) != str(target) + ): + # must call unlink before checking exists because a broken + # link reports as not existing and we want to repair it + link_path.unlink(missing_ok=True) + # https://github.com/python/cpython/issues/73843 link_path.symlink_to(str(target), target_is_directory=True) _logger.info( "Using %s symlink to current repository in order to enable Ansible to find the role using its expected full name.", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/src/ansible_compat/schema.py new/ansible-compat-2.1.0/src/ansible_compat/schema.py --- old/ansible-compat-2.0.4/src/ansible_compat/schema.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible-compat-2.1.0/src/ansible_compat/schema.py 2022-05-23 18:11:08.000000000 +0200 @@ -0,0 +1,128 @@ +"""Utils for JSON Schema validation.""" +import json +from dataclasses import dataclass +from typing import Any, Deque, Dict, List, Mapping, Union + +import jsonschema +from jsonschema.validators import validator_for + + +def to_path(schema_path: Deque[str]) -> str: + """Flatten a path to a dot delimited string. + + :param schema_path: The schema path + :returns: The dot delimited path + """ + return ".".join(str(index) for index in schema_path) + + +def json_path(absolute_path: Deque[str]) -> str: + """Flatten a data path to a dot delimited string. + + :param absolute_path: The path + :returns: The dot delimited string + """ + path = "$" + for elem in absolute_path: + if isinstance(elem, int): + path += "[" + str(elem) + "]" + else: + path += "." + elem + return path + + +@dataclass +class JsonSchemaError: + # pylint: disable=too-many-instance-attributes + """Data structure to hold a json schema validation error.""" + + message: str + data_path: str + json_path: str + schema_path: str + relative_schema: str + expected: Union[bool, int, str] + validator: str + found: str + + @property + def _hash_key(self) -> Any: + # line attr is knowingly excluded, as dict is not hashable + return ( + self.schema_path, + self.data_path, + self.json_path, + self.message, + self.expected, + ) + + def __hash__(self) -> int: + """Return a hash value of the instance.""" + return hash(self._hash_key) + + def __eq__(self, other: object) -> bool: + """Identify whether the other object represents the same rule match.""" + if not isinstance(other, self.__class__): + return NotImplemented + return self.__hash__() == other.__hash__() + + def __lt__(self, other: object) -> bool: + """Return whether the current object is less than the other.""" + if not isinstance(other, self.__class__): + return NotImplemented + return bool(self._hash_key < other._hash_key) + + def to_friendly(self) -> str: + """Provide a friendly explanation of the error. + + :returns: The error message + """ + return f"In '{self.data_path}': {self.message}." + + +def validate( + schema: Union[str, Mapping[str, Any]], data: Dict[str, Any] +) -> List[JsonSchemaError]: + """Validate some data against a JSON schema. + + :param schema: the JSON schema to use for validation + :param data: The data to validate + :returns: Any errors encountered + """ + errors: List[JsonSchemaError] = [] + + if isinstance(schema, str): + schema = json.loads(schema) + try: + if not isinstance(schema, Mapping): + raise jsonschema.SchemaError("Invalid schema, must be a mapping") + validator = validator_for(schema) + validator.check_schema(schema) + except jsonschema.SchemaError as exc: + error = JsonSchemaError( + message=str(exc), + data_path="schema sanity check", + json_path="", + schema_path="", + relative_schema="", + expected="", + validator="", + found="", + ) + errors.append(error) + return errors + + for validation_error in validator(schema).iter_errors(data): + if isinstance(validation_error, jsonschema.ValidationError): + error = JsonSchemaError( + message=validation_error.message, + data_path=to_path(validation_error.absolute_path), + json_path=json_path(validation_error.absolute_path), + schema_path=to_path(validation_error.schema_path), + relative_schema=validation_error.schema, + expected=validation_error.validator_value, + validator=validation_error.validator, + found=str(validation_error.instance), + ) + errors.append(error) + return sorted(errors) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/src/ansible_compat.egg-info/PKG-INFO new/ansible-compat-2.1.0/src/ansible_compat.egg-info/PKG-INFO --- old/ansible-compat-2.0.4/src/ansible_compat.egg-info/PKG-INFO 2022-05-16 18:24:46.000000000 +0200 +++ new/ansible-compat-2.1.0/src/ansible_compat.egg-info/PKG-INFO 2022-05-23 18:11:28.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ansible-compat -Version: 2.0.4 +Version: 2.1.0 Summary: Ansible compatibility goodies Home-page: https://github.com/ansible-community/ansible-compat Author: Sorin Sbarnea @@ -35,6 +35,7 @@ Classifier: Topic :: Utilities Requires-Python: >=3.8 Description-Content-Type: text/markdown +Provides-Extra: docs Provides-Extra: test License-File: LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/src/ansible_compat.egg-info/SOURCES.txt new/ansible-compat-2.1.0/src/ansible_compat.egg-info/SOURCES.txt --- old/ansible-compat-2.0.4/src/ansible_compat.egg-info/SOURCES.txt 2022-05-16 18:24:46.000000000 +0200 +++ new/ansible-compat-2.1.0/src/ansible_compat.egg-info/SOURCES.txt 2022-05-23 18:11:29.000000000 +0200 @@ -2,13 +2,14 @@ .gitignore .pre-commit-config.yaml .pylintrc +.readthedocs.yml .yamllint LICENSE README.md codecov.yml -constraints.txt mypy.ini pyproject.toml +requirements.txt setup.cfg tox.ini .github/CODEOWNERS @@ -21,8 +22,6 @@ docs/conf.py docs/examples.md docs/index.md -docs/requirements.in -docs/requirements.txt examples/reqs_v1/requirements.yml examples/reqs_v2/requirements.yml src/ansible_compat/__init__.py @@ -34,6 +33,7 @@ src/ansible_compat/prerun.py src/ansible_compat/py.typed src/ansible_compat/runtime.py +src/ansible_compat/schema.py src/ansible_compat.egg-info/PKG-INFO src/ansible_compat.egg-info/SOURCES.txt src/ansible_compat.egg-info/dependency_links.txt @@ -48,6 +48,7 @@ test/test_prerun.py test/test_runtime.py test/test_runtime_example.py +test/test_schema.py test/assets/requirements-invalid-collection.yml test/assets/requirements-invalid-role.yml test/collections/acme.broken/galaxy.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/src/ansible_compat.egg-info/requires.txt new/ansible-compat-2.1.0/src/ansible_compat.egg-info/requires.txt --- old/ansible-compat-2.0.4/src/ansible_compat.egg-info/requires.txt 2022-05-16 18:24:46.000000000 +0200 +++ new/ansible-compat-2.1.0/src/ansible_compat.egg-info/requires.txt 2022-05-23 18:11:29.000000000 +0200 @@ -1,5 +1,12 @@ PyYAML subprocess-tee>=0.3.5 +jsonschema>=4.5.1 + +[docs] +sphinx-autobuild<1.0,>=0.7.1 +sphinx<5.0,>=4.2.0 +sphinx_ansible_theme +myst_parser [test] coverage diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/test/test_runtime.py new/ansible-compat-2.1.0/test/test_runtime.py --- old/ansible-compat-2.0.4/test/test_runtime.py 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/test/test_runtime.py 2022-05-23 18:11:08.000000000 +0200 @@ -134,6 +134,12 @@ result = runtime.exec(["ansible-galaxy", "list"]) assert result.returncode == 0, result assert role_name in result.stdout + if isolated: + assert pathlib.Path(f"{runtime.cache_dir}/roles/{role_name}").is_symlink() + else: + assert pathlib.Path( + f"{os.path.expanduser(runtime.config.default_roles_path[0])}/{role_name}" + ).is_symlink() runtime.clean() # also test that clean does not break when cache_dir is missing tmp_dir = runtime.cache_dir @@ -505,6 +511,36 @@ runtime_tmp._install_galaxy_role(runtime_tmp.project_dir, role_name_check=1) +@pytest.mark.parametrize( + "galaxy_info", + ( + """galaxy_info: + role_name: foo-bar + namespace: acme +""", + """galaxy_info: + role_name: foo-bar +""", + ), + ids=("bad-name", "bad-name-without-namespace"), +) +def test_install_galaxy_role_name_role_name_check_equals_to_1( + runtime_tmp: Runtime, + galaxy_info: str, + caplog: pytest.LogCaptureFixture, +) -> None: + """Check install role with bad role name in galaxy info.""" + caplog.set_level(logging.WARN) + pathlib.Path(f"{runtime_tmp.project_dir}/meta").mkdir() + pathlib.Path(f"{runtime_tmp.project_dir}/meta/main.yml").write_text( + galaxy_info, + encoding="utf-8", + ) + + runtime_tmp._install_galaxy_role(runtime_tmp.project_dir, role_name_check=1) + assert "Computed fully qualified role name of " in caplog.text + + def test_install_galaxy_role_no_checks(runtime_tmp: Runtime) -> None: """Check install role with bad namespace in galaxy info.""" runtime_tmp.prepare_environment() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/test/test_schema.py new/ansible-compat-2.1.0/test/test_schema.py --- old/ansible-compat-2.0.4/test/test_schema.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible-compat-2.1.0/test/test_schema.py 2022-05-23 18:11:08.000000000 +0200 @@ -0,0 +1,48 @@ +"""Tests for schema utilities.""" +from ansible_compat.schema import JsonSchemaError, validate + +schema = { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "environment": {"type": "object", "additionalProperties": {"type": "string"}} + }, +} + +instance = {"environment": {"a": False, "b": True, "c": "foo"}} + +expected_results = [ + JsonSchemaError( + message="False is not of type 'string'", + data_path="environment.a", + json_path="$.environment.a", + schema_path="properties.environment.additionalProperties.type", + relative_schema='{"type": "string"}', + expected="string", + validator="type", + found="False", + ), + JsonSchemaError( + message="True is not of type 'string'", + data_path="environment.b", + json_path="$.environment.b", + schema_path="properties.environment.additionalProperties.type", + relative_schema='{"type": "string"}', + expected="string", + validator="type", + found="True", + ), +] + + +def test_schema() -> None: + """Test the schema validator.""" + results = validate(schema=schema, data=instance) + # ensure we produce consistent results between runs + for _ in range(1, 100): + new_results = validate(schema=schema, data=instance) + assert results == new_results, "inconsistent returns" + # print(result) + assert len(results) == len(expected_results) + assert sorted(results) == results, "multiple errors not sorted" + for i, result in enumerate(results): + assert result == expected_results[i] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible-compat-2.0.4/tox.ini new/ansible-compat-2.1.0/tox.ini --- old/ansible-compat-2.0.4/tox.ini 2022-05-16 18:24:27.000000000 +0200 +++ new/ansible-compat-2.1.0/tox.ini 2022-05-23 18:11:08.000000000 +0200 @@ -50,9 +50,9 @@ setenv = COVERAGE_FILE = {env:COVERAGE_FILE:{toxworkdir}/.coverage.{envname}} PIP_DISABLE_PIP_VERSION_CHECK = 1 - PIP_CONSTRAINT = {toxinidir}/constraints.txt + PIP_CONSTRAINT = {toxinidir}/requirements.txt PRE_COMMIT_COLOR = always - PYTEST_REQPASS = 75 + PYTEST_REQPASS = 78 FORCE_COLOR = 1 allowlist_externals = ansible @@ -75,7 +75,7 @@ PRE_COMMIT_HOME [testenv:deps] -description = Bump all test depeendencies +description = Bump all test dependencies basepython = {[testenv:lint]basepython} envdir = {toxworkdir}/lint deps = {[testenv:lint]deps} @@ -123,6 +123,5 @@ -d "{toxworkdir}/doctree" \ docs/ "{toxworkdir}/html" deps = - -r docs/requirements.txt - --editable . + --editable .[docs] passenv = *