diff --git a/changelogs/fragments/ansible-test-pylint-deprecated-fix.yml b/changelogs/fragments/ansible-test-pylint-deprecated-fix.yml new file mode 100644 index 00000000000..9dabcd0c3a3 --- /dev/null +++ b/changelogs/fragments/ansible-test-pylint-deprecated-fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - ansible-test - Updated the ``pylint`` sanity test to skip some deprecation validation checks when all arguments are dynamic. diff --git a/test/integration/targets/ansible-test-sanity-pylint/ansible_collections/ns/col/plugins/lookup/deprecated.py b/test/integration/targets/ansible-test-sanity-pylint/ansible_collections/ns/col/plugins/lookup/deprecated.py index afb9edb2e14..3cb92997313 100644 --- a/test/integration/targets/ansible-test-sanity-pylint/ansible_collections/ns/col/plugins/lookup/deprecated.py +++ b/test/integration/targets/ansible-test-sanity-pylint/ansible_collections/ns/col/plugins/lookup/deprecated.py @@ -83,3 +83,10 @@ def do_stuff() -> None: foreign_global_display.deprecated('', version='2.0.0', collection_name='ns.col') _display.deprecated('', version='2.0.0', collection_name='ns.col') give_me_a_func()("hello") # not detected + + # don't validate date/version/collection_name if all are dynamic + a_msg = 'message not checked' + a_date = 'date not checked' + a_version = 'version not checked' + a_collection_name = 'mismatched' + _display.deprecated(msg=a_msg, date=a_date, version=a_version, collection_name=a_collection_name) diff --git a/test/lib/ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py b/test/lib/ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py index 3447e857614..a350be5aca8 100644 --- a/test/lib/ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +++ b/test/lib/ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py @@ -39,6 +39,10 @@ class DeprecationCallArgs: removed: object = None # only on Display.deprecated value: object = None # only on deprecate_value + def all_args_dynamic(self) -> bool: + """True if all args are dynamic or None, otherwise False.""" + return all(arg is None or isinstance(arg, astroid.NodeNG) for arg in dataclasses.asdict(self).values()) + class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker): """Checks for deprecated calls to ensure proper usage.""" @@ -346,6 +350,10 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker): self.add_message('ansible-deprecated-date-not-permitted', node=node, args=(name,)) return + if call_args.all_args_dynamic(): + # assume collection maintainers know what they're doing if all args are dynamic + return + if call_args.version and call_args.date: self.add_message('ansible-deprecated-both-version-and-date', node=node, args=(name,)) return @@ -407,10 +415,13 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker): self.add_message('ansible-deprecated-unnecessary-collection-name', node=node, args=('deprecator', name,)) return + if args.all_args_dynamic(): + # assume collection maintainers know what they're doing if all args are dynamic + return + expected_collection_name = 'ansible.builtin' if self.is_ansible_core else self.collection_name if args.collection_name and args.collection_name != expected_collection_name: - # if collection_name is provided and a constant, report when it does not match the expected name self.add_message('wrong-collection-deprecated', node=node, args=(args.collection_name, name)) def check_version(self, node: astroid.Call, name: str, args: DeprecationCallArgs) -> None: