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 2025-01-27 20:58:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ansible-compat (Old)
and /work/SRC/openSUSE:Factory/.python-ansible-compat.new.2316 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ansible-compat"
Mon Jan 27 20:58:41 2025 rev:32 rq:1240616 version:25.1.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-ansible-compat/python-ansible-compat.changes
2025-01-16 18:34:40.451293450 +0100
+++
/work/SRC/openSUSE:Factory/.python-ansible-compat.new.2316/python-ansible-compat.changes
2025-01-27 20:59:32.117221143 +0100
@@ -1,0 +2,12 @@
+Mon Jan 27 16:42:57 UTC 2025 - Johannes Kastl
<[email protected]>
+
+- update to 25.1.0:
+ * Major
+ - Inject venv site-packages at the top of collection path (test
+ isolation) (#447) @ssbarnea
+ - Fail if old ANSIBLE_COLLECTIONS_PATHS is detected (#449)
+ @ssbarnea
+ * Bugfixes
+ - Patch #449 to use ANSIBLE_COLLECTIONS_PATH (#450) @ssbarnea
+
+-------------------------------------------------------------------
Old:
----
python-ansible-compat-25.0.0.tar.gz
New:
----
python-ansible-compat-25.1.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-ansible-compat.spec ++++++
--- /var/tmp/diff_new_pack.isAllz/_old 2025-01-27 20:59:32.597240928 +0100
+++ /var/tmp/diff_new_pack.isAllz/_new 2025-01-27 20:59:32.597240928 +0100
@@ -24,7 +24,7 @@
%endif
Name: python-ansible-compat
-Version: 25.0.0
+Version: 25.1.0
Release: 0
Summary: Compatibility shim for Ansible 2.9 and newer
License: MIT
@@ -96,6 +96,8 @@
# tests that need network connectivity
IGNORED_CHECKS="${IGNORED_CHECKS} or test_scan_sys_path[0]"
IGNORED_CHECKS="${IGNORED_CHECKS} or test_scan_sys_path[1]"
+IGNORED_CHECKS="${IGNORED_CHECKS} or test_scan_sys_path[disabled]"
+IGNORED_CHECKS="${IGNORED_CHECKS} or test_scan_sys_path[enabled]"
# Disable checks on test names:
https://github.com/pytest-dev/pytest-plus#user-content-avoiding-problematic-test-identifiers
https://github.com/ansible/ansible-compat/issues/340
export PYTEST_CHECK_TEST_ID_REGEX=0
%pytest -k "not (${IGNORED_CHECKS})"
++++++ python-ansible-compat-25.0.0.tar.gz ->
python-ansible-compat-25.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/.config/constraints.txt
new/ansible-compat-25.1.0/.config/constraints.txt
--- old/ansible-compat-25.0.0/.config/constraints.txt 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/.config/constraints.txt 2025-01-27
17:15:25.000000000 +0100
@@ -1,7 +1,7 @@
# This file was autogenerated by uv via the following command:
# tox run deps
argparse-manpage==4.6 # via ansible-compat (pyproject.toml)
-attrs==24.3.0 # via jsonschema, referencing
+attrs==25.1.0 # via jsonschema, referencing
babel==2.16.0 # via mkdocs-material
beautifulsoup4==4.12.3 # via linkchecker, mkdocs-htmlproofer-plugin
black==24.10.0 # via ansible-compat (pyproject.toml)
@@ -20,7 +20,7 @@
dnspython==2.7.0 # via linkchecker
exceptiongroup==1.2.2 # via pytest
ghp-import==2.1.0 # via mkdocs
-griffe==1.5.4 # via mkdocstrings-python
+griffe==1.5.5 # via mkdocstrings-python
hjson==3.1.0 # via mkdocs-macros-plugin, super-collections
htmlmin2==0.1.13 # via mkdocs-minify-plugin
idna==3.10 # via requests
@@ -37,12 +37,12 @@
mergedeep==1.3.4 # via mkdocs, mkdocs-get-deps
mkdocs==1.6.1 # via mkdocs-ansible, mkdocs-autorefs,
mkdocs-gen-files, mkdocs-htmlproofer-plugin, mkdocs-macros-plugin,
mkdocs-material, mkdocs-minify-plugin, mkdocs-monorepo-plugin, mkdocstrings
mkdocs-ansible==24.12.0 # via ansible-compat (pyproject.toml)
-mkdocs-autorefs==1.2.0 # via mkdocstrings, mkdocstrings-python
+mkdocs-autorefs==1.3.0 # via mkdocstrings, mkdocstrings-python
mkdocs-gen-files==0.5.0 # via mkdocs-ansible
mkdocs-get-deps==0.2.0 # via mkdocs
mkdocs-htmlproofer-plugin==1.3.0 # via mkdocs-ansible
mkdocs-macros-plugin==1.3.7 # via mkdocs-ansible
-mkdocs-material==9.5.49 # via mkdocs-ansible
+mkdocs-material==9.5.50 # via mkdocs-ansible
mkdocs-material-extensions==1.3.1 # via mkdocs-ansible, mkdocs-material
mkdocs-minify-plugin==0.8.0 # via mkdocs-ansible
mkdocs-monorepo-plugin==1.1.0 # via mkdocs-ansible
@@ -57,7 +57,7 @@
pluggy==1.5.0 # via pytest
pycparser==2.22 # via cffi
pygments==2.19.1 # via mkdocs-material
-pymdown-extensions==10.14 # via markdown-exec, mkdocs-ansible,
mkdocs-material, mkdocstrings
+pymdown-extensions==10.14.1 # via markdown-exec, mkdocs-ansible,
mkdocs-material, mkdocstrings
pytest==8.3.4 # via pytest-instafail, pytest-mock, pytest-plus,
ansible-compat (pyproject.toml)
pytest-instafail==0.5.0 # via ansible-compat (pyproject.toml)
pytest-mock==3.14.0 # via ansible-compat (pyproject.toml)
@@ -66,7 +66,7 @@
python-slugify==8.0.4 # via mkdocs-monorepo-plugin
pyyaml==6.0.2 # via ansible-core, mkdocs, mkdocs-get-deps,
mkdocs-macros-plugin, pymdown-extensions, pyyaml-env-tag, ansible-compat
(pyproject.toml)
pyyaml-env-tag==0.1 # via mkdocs
-referencing==0.35.1 # via jsonschema, jsonschema-specifications
+referencing==0.36.2 # via jsonschema, jsonschema-specifications
regex==2024.11.6 # via mkdocs-material
requests==2.32.3 # via linkchecker, mkdocs-htmlproofer-plugin,
mkdocs-material
rpds-py==0.22.3 # via jsonschema, referencing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/.config/pydoclint-baseline.txt
new/ansible-compat-25.1.0/.config/pydoclint-baseline.txt
--- old/ansible-compat-25.0.0/.config/pydoclint-baseline.txt 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/.config/pydoclint-baseline.txt 2025-01-27
17:15:25.000000000 +0100
@@ -1,21 +1,18 @@
src/ansible_compat/config.py
- DOC201: Function `ansible_collections_path` does not have a return section
in docstring
DOC101: Function `parse_ansible_version`: Docstring contains fewer
arguments than in function signature.
DOC103: Function `parse_ansible_version`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [stdout: str].
DOC201: Function `parse_ansible_version` does not have a return section in
docstring
DOC501: Function `parse_ansible_version` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Function `parse_ansible_version` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
+ DOC503: Function `parse_ansible_version` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
DOC101: Function `ansible_version`: Docstring contains fewer arguments
than in function signature.
DOC103: Function `ansible_version`: Docstring arguments are different from
function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [version: str].
DOC201: Function `ansible_version` does not have a return section in
docstring
DOC501: Function `ansible_version` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Function `ansible_version` exceptions in the "Raises" section in
the docstring do not match those in the function body Raises values in the
docstring: []. Raised exceptions in the body: ['MissingAnsibleError'].
- DOC601: Class `AnsibleConfig`: Class docstring contains fewer class
attributes than actual class attributes. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
- DOC603: Class `AnsibleConfig`: Class docstring attributes are different
from actual class attributes. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Attributes in the class definition but not in the docstring: [_aliases: ,
action_warnings: bool, agnostic_become_prompt: bool,
allow_world_readable_tmpfiles: bool, ansible_connection_path: str | None,
ansible_cow_acceptlist: list[str], ansible_cow_path: str | None,
ansible_cow_selection: str, ansible_force_color: bool, ansible_nocolor: bool,
ansible_nocows: bool, ansible_pipelining: bool, any_errors_fatal: bool,
become_allow_same_user: bool, become_plugin_path: list[str], cache_plugin: str,
cache_plugin_connection: str | None, cache_plugin_prefix: str,
cache_plugin_timeout: int, callable_accept_list: list[str], callbacks_enabled:
list[str], collections_on_ansible_version_mismatch: Literal['warning',
'ignore'], collections_paths: list[str], collections_scan_sys_path: boo
l, color_changed: str, color_console_prompt: str, color_debug: str,
color_deprecate: str, color_diff_add: str, color_diff_lines: str,
color_diff_remove: str, color_error: str, color_highlight: str, color_ok: str,
color_skip: str, color_unreachable: str, color_verbose: str, color_warn: str,
command_warnings: bool, conditional_bare_vars: bool, connection_facts_modules:
dict[str, str], controller_python_warning: bool, coverage_remote_output: str |
None, coverage_remote_paths: list[str], default_action_plugin_path: list[str],
default_allow_unsafe_lookups: bool, default_ask_pass: bool,
default_ask_vault_pass: bool, default_become: bool, default_become_ask_pass:
bool, default_become_exe: str | None, default_become_flags: str,
default_become_method: str, default_become_user: str,
default_cache_plugin_path: list[str], default_callback_plugin_path: list[str],
default_cliconf_plugin_path: list[str], default_collections_path: list[str],
default_connection_plugin_path: list[str], default_debug:
bool, default_executable: str, default_fact_path: str | None,
default_filter_plugin_path: list[str], default_force_handlers: bool,
default_forks: int, default_gather_subset: list[str], default_gather_timeout:
int, default_gathering: Literal['smart', 'explicit', 'implicit'],
default_handler_includes_static: bool, default_hash_behaviour: str,
default_host_list: list[str], default_httpapi_plugin_path: list[str],
default_internal_poll_interval: float, default_inventory_plugin_path:
list[str], default_jinja2_extensions: list[str], default_jinja2_native: bool,
default_keep_remote_files: bool, default_libvirt_lxc_noseclabel: bool,
default_load_callback_plugins: bool, default_local_tmp: str,
default_log_filter: list[str], default_log_path: str | None,
default_lookup_lugin_path: list[str], default_managed_str: str,
default_module_args: str, default_module_compression: str, default_module_name:
str, default_module_path: list[str], default_module_utils_path: list[str],
default_netconf_plugin_
path: list[str], default_no_log: bool, default_no_target_syslog: bool,
default_null_representation: str | None, default_poll_interval: int,
default_private_key_file: str | None, default_private_role_vars: bool,
default_remote_port: str | None, default_remote_user: str | None,
default_roles_path: list[str], default_selinux_special_fs: list[str],
default_stdout_callback: str, default_strategy: str,
default_strategy_plugin_path: list[str], default_su: bool,
default_syslog_facility: str, default_task_includes_static: bool,
default_terminal_plugin_path: list[str], default_test_plugin_path: list[str],
default_timeout: int, default_transport: str, default_undefined_var_behavior:
bool, default_vars_plugin_path: list[str], default_vault_encrypt_identity: str
| None, default_vault_id_match: bool, default_vault_identity: str,
default_vault_identity_list: list[str], default_vault_password_file: str |
None, default_verbosity: int, deprecation_warnings: bool, devel_warning: bool,
diff_always: boo
l, diff_context: int, display_args_to_stdout: bool, display_skipped_hosts:
bool, doc_fragment_plugin_path: list[str], docsite_root_url: str,
duplicate_yaml_dict_key: Literal['warn', 'error', 'ignore'],
enable_task_debugger: bool, error_on_missing_handler: bool, facts_modules:
list[str], galaxy_cache_dir: str, galaxy_display_progress: str | None,
galaxy_ignore_certs: bool, galaxy_role_skeleton: str | None,
galaxy_role_skeleton_ignore: list[str], galaxy_server: str, galaxy_server_list:
str | None, galaxy_token_path: str, host_key_checking: bool,
host_pattern_mismatch: Literal['warning', 'error', 'ignore'],
inject_facts_as_vars: bool, interpreter_python: str,
interpreter_python_distro_map: dict[str, str], interpreter_python_fallback:
list[str], invalid_task_attribute_failed: bool,
inventory_any_unparsed_is_failed: bool, inventory_cache_enabled: bool,
inventory_cache_plugin: str | None, inventory_cache_plugin_connection: str |
None, inventory_cache_plugin_prefix: str, inventory_cache_ti
meout: int, inventory_enabled: list[str], inventory_export: bool,
inventory_ignore_exts: str, inventory_ignore_patterns: list[str],
inventory_unparsed_is_failed: bool, localhost_warning: bool,
max_file_size_for_diff: int, module_ignore_exts: str, netconf_ssh_config: str |
None, network_group_modules: list[str], old_plugin_cache_clearing: bool,
paramiko_host_key_auto_add: bool, paramiko_look_for_keys: bool,
persistent_command_timeout: int, persistent_connect_retry_timeout: int,
persistent_connect_timeout: int, persistent_control_path_dir: str,
playbook_dir: str | None, playbook_vars_root: Literal['top', 'bottom', 'all'],
plugin_filters_cfg: str | None, python_module_rlimit_nofile: int,
retry_files_enabled: bool, retry_files_save_path: str | None, run_vars_plugins:
str, show_custom_stats: bool, string_conversion_action: Literal['warn',
'error', 'ignore'], string_type_filters: list[str], system_warnings: bool,
tags_run: list[str], tags_skip: list[str], task_debugger_ignore_errors: bool
, task_timeout: int, transform_invalid_group_chars: Literal['always', 'never',
'ignore', 'silently'], use_persistent_connections: bool,
variable_plugins_enabled: list[str], variable_precedence: list[str],
verbose_to_stderr: bool, win_async_startup_timeout: int,
worker_shutdown_poll_count: int, worker_shutdown_poll_delay: float,
yaml_filename_extensions: list[str]]. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
+ DOC503: Function `ansible_version` exceptions in the "Raises" section in
the docstring do not match those in the function body. Raised exceptions in the
docstring: []. Raised exceptions in the body: ['MissingAnsibleError'].
+ DOC604: Class `AnsibleConfig`: Attributes are the same in docstring and
class def, but are in a different order. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
+ DOC605: Class `AnsibleConfig`: Attribute names match, but type hints in
these attributes do not match: action_warnings, agnostic_become_prompt,
allow_world_readable_tmpfiles, ansible_connection_path, ansible_cow_acceptlist,
ansible_cow_path, ansible_cow_selection, ansible_force_color, ansible_nocolor,
ansible_nocows, ansible_pipelining, any_errors_fatal, become_allow_same_user,
become_plugin_path, cache_plugin, cache_plugin_connection, cache_plugin_prefix,
cache_plugin_timeout, callable_accept_list, callbacks_enabled,
collections_on_ansible_version_mismatch, collections_paths,
collections_scan_sys_path, color_changed, color_console_prompt, color_debug,
color_deprecate, color_diff_add, color_diff_lines, color_diff_remove,
color_error, color_highlight, color_ok, color_skip, color_unreachable,
color_verbose, color_warn, command_warnings, conditional_bare_vars,
connection_facts_modules, controller_python_warning, coverage_remote_output,
coverage_remote_paths, default_action_plugin_p
ath, default_allow_unsafe_lookups, default_ask_pass, default_ask_vault_pass,
default_become, default_become_ask_pass, default_become_exe,
default_become_flags, default_become_method, default_become_user,
default_cache_plugin_path, default_callback_plugin_path,
default_cliconf_plugin_path, default_connection_plugin_path, default_debug,
default_executable, default_fact_path, default_filter_plugin_path,
default_force_handlers, default_forks, default_gather_subset,
default_gather_timeout, default_gathering, default_handler_includes_static,
default_hash_behaviour, default_host_list, default_httpapi_plugin_path,
default_internal_poll_interval, default_inventory_plugin_path,
default_jinja2_extensions, default_jinja2_native, default_keep_remote_files,
default_libvirt_lxc_noseclabel, default_load_callback_plugins,
default_local_tmp, default_log_filter, default_log_path,
default_lookup_plugin_path, default_managed_str, default_module_args,
default_module_compression, default_module_name, defa
ult_module_path, default_module_utils_path, default_netconf_plugin_path,
default_no_log, default_no_target_syslog, default_null_representation,
default_poll_interval, default_private_key_file, default_private_role_vars,
default_remote_port, default_remote_user, default_collections_path,
default_roles_path, default_selinux_special_fs, default_stdout_callback,
default_strategy, default_strategy_plugin_path, default_su,
default_syslog_facility, default_task_includes_static,
default_terminal_plugin_path, default_test_plugin_path, default_timeout,
default_transport, default_undefined_var_behavior, default_vars_plugin_path,
default_vault_encrypt_identity, default_vault_id_match, default_vault_identity,
default_vault_identity_list, default_vault_password_file, default_verbosity,
deprecation_warnings, devel_warning, diff_always, diff_context,
display_args_to_stdout, display_skipped_hosts, docsite_root_url,
doc_fragment_plugin_path, duplicate_yaml_dict_key, enable_task_debugger,
error_on_mis
sing_handler, facts_modules, galaxy_cache_dir, galaxy_display_progress,
galaxy_ignore_certs, galaxy_role_skeleton, galaxy_role_skeleton_ignore,
galaxy_server, galaxy_server_list, galaxy_token_path, host_key_checking,
host_pattern_mismatch, inject_facts_as_vars, interpreter_python,
interpreter_python_distro_map, interpreter_python_fallback,
invalid_task_attribute_failed, inventory_any_unparsed_is_failed,
inventory_cache_enabled, inventory_cache_plugin,
inventory_cache_plugin_connection, inventory_cache_plugin_prefix,
inventory_cache_timeout, inventory_enabled, inventory_export,
inventory_ignore_exts, inventory_ignore_patterns, inventory_unparsed_is_failed,
localhost_warning, max_file_size_for_diff, module_ignore_exts,
netconf_ssh_config, network_group_modules, old_plugin_cache_clearing,
paramiko_host_key_auto_add, paramiko_look_for_keys, persistent_command_timeout,
persistent_connect_retry_timeout, persistent_connect_timeout,
persistent_control_path_dir, playbook_dir, playbook_vars_r
oot, plugin_filters_cfg, python_module_rlimit_nofile, retry_files_enabled,
retry_files_save_path, run_vars_plugins, show_custom_stats,
string_conversion_action, string_type_filters, system_warnings, tags_run,
tags_skip, task_debugger_ignore_errors, task_timeout,
transform_invalid_group_chars, use_persistent_connections,
variable_plugins_enabled, variable_precedence, verbose_to_stderr,
win_async_startup_timeout, worker_shutdown_poll_count,
worker_shutdown_poll_delay, yaml_filename_extensions (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
DOC101: Method `AnsibleConfig.__init__`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `AnsibleConfig.__init__`: Docstring arguments are different
from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [cache_dir: Path
| None, config_dump: str | None, data: dict[str, object] | None].
- DOC501: Method `AnsibleConfig.__init__` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Method `AnsibleConfig.__init__` exceptions in the "Raises" section
in the docstring do not match those in the function body Raises values in the
docstring: []. Raised exceptions in the body: ['RuntimeError'].
DOC101: Method `AnsibleConfig.__getattribute__`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `AnsibleConfig.__getattribute__`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [attr_name: str].
DOC201: Method `AnsibleConfig.__getattribute__` does not have a return
section in docstring
@@ -49,7 +46,7 @@
DOC103: Function `colpath_from_path`: Docstring arguments are different
from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [path: Path].
DOC201: Function `colpath_from_path` does not have a return section in
docstring
DOC501: Function `colpath_from_path` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Function `colpath_from_path` exceptions in the "Raises" section in
the docstring do not match those in the function body Raises values in the
docstring: []. Raised exceptions in the body: ['InvalidPrerequisiteError'].
+ DOC503: Function `colpath_from_path` exceptions in the "Raises" section in
the docstring do not match those in the function body. Raised exceptions in the
docstring: []. Raised exceptions in the body: ['InvalidPrerequisiteError'].
--------------------
src/ansible_compat/runtime.py
DOC601: Class `Collection`: Class docstring contains fewer class
attributes than actual class attributes. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
@@ -62,26 +59,26 @@
DOC103: Method `Plugins.__getattribute__`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [attr: str].
DOC201: Method `Plugins.__getattribute__` does not have a return section
in docstring
DOC501: Method `Plugins.__getattribute__` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Method `Plugins.__getattribute__` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body: ['AnsibleCompatError'].
+ DOC503: Method `Plugins.__getattribute__` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['AnsibleCompatError'].
DOC601: Class `Runtime`: Class docstring contains fewer class attributes
than actual class attributes. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
DOC603: Class `Runtime`: Class docstring attributes are different from
actual class attributes. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Attributes in the class definition but not in the docstring:
[_has_playbook_cache: dict[tuple[str, Path | None], bool], _version: Version |
None, cache_dir: Path, collections: OrderedDict[str, Collection], initialized:
bool, plugins: Plugins, require_module: bool]. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
DOC101: Method `Runtime.__init__`: Docstring contains fewer arguments than
in function signature.
DOC103: Method `Runtime.__init__`: Docstring arguments are different from
function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [environ:
dict[str, str] | None, isolated: bool, max_retries: int, min_required_version:
str | None, project_dir: Path | None, require_module: bool, verbosity: int].
DOC501: Method `Runtime.__init__` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Method `Runtime.__init__` exceptions in the "Raises" section in
the docstring do not match those in the function body Raises values in the
docstring: []. Raised exceptions in the body: ['RuntimeError'].
+ DOC503: Method `Runtime.__init__` exceptions in the "Raises" section in
the docstring do not match those in the function body. Raised exceptions in the
docstring: []. Raised exceptions in the body: ['RuntimeError'].
DOC101: Function `warning`: Docstring contains fewer arguments than in
function signature.
DOC103: Function `warning`: Docstring arguments are different from
function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [formatted: bool,
msg: str, self: Display].
DOC101: Method `Runtime.initialize_logger`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `Runtime.initialize_logger`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [level: int].
DOC501: Method `Runtime.load_collections` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Method `Runtime.load_collections` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body: ['RuntimeError',
'TypeError'].
+ DOC503: Method `Runtime.load_collections` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['RuntimeError', 'TypeError'].
DOC501: Method `Runtime._ensure_module_available` has "raise" statements,
but the docstring does not have a "Raises" section
- DOC503: Method `Runtime._ensure_module_available` exceptions in the
"Raises" section in the docstring do not match those in the function body
Raises values in the docstring: []. Raised exceptions in the body:
['RuntimeError'].
+ DOC503: Method `Runtime._ensure_module_available` exceptions in the
"Raises" section in the docstring do not match those in the function body.
Raised exceptions in the docstring: []. Raised exceptions in the body:
['RuntimeError'].
DOC101: Method `Runtime.run`: Docstring contains fewer arguments than in
function signature.
DOC103: Method `Runtime.run`: Docstring arguments are different from
function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [args: str |
list[str], cwd: Path | None, env: dict[str, str] | None, retry: bool, set_acp:
bool, tee: bool].
DOC201: Method `Runtime.run` does not have a return section in docstring
DOC501: Method `Runtime.version` has "raise" statements, but the docstring
does not have a "Raises" section
- DOC503: Method `Runtime.version` exceptions in the "Raises" section in the
docstring do not match those in the function body Raises values in the
docstring: []. Raised exceptions in the body: ['MissingAnsibleError'].
+ DOC503: Method `Runtime.version` exceptions in the "Raises" section in the
docstring do not match those in the function body. Raised exceptions in the
docstring: []. Raised exceptions in the body: ['MissingAnsibleError'].
DOC101: Method `Runtime.version_in_range`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `Runtime.version_in_range`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [lower: str |
None, upper: str | None].
DOC201: Method `Runtime.version_in_range` does not have a return section
in docstring
@@ -91,22 +88,22 @@
DOC101: Method `Runtime.install_collection`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `Runtime.install_collection`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [collection: str
| Path, destination: Path | None, force: bool].
DOC501: Method `Runtime.install_collection` has "raise" statements, but
the docstring does not have a "Raises" section
- DOC503: Method `Runtime.install_collection` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
+ DOC503: Method `Runtime.install_collection` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
DOC101: Method `Runtime.install_collection_from_disk`: Docstring contains
fewer arguments than in function signature.
DOC103: Method `Runtime.install_collection_from_disk`: Docstring arguments
are different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [destination:
Path | None, path: Path].
DOC101: Method `Runtime.install_requirements`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `Runtime.install_requirements`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [offline: bool,
requirement: Path, retry: bool].
DOC501: Method `Runtime.install_requirements` has "raise" statements, but
the docstring does not have a "Raises" section
- DOC503: Method `Runtime.install_requirements` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body: ['AnsibleCommandError',
'InvalidPrerequisiteError'].
+ DOC503: Method `Runtime.install_requirements` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['AnsibleCommandError', 'InvalidPrerequisiteError'].
DOC101: Method `Runtime.prepare_environment`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `Runtime.prepare_environment`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [install_local:
bool, offline: bool, required_collections: dict[str, str] | None, retry: bool,
role_name_check: int].
DOC501: Method `Runtime.require_collection` has "raise" statements, but
the docstring does not have a "Raises" section
- DOC503: Method `Runtime.require_collection` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
+ DOC503: Method `Runtime.require_collection` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
DOC501: Method `Runtime._prepare_ansible_paths` has "raise" statements,
but the docstring does not have a "Raises" section
- DOC503: Method `Runtime._prepare_ansible_paths` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body: ['RuntimeError'].
+ DOC503: Method `Runtime._prepare_ansible_paths` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['RuntimeError'].
DOC201: Method `Runtime._get_roles_path` does not have a return section in
docstring
DOC501: Method `Runtime._install_galaxy_role` has "raise" statements, but
the docstring does not have a "Raises" section
- DOC503: Method `Runtime._install_galaxy_role` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
+ DOC503: Method `Runtime._install_galaxy_role` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['InvalidPrerequisiteError'].
DOC101: Method `Runtime._update_env`: Docstring contains fewer arguments
than in function signature.
DOC103: Method `Runtime._update_env`: Docstring arguments are different
from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [default: str,
value: list[str], varname: str].
DOC101: Function `_get_role_fqrn`: Docstring contains fewer arguments than
in function signature.
@@ -116,7 +113,7 @@
DOC103: Function `_get_galaxy_role_ns`: Docstring arguments are different
from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [galaxy_infos:
dict[str, Any]].
DOC201: Function `_get_galaxy_role_ns` does not have a return section in
docstring
DOC501: Function `_get_galaxy_role_ns` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Function `_get_galaxy_role_ns` exceptions in the "Raises" section
in the docstring do not match those in the function body Raises values in the
docstring: []. Raised exceptions in the body: ['AnsibleCompatError'].
+ DOC503: Function `_get_galaxy_role_ns` exceptions in the "Raises" section
in the docstring do not match those in the function body. Raised exceptions in
the docstring: []. Raised exceptions in the body: ['AnsibleCompatError'].
DOC101: Function `_get_galaxy_role_name`: Docstring contains fewer
arguments than in function signature.
DOC103: Function `_get_galaxy_role_name`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [galaxy_infos:
dict[str, Any]].
DOC201: Function `_get_galaxy_role_name` does not have a return section in
docstring
@@ -130,12 +127,12 @@
DOC601: Class `JsonSchemaError`: Class docstring contains fewer class
attributes than actual class attributes. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
DOC603: Class `JsonSchemaError`: Class docstring attributes are different
from actual class attributes. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Attributes in the class definition but not in the docstring: [data_path: str,
expected: bool | int | str, found: str, json_path: str, message: str,
relative_schema: str, schema_path: str, validator: str]. (Please read
https://jsh9.github.io/pydoclint/checking_class_attributes.html on how to
correctly document class attributes.)
DOC201: Method `JsonSchemaError.to_friendly` does not have a return
section in docstring
- DOC001: Function/method `validate`: Potential formatting errors in
docstring. Error message: Expected a colon in 'SchemaError if the schema is
invalid'.
+ DOC001: Function/method `validate`: Potential formatting errors in
docstring. Error message: Expected a colon in 'SchemaError if the schema is
invalid'. (Note: DOC001 could trigger other unrelated violations under this
function/method too. Please fix the docstring formatting first.)
DOC101: Function `validate`: Docstring contains fewer arguments than in
function signature.
DOC103: Function `validate`: Docstring arguments are different from
function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [data: JSON,
schema: JSON].
DOC201: Function `validate` does not have a return section in docstring
DOC501: Function `validate` has "raise" statements, but the docstring does
not have a "Raises" section
- DOC503: Function `validate` exceptions in the "Raises" section in the
docstring do not match those in the function body Raises values in the
docstring: []. Raised exceptions in the body: ['jsonschema.SchemaError'].
+ DOC503: Function `validate` exceptions in the "Raises" section in the
docstring do not match those in the function body. Raised exceptions in the
docstring: []. Raised exceptions in the body: ['jsonschema.SchemaError'].
--------------------
test/conftest.py
DOC101: Function `runtime`: Docstring contains fewer arguments than in
function signature.
@@ -157,7 +154,7 @@
DOC201: Method `VirtualEnvironment.python_script_run` does not have a
return section in docstring
DOC201: Method `VirtualEnvironment.site_package_dirs` does not have a
return section in docstring
DOC501: Method `VirtualEnvironment.site_package_dirs` has "raise"
statements, but the docstring does not have a "Raises" section
- DOC503: Method `VirtualEnvironment.site_package_dirs` exceptions in the
"Raises" section in the docstring do not match those in the function body
Raises values in the docstring: []. Raised exceptions in the body:
['TypeError'].
+ DOC503: Method `VirtualEnvironment.site_package_dirs` exceptions in the
"Raises" section in the docstring do not match those in the function body.
Raised exceptions in the docstring: []. Raised exceptions in the body:
['TypeError'].
DOC101: Function `venv_module`: Docstring contains fewer arguments than in
function signature.
DOC103: Function `venv_module`: Docstring arguments are different from
function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring:
[tmp_path_factory: pytest.TempPathFactory].
DOC201: Function `venv_module` does not have a return section in docstring
@@ -165,8 +162,6 @@
test/test_config.py
DOC101: Function `test_ansible_version_missing`: Docstring contains fewer
arguments than in function signature.
DOC103: Function `test_ansible_version_missing`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [monkeypatch:
MonkeyPatch].
- DOC101: Function `test_ansible_collections_path_env`: Docstring contains
fewer arguments than in function signature.
- DOC103: Function `test_ansible_collections_path_env`: Docstring arguments
are different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [monkeypatch:
MonkeyPatch, var: str].
--------------------
test/test_runtime.py
DOC101: Function `test_runtime_version`: Docstring contains fewer
arguments than in function signature.
@@ -178,7 +173,7 @@
DOC101: Method `RaiseException.__init__`: Docstring contains fewer
arguments than in function signature.
DOC103: Method `RaiseException.__init__`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [**kwargs: Any,
*args: Any].
DOC501: Method `RaiseException.__init__` has "raise" statements, but the
docstring does not have a "Raises" section
- DOC503: Method `RaiseException.__init__` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body: ['ModuleNotFoundError'].
+ DOC503: Method `RaiseException.__init__` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['ModuleNotFoundError'].
DOC101: Function `test_runtime_mismatch_ansible_module`: Docstring
contains fewer arguments than in function signature.
DOC103: Function `test_runtime_mismatch_ansible_module`: Docstring
arguments are different from function arguments. (Or could be other formatting
issues: https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103
). Arguments in the function signature but not in the docstring: [monkeypatch:
MonkeyPatch].
DOC101: Function `test_runtime_version_fail_module`: Docstring contains
fewer arguments than in function signature.
@@ -230,7 +225,7 @@
DOC101: Function `test_install_collection_dest`: Docstring contains fewer
arguments than in function signature.
DOC103: Function `test_install_collection_dest`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [runtime:
Runtime, tmp_path: pathlib.Path].
DOC501: Function `test_install_collection_dest` has "raise" statements,
but the docstring does not have a "Raises" section
- DOC503: Function `test_install_collection_dest` exceptions in the "Raises"
section in the docstring do not match those in the function body Raises values
in the docstring: []. Raised exceptions in the body: ['AssertionError'].
+ DOC503: Function `test_install_collection_dest` exceptions in the "Raises"
section in the docstring do not match those in the function body. Raised
exceptions in the docstring: []. Raised exceptions in the body:
['AssertionError'].
DOC101: Function `test_install_collection_fail`: Docstring contains fewer
arguments than in function signature.
DOC103: Function `test_install_collection_fail`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [runtime:
Runtime].
DOC101: Function `test_install_galaxy_role`: Docstring contains fewer
arguments than in function signature.
@@ -277,6 +272,8 @@
DOC103: Function `test_is_url`: Docstring arguments are different from
function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [name: str,
result: bool].
DOC101: Function `test_prepare_environment_symlink`: Docstring contains
fewer arguments than in function signature.
DOC103: Function `test_prepare_environment_symlink`: Docstring arguments
are different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [caplog:
pytest.LogCaptureFixture, dest: str | Path, message: str].
+ DOC101: Function `test_runtime_exception`: Docstring contains fewer
arguments than in function signature.
+ DOC103: Function `test_runtime_exception`: Docstring arguments are
different from function arguments. (Or could be other formatting issues:
https://jsh9.github.io/pydoclint/violation_codes.html#notes-on-doc103 ).
Arguments in the function signature but not in the docstring: [monkeypatch:
pytest.MonkeyPatch].
--------------------
test/test_schema.py
DOC101: Function `json_from_asset`: Docstring contains fewer arguments
than in function signature.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/.git_archival.txt
new/ansible-compat-25.1.0/.git_archival.txt
--- old/ansible-compat-25.0.0/.git_archival.txt 2025-01-12 21:15:20.000000000
+0100
+++ new/ansible-compat-25.1.0/.git_archival.txt 2025-01-27 17:15:25.000000000
+0100
@@ -1,4 +1,4 @@
-node: 4db0011d8fc2c093255ef673e5bf8388832407e5
-node-date: 2025-01-12T20:15:20Z
-describe-name: v25.0.0
-ref-names: HEAD -> main, tag: v25.0.0
+node: 83c5cfbc78480382a6e8f194d0e83129e4d0f2c2
+node-date: 2025-01-27T21:45:25+05:30
+describe-name: v25.1.0
+ref-names: HEAD -> main, tag: v25.1.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/.pre-commit-config.yaml
new/ansible-compat-25.1.0/.pre-commit-config.yaml
--- old/ansible-compat-25.0.0/.pre-commit-config.yaml 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/.pre-commit-config.yaml 2025-01-27
17:15:25.000000000 +0100
@@ -19,7 +19,7 @@
)$
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: "v0.8.6"
+ rev: "v0.9.2"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
@@ -54,13 +54,16 @@
- id: debug-statements
language_version: python3
- repo: https://github.com/codespell-project/codespell
- rev: v2.3.0
+ rev: v2.4.0
hooks:
- id: codespell
- repo: https://github.com/jsh9/pydoclint
- rev: 0.5.9
+ rev: 0.6.0
hooks:
- id: pydoclint
+ # This allows automatic reduction of the baseline file when needed.
+ entry: sh -ec "pydoclint . && pydoclint --generate-baseline=1 ."
+ pass_filenames: false
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.35.1
hooks:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/pyproject.toml
new/ansible-compat-25.1.0/pyproject.toml
--- old/ansible-compat-25.0.0/pyproject.toml 2025-01-12 21:15:20.000000000
+0100
+++ new/ansible-compat-25.1.0/pyproject.toml 2025-01-27 17:15:25.000000000
+0100
@@ -88,8 +88,7 @@
baseline = ".config/pydoclint-baseline.txt"
check-return-types = false
check-yield-types = false
-exclude = '\.cache|\.git|\.tox|build|out|venv'
-quiet = true # no need to print out the files being checked
+exclude = '\.ansible|\.cache|\.git|\.tox|build|ansible_collections|out|venv'
should-document-private-class-attributes = true
show-filenames-in-every-violation-message = true
skip-checking-short-docstrings = false
@@ -350,7 +349,7 @@
]
[tool.pytest.ini_options]
-addopts = "-p no:pytest_cov --durations=10 --durations-min=1.0 --failed-first"
+addopts = "-p no:pytest_cov --durations=10 --durations-min=1.0 --failed-first
--instafail"
# ensure we treat warnings as error
filterwarnings = [
"error",
@@ -369,6 +368,9 @@
docstring-code-format = true
[tool.ruff.lint]
+external = [
+ "DOC" # pydoclint
+]
ignore = [
# Disabled on purpose:
"CPY001",
@@ -405,8 +407,11 @@
"PLR0917",
"S101",
"S404",
+ "S603", # subprocess
+ "S607", # subprocess
"SLF001"
]
+"tools/*.py" = ["S603"]
[tool.ruff.lint.pydocstyle]
convention = "google"
@@ -439,10 +444,4 @@
[tool.uv.pip]
annotation-style = "line"
custom-compile-command = "tox run deps"
-no-emit-package = [
- "ansible-core",
- "pip",
- "resolvelib",
- "typing_extensions",
- "uv"
-]
+no-emit-package = ["ansible-core", "pip", "resolvelib", "typing_extensions",
"uv"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/src/ansible_compat/config.py
new/ansible-compat-25.1.0/src/ansible_compat/config.py
--- old/ansible-compat-25.0.0/src/ansible_compat/config.py 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/src/ansible_compat/config.py 2025-01-27
17:15:25.000000000 +0100
@@ -20,18 +20,6 @@
from pathlib import Path
-# do not use lru_cache here, as environment can change between calls
-def ansible_collections_path() -> str:
- """Return collection path variable for current version of Ansible."""
- for env_var in [
- "ANSIBLE_COLLECTIONS_PATH",
- "ANSIBLE_COLLECTIONS_PATHS",
- ]:
- if env_var in os.environ:
- return env_var
- return "ANSIBLE_COLLECTIONS_PATH"
-
-
def parse_ansible_version(stdout: str) -> Version:
"""Parse output of 'ansible --version'."""
# Ansible can produce extra output before displaying version in debug mode.
@@ -71,10 +59,206 @@
return parse_ansible_version(proc.stdout)
-class AnsibleConfig(UserDict[str, object]): # pylint:
disable=too-many-ancestors
+class AnsibleConfig(
+ UserDict[str, object],
+): # pylint: disable=too-many-ancestors # noqa: DOC605
"""Interface to query Ansible configuration.
This should allow user to access everything provided by `ansible-config
dump` without having to parse the data himself.
+
+ Attributes:
+ _aliases:
+ action_warnings:
+ agnostic_become_prompt:
+ allow_world_readable_tmpfiles:
+ ansible_connection_path:
+ ansible_cow_acceptlist:
+ ansible_cow_path:
+ ansible_cow_selection:
+ ansible_force_color:
+ ansible_nocolor:
+ ansible_nocows:
+ ansible_pipelining:
+ any_errors_fatal:
+ become_allow_same_user:
+ become_plugin_path:
+ cache_plugin:
+ cache_plugin_connection:
+ cache_plugin_prefix:
+ cache_plugin_timeout:
+ callable_accept_list:
+ callbacks_enabled:
+ collections_on_ansible_version_mismatch:
+ collections_paths:
+ collections_scan_sys_path:
+ color_changed:
+ color_console_prompt:
+ color_debug:
+ color_deprecate:
+ color_diff_add:
+ color_diff_lines:
+ color_diff_remove:
+ color_error:
+ color_highlight:
+ color_ok:
+ color_skip:
+ color_unreachable:
+ color_verbose:
+ color_warn:
+ command_warnings:
+ conditional_bare_vars:
+ connection_facts_modules:
+ controller_python_warning:
+ coverage_remote_output:
+ coverage_remote_paths:
+ default_action_plugin_path:
+ default_allow_unsafe_lookups:
+ default_ask_pass:
+ default_ask_vault_pass:
+ default_become:
+ default_become_ask_pass:
+ default_become_exe:
+ default_become_flags:
+ default_become_method:
+ default_become_user:
+ default_cache_plugin_path:
+ default_callback_plugin_path:
+ default_cliconf_plugin_path:
+ default_collections_path:
+ default_connection_plugin_path:
+ default_debug:
+ default_executable:
+ default_fact_path:
+ default_filter_plugin_path:
+ default_force_handlers:
+ default_forks:
+ default_gather_subset:
+ default_gather_timeout:
+ default_gathering:
+ default_handler_includes_static:
+ default_hash_behaviour:
+ default_host_list:
+ default_httpapi_plugin_path:
+ default_internal_poll_interval:
+ default_inventory_plugin_path:
+ default_jinja2_extensions:
+ default_jinja2_native:
+ default_keep_remote_files:
+ default_libvirt_lxc_noseclabel:
+ default_load_callback_plugins:
+ default_local_tmp:
+ default_log_filter:
+ default_log_path:
+ default_lookup_plugin_path:
+ default_managed_str:
+ default_module_args:
+ default_module_compression:
+ default_module_name:
+ default_module_path:
+ default_module_utils_path:
+ default_netconf_plugin_path:
+ default_no_log:
+ default_no_target_syslog:
+ default_null_representation:
+ default_poll_interval:
+ default_private_key_file:
+ default_private_role_vars:
+ default_remote_port:
+ default_remote_user:
+ default_roles_path:
+ default_selinux_special_fs:
+ default_stdout_callback:
+ default_strategy:
+ default_strategy_plugin_path:
+ default_su:
+ default_syslog_facility:
+ default_task_includes_static:
+ default_terminal_plugin_path:
+ default_test_plugin_path:
+ default_timeout:
+ default_transport:
+ default_undefined_var_behavior:
+ default_vars_plugin_path:
+ default_vault_encrypt_identity:
+ default_vault_id_match:
+ default_vault_identity:
+ default_vault_identity_list:
+ default_vault_password_file:
+ default_verbosity:
+ deprecation_warnings:
+ devel_warning:
+ diff_always:
+ diff_context:
+ display_args_to_stdout:
+ display_skipped_hosts:
+ doc_fragment_plugin_path:
+ docsite_root_url:
+ duplicate_yaml_dict_key:
+ enable_task_debugger:
+ error_on_missing_handler:
+ facts_modules:
+ galaxy_cache_dir:
+ galaxy_display_progress:
+ galaxy_ignore_certs:
+ galaxy_role_skeleton:
+ galaxy_role_skeleton_ignore:
+ galaxy_server:
+ galaxy_server_list:
+ galaxy_token_path:
+ host_key_checking:
+ host_pattern_mismatch:
+ inject_facts_as_vars:
+ interpreter_python:
+ interpreter_python_distro_map:
+ interpreter_python_fallback:
+ invalid_task_attribute_failed:
+ inventory_any_unparsed_is_failed:
+ inventory_cache_enabled:
+ inventory_cache_plugin:
+ inventory_cache_plugin_connection:
+ inventory_cache_plugin_prefix:
+ inventory_cache_timeout:
+ inventory_enabled:
+ inventory_export:
+ inventory_ignore_exts:
+ inventory_ignore_patterns:
+ inventory_unparsed_is_failed:
+ localhost_warning:
+ max_file_size_for_diff:
+ module_ignore_exts:
+ netconf_ssh_config:
+ network_group_modules:
+ old_plugin_cache_clearing:
+ paramiko_host_key_auto_add:
+ paramiko_look_for_keys:
+ persistent_command_timeout:
+ persistent_connect_retry_timeout:
+ persistent_connect_timeout:
+ persistent_control_path_dir:
+ playbook_dir:
+ playbook_vars_root:
+ plugin_filters_cfg:
+ python_module_rlimit_nofile:
+ retry_files_enabled:
+ retry_files_save_path:
+ run_vars_plugins:
+ show_custom_stats:
+ string_conversion_action:
+ string_type_filters:
+ system_warnings:
+ tags_run:
+ tags_skip:
+ task_debugger_ignore_errors:
+ task_timeout:
+ transform_invalid_group_chars:
+ use_persistent_connections:
+ variable_plugins_enabled:
+ variable_precedence:
+ verbose_to_stderr:
+ win_async_startup_timeout:
+ worker_shutdown_poll_count:
+ worker_shutdown_poll_delay:
+ yaml_filename_extensions:
"""
_aliases = {
@@ -169,9 +353,9 @@
]
default_force_handlers: bool = False
default_forks: int = 5
- default_gathering: Literal["smart", "explicit", "implicit"] = "smart"
default_gather_subset: list[str] = ["all"]
default_gather_timeout: int = 10
+ default_gathering: Literal["smart", "explicit", "implicit"] = "smart"
default_handler_includes_static: bool = False
default_hash_behaviour: str = "replace"
default_host_list: list[str] = ["/etc/ansible/hosts"]
@@ -192,7 +376,7 @@
default_local_tmp: str = "~/.ansible/tmp"
default_log_filter: list[str] = []
default_log_path: str | None = None
- default_lookup_lugin_path: list[str] = [
+ default_lookup_plugin_path: list[str] = [
"~/.ansible/plugins/lookup",
"/usr/share/ansible/plugins/lookup",
]
@@ -263,9 +447,9 @@
"/usr/share/ansible/plugins/vars",
]
default_vault_encrypt_identity: str | None = None
+ default_vault_id_match: bool = False
default_vault_identity: str = "default"
default_vault_identity_list: list[str] = []
- default_vault_id_match: bool = False
default_vault_password_file: str | None = None
default_verbosity: int = 0
deprecation_warnings: bool = False
@@ -430,17 +614,6 @@
self[key] = ast.literal_eval(value)
except (NameError, SyntaxError, ValueError):
self[key] = value
- # inject isolation collections paths into the config
- if self.cache_dir:
- cpaths = self.data["COLLECTIONS_PATHS"]
- if cpaths and isinstance(cpaths, list):
- cpaths.insert(
- 0,
- f"{self.cache_dir}/collections",
- )
- else: # pragma: no cover
- msg = f"Unexpected data type for COLLECTIONS_PATHS: {cpaths}"
- raise RuntimeError(msg)
if data:
return
@@ -477,7 +650,6 @@
__all__ = [
"AnsibleConfig",
- "ansible_collections_path",
"ansible_version",
"parse_ansible_version",
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/src/ansible_compat/runtime.py
new/ansible-compat-25.1.0/src/ansible_compat/runtime.py
--- old/ansible-compat-25.0.0/src/ansible_compat/runtime.py 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/src/ansible_compat/runtime.py 2025-01-27
17:15:25.000000000 +0100
@@ -11,6 +11,7 @@
import os
import re
import shutil
+import site
import subprocess # noqa: S404
import sys
import warnings
@@ -24,7 +25,6 @@
from ansible_compat.config import (
AnsibleConfig,
- ansible_collections_path,
parse_ansible_version,
)
from ansible_compat.constants import (
@@ -195,6 +195,9 @@
self.isolated = isolated
self.max_retries = max_retries
self.environ = environ or os.environ.copy()
+ if "ANSIBLE_COLLECTIONS_PATHS" in self.environ:
+ msg = "ANSIBLE_COLLECTIONS_PATHS was detected, replace it with
ANSIBLE_COLLECTIONS_PATH to continue."
+ raise RuntimeError(msg)
self.plugins = Plugins(runtime=self)
self.verbosity = verbosity
@@ -214,7 +217,7 @@
self.config = AnsibleConfig(cache_dir=self.cache_dir)
# Add the sys.path to the collection paths if not isolated
- self._add_sys_path_to_collection_paths()
+ self._patch_collection_paths()
if not self.version_in_range(lower=min_required_version):
msg = f"Found incompatible version of ansible runtime
{self.version}, instead of {min_required_version} or newer."
@@ -259,17 +262,43 @@
# Use module-level _logger instance to validate it
_logger.debug("Logging initialized to level %s", logging_level)
- def _add_sys_path_to_collection_paths(self) -> None:
- """Add the sys.path to the collection paths."""
+ def _patch_collection_paths(self) -> None:
+ """Modify Ansible collection path for testing purposes.
+
+ - Add the sys.path to the end of collection paths.
+ - Add the site-packages to the beginning of collection paths to match
+ ansible-core and ade behavior and trick ansible-galaxy to install
+ default to the venv site-packages location (isolation).
+ """
+ collections_paths: list[str] = self.config.collections_paths.copy()
if self.config.collections_scan_sys_path:
for path in sys.path:
if (
- path not in self.config.collections_paths
+ path not in collections_paths
and (Path(path) / "ansible_collections").is_dir()
):
- self.config.collections_paths.append( # pylint:
disable=E1101
+ collections_paths.append( # pylint: disable=E1101
path,
)
+ # When inside a venv, we also add the site-packages to the top of
the
+ # collections path because this is the first place where
ansible-core
+ # will look for them. This also ensures that when calling
ansible-galaxy
+ # to install content, it will be installed in the venv
site-packages instead
+ # of altering the user configuration. Matches behavior of ADE and
+ # ensures isolation.
+ for path in reversed(site.getsitepackages()):
+ if path not in collections_paths:
+ collections_paths.insert(0, path)
+
+ if collections_paths != self.config.collections_paths:
+ _logger.info(
+ "Collection paths was patch to include extra directories
%s",
+ ",".join(collections_paths),
+ )
+ else:
+ msg = "ANSIBLE_COLLECTIONS_SCAN_SYS_PATH is disabled, not patching
collection paths. This may lead to unexpected behavior when using dev tools and
prevent full isolation from user environment."
+ _logger.warning(msg)
+ self.config.collections_paths = collections_paths
def load_collections(self) -> None:
"""Load collection data."""
@@ -505,7 +534,7 @@
cpaths: list[str] = self.config.collections_paths
if destination and str(destination) not in cpaths:
# we cannot use '-p' because it breaks galaxy ability to ignore
already installed collections, so
- # we hack ansible_collections_path instead and inject our own path
there.
+ # we hack ANSIBLE_COLLECTIONS_PATH instead and inject our own path
there.
# pylint: disable=no-member
cpaths.insert(0, str(destination))
cmd.append(f"{collection}")
@@ -514,7 +543,7 @@
process = self.run(
cmd,
retry=True,
- env={**self.environ, ansible_collections_path(): ":".join(cpaths)},
+ env={**self.environ, "ANSIBLE_COLLECTIONS_PATH": ":".join(cpaths)},
)
if process.returncode != 0:
msg = f"Command {' '.join(cmd)}, returned {process.returncode}
code:\n{process.stdout}\n{process.stderr}"
@@ -822,7 +851,7 @@
if library_paths != self.config.DEFAULT_MODULE_PATH:
self._update_env("ANSIBLE_LIBRARY", library_paths)
if collections_path != self.config.default_collections_path:
- self._update_env(ansible_collections_path(), collections_path)
+ self._update_env("ANSIBLE_COLLECTIONS_PATH", collections_path)
if roles_path != self.config.default_roles_path:
self._update_env("ANSIBLE_ROLES_PATH", roles_path)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/test/test_config.py
new/ansible-compat-25.1.0/test/test_config.py
--- old/ansible-compat-25.0.0/test/test_config.py 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/test/test_config.py 2025-01-27
17:15:25.000000000 +0100
@@ -9,7 +9,6 @@
from ansible_compat.config import (
AnsibleConfig,
- ansible_collections_path,
ansible_version,
parse_ansible_version,
)
@@ -90,17 +89,3 @@
def test_ansible_version_arg() -> None:
"""Validate ansible_version behavior."""
assert ansible_version("2.0") >= Version("1.0")
-
-
[email protected](
- "var",
- ("", "ANSIBLE_COLLECTIONS_PATH", "ANSIBLE_COLLECTIONS_PATHS"),
- ids=["blank", "singular", "plural"],
-)
-def test_ansible_collections_path_env(var: str, monkeypatch: MonkeyPatch) ->
None:
- """Test that ansible_collections_path returns the appropriate env var."""
- # Set the variable
- if var:
- monkeypatch.setenv(var, "")
-
- assert ansible_collections_path() == (var or "ANSIBLE_COLLECTIONS_PATH")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/test/test_runtime.py
new/ansible-compat-25.1.0/test/test_runtime.py
--- old/ansible-compat-25.0.0/test/test_runtime.py 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/test/test_runtime.py 2025-01-27
17:15:25.000000000 +0100
@@ -401,7 +401,7 @@
def test_require_collection_wrong_version(runtime: Runtime) -> None:
"""Tests behaviour of require_collection."""
- subprocess.check_output( # noqa: S603
+ subprocess.check_output(
[
"ansible-galaxy",
"collection",
@@ -1030,3 +1030,13 @@
assert not runtime.has_playbook("this-does-not-exist.yml", basedir=Path())
# this is part of community.molecule collection
assert runtime.has_playbook("community.molecule.validate.yml")
+
+
+def test_runtime_exception(monkeypatch: pytest.MonkeyPatch) -> None:
+ """Asserts that we raise a runtime exception if unsupported environment
variable is detected."""
+ monkeypatch.setenv("ANSIBLE_COLLECTIONS_PATHS", "foo")
+ with pytest.raises(
+ RuntimeError,
+ match=r"ANSIBLE_COLLECTIONS_PATHS was detected, replace it with
ANSIBLE_COLLECTIONS_PATH to continue.",
+ ):
+ Runtime()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/test/test_runtime_scan_path.py
new/ansible-compat-25.1.0/test/test_runtime_scan_path.py
--- old/ansible-compat-25.0.0/test/test_runtime_scan_path.py 2025-01-12
21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/test/test_runtime_scan_path.py 2025-01-27
17:15:25.000000000 +0100
@@ -21,15 +21,14 @@
@pytest.mark.parametrize(
("scan", "raises_not_found"),
(
- pytest.param(False, True, id="0"),
- pytest.param(True, False, id="1"),
+ pytest.param(False, True, id="disabled"),
+ pytest.param(True, False, id="enabled"),
),
ids=str,
)
def test_scan_sys_path(
venv_module: VirtualEnvironment,
monkeypatch: MonkeyPatch,
- runtime_tmp: Runtime,
tmp_path: Path,
scan: bool,
raises_not_found: bool,
@@ -39,7 +38,6 @@
Args:
venv_module: Fixture for a virtual environment
monkeypatch: Fixture for monkeypatching
- runtime_tmp: Fixture for a Runtime object
tmp_path: Fixture for a temporary directory
scan: Whether to scan the sys path
raises_not_found: Whether the collection is expected to be found
@@ -48,6 +46,12 @@
# that might be installed by other tests.
monkeypatch.setenv("VIRTUAL_ENV", venv_module.project.as_posix())
monkeypatch.setenv("ANSIBLE_HOME", tmp_path.as_posix())
+ # Set the sys scan path environment variable
+ monkeypatch.setenv("ANSIBLE_COLLECTIONS_SCAN_SYS_PATH", str(scan))
+ # Set the ansible collections paths to avoid bleed from other tests
+ monkeypatch.setenv("ANSIBLE_COLLECTIONS_PATH", str(tmp_path))
+
+ runtime_tmp = Runtime(project_dir=tmp_path, isolated=True)
first_site_package_dir = venv_module.site_package_dirs()[0]
installed_to = (
@@ -66,10 +70,6 @@
)
# Confirm the collection is installed
assert installed_to.exists()
- # Set the sys scan path environment variable
- monkeypatch.setenv("ANSIBLE_COLLECTIONS_SCAN_SYS_PATH", str(scan))
- # Set the ansible collections paths to avoid bleed from other tests
- monkeypatch.setenv("ANSIBLE_COLLECTIONS_PATH", str(tmp_path))
script = textwrap.dedent(
f"""
@@ -91,3 +91,5 @@
result = json.loads(proc.stdout)
assert result["found_version"] == V2_COLLECTION_VERSION
assert result["collection_path"] == str(installed_to)
+
+ runtime_tmp.clean()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/tools/smoke.py
new/ansible-compat-25.1.0/tools/smoke.py
--- old/ansible-compat-25.0.0/tools/smoke.py 1970-01-01 01:00:00.000000000
+0100
+++ new/ansible-compat-25.1.0/tools/smoke.py 2025-01-27 17:15:25.000000000
+0100
@@ -0,0 +1,55 @@
+#!python3
+"""Runs downstream projects tests with current code from compat injected in
them."""
+
+import hashlib
+import logging
+import os
+import tempfile
+from pathlib import Path
+from subprocess import run # noqa: S404
+
+logging.basicConfig(
+ level=logging.DEBUG,
+ format="%(levelname)s: %(message)s",
+)
+logger = logging.getLogger()
+
+
+parent_project_dir = Path(__file__).parent.parent.resolve().as_posix()
+checksum = hashlib.sha256(parent_project_dir.encode("utf-8")).hexdigest()[:4]
+tmp_path = Path(tempfile.gettempdir()) / f"ansible-compat-smoke-{checksum}"
+
+logger.info("Using %s temporary directory...", tmp_path)
+
+for project in ("molecule", "ansible-lint"):
+
+ logger.info("Running tests for %s", project)
+ project_dir = tmp_path / project
+ if (project_dir / ".git").exists():
+ run(["git", "-C", project_dir, "pull"], check=True)
+ else:
+ project_dir.mkdir(parents=True, exist_ok=True)
+ run(
+ [
+ "git",
+ "clone",
+ "--recursive",
+ f"https://github.com/ansible/{project}",
+ project_dir,
+ ],
+ check=True,
+ )
+
+ os.chdir(project_dir)
+ venv_dir = (project_dir / ".venv").as_posix()
+ os.environ["VIRTUAL_ENV"] = venv_dir
+ run(
+ ["uv", "venv", "--seed", venv_dir],
+ check=True,
+ ) # creates .venv (implicit for next commands)
+ run(
+ ["uv", "pip", "install", "-e", f"{parent_project_dir}[test]", "-e",
".[test]"],
+ check=True,
+ )
+ run(["uv", "pip", "freeze"], check=True)
+ run(["uv", "run", "pytest", "-v", "-n", "auto"], check=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ansible-compat-25.0.0/tox.ini
new/ansible-compat-25.1.0/tox.ini
--- old/ansible-compat-25.0.0/tox.ini 2025-01-12 21:15:20.000000000 +0100
+++ new/ansible-compat-25.1.0/tox.ini 2025-01-27 17:15:25.000000000 +0100
@@ -1,5 +1,4 @@
[tox]
-minversion = 4.6.3
envlist =
lint
pkg
@@ -18,9 +17,8 @@
isolated_build = true
skip_missing_interpreters = True
requires =
- tox >= 4.6.3
- tox-extra >= 2.0.1
- tox-uv
+ tox >= 4.24.1
+ tox-uv >= 1.20.1
setuptools >= 65.3.0 # editable installs
[testenv]
@@ -36,7 +34,7 @@
ansible217: ansible-core>=2.17,<2.18
ansible218: ansible-core>=2.18,<2.19
- devel: ansible-core @
git+https://github.com/ansible/ansible.git@c5d18c39d81e2b3b10856b2fb76747230e4fac4a
# GPLv3+
+ devel: ansible-core @ git+https://github.com/ansible/ansible.git@devel #
GPLv3+
# avoid installing ansible-core on -devel envs:
!devel: ansible-core
extras =
@@ -80,6 +78,7 @@
COVERAGE_PROCESS_START={toxinidir}/pyproject.toml
PIP_DISABLE_PIP_VERSION_CHECK = 1
PIP_CONSTRAINT = {toxinidir}/.config/constraints.txt
+ UV_CONSTRAINT = {toxinidir}/.config/constraints.txt
PRE_COMMIT_COLOR = always
FORCE_COLOR = 1
allowlist_externals =
@@ -88,6 +87,7 @@
sh
# https://tox.wiki/en/latest/upgrading.html#editable-mode
package = editable
+uv_seed = true
[testenv:lint]
description = Run all linters
@@ -108,6 +108,7 @@
setenv =
{[testenv]setenv}
PIP_CONSTRAINT = /dev/null
+ UV_CONSTRAINT = /dev/null
[testenv:deps]
description = Bump all test dependencies
@@ -121,6 +122,7 @@
setenv =
{[testenv]setenv}
PIP_CONSTRAINT = /dev/null
+ UV_CONSTRAINT = /dev/null
[testenv:pkg]
description =
@@ -171,20 +173,11 @@
passenv = *
[testenv:smoke]
-description = Run ansible-lint own testing with current code from compat
library
-commands_pre =
- ansible localhost -m ansible.builtin.git -a
'repo=https://github.com/ansible/ansible-lint dest={envdir}/tmp/ansible-lint'
- pip install -e "{envdir}/tmp/ansible-lint[test]"
+description = Run ansible-lint and molecule own testing with current code from
compat library
commands =
- bash -c "pip freeze|grep ansible"
- pytest -k role
-deps =
- ansible-core
-setenv =
- {[testenv]setenv}
- PIP_CONSTRAINT = /dev/null
- PYTEST_REQPASS = 0
-changedir = {envdir}/tmp/ansible-lint
-allowlist_externals =
- pwd
- bash
+ python3 tools/smoke.py
+del_env =
+ PIP_CONSTRAINT
+ UV_CONSTRAINT
+editable = true
+skip_install = true