Import test: improve docs, add more tests (#73600)
This commit is contained in:
parent
ba3f84883f
commit
3cc693b92c
7 changed files with 148 additions and 4 deletions
|
@ -1,5 +1,68 @@
|
|||
import
|
||||
======
|
||||
|
||||
All Python imports in ``lib/ansible/modules/`` and ``lib/ansible/module_utils/`` which are not from the Python standard library
|
||||
must be imported in a try/except ImportError block.
|
||||
Ansible allows unchecked imports of some libraries from specific directories, listed at the bottom of this section. Import all other Python libraries in a try/except ImportError block to support sanity tests such as ``validate-modules`` and to allow Ansible to give better error messages to the user. To import a library in a try/except ImportError block:
|
||||
|
||||
1. In modules:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Instead of 'import another_library', do:
|
||||
|
||||
import traceback
|
||||
|
||||
try:
|
||||
import another_library
|
||||
except ImportError:
|
||||
HAS_ANOTHER_LIBRARY = False
|
||||
ANOTHER_LIBRARY_IMPORT_ERROR = traceback.format_exc()
|
||||
else:
|
||||
HAS_ANOTHER_LIBRARY = True
|
||||
|
||||
|
||||
# Later in module code:
|
||||
|
||||
module = AnsibleModule(...)
|
||||
|
||||
if not HAS_ANOTHER_LIBRARY:
|
||||
# Needs: from ansible.module_utils.basic import missing_required_lib
|
||||
module.fail_json(
|
||||
msg=missing_required_lib('another_library'),
|
||||
exception=ANOTHER_LIBRARY_IMPORT_ERROR)
|
||||
|
||||
2. In plugins:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Instead of 'import another_library', do:
|
||||
|
||||
from ansible.module_utils.six import raise_from
|
||||
|
||||
try:
|
||||
import another_library
|
||||
except ImportError as imp_exc:
|
||||
ANOTHER_LIBRARY_IMPORT_ERROR = imp_exc
|
||||
else:
|
||||
ANOTHER_LIBRARY_IMPORT_ERROR = None
|
||||
|
||||
|
||||
# Later in plugin code, for example in __init__ of the plugin:
|
||||
|
||||
if ANOTHER_LIBRARY_IMPORT_ERROR:
|
||||
raise_from(
|
||||
AnsibleError('another_library must be installed to use this plugin'),
|
||||
ANOTHER_LIBRARY_IMPORT_ERROR)
|
||||
# If you target only newer Python 3 versions, you can also use the
|
||||
# 'raise ... from ...' syntax.
|
||||
|
||||
Ansible allows the following unchecked imports from these specific directories:
|
||||
|
||||
* ansible-core:
|
||||
|
||||
* For ``lib/ansible/modules/`` and ``lib/ansible/module_utils/``, unchecked imports are only allowed from the Python standard library;
|
||||
* For ``lib/ansible/plugins/``, unchecked imports are only allowed from the Python standard library, from dependencies of ansible-core, and from ansible-core itself;
|
||||
|
||||
* collections:
|
||||
|
||||
* For ``plugins/modules/`` and ``plugins/module_utils/``, unchecked imports are only allowed from the Python standard library;
|
||||
* For other directories in ``plugins/`` (see `the community collection requirements <https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#modules-plugins>`_ for a list), unchecked imports are only allowed from the Python standard library, from dependencies of ansible-core, and from ansible-core itself.
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: bad
|
||||
short_description: Bad lookup
|
||||
description: A bad lookup.
|
||||
author:
|
||||
- Ansible Core Team
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- debug:
|
||||
msg: "{{ lookup('ns.col.bad') }}"
|
||||
'''
|
||||
|
||||
RETURN = ''' # '''
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible import constants
|
||||
|
||||
import lxml
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
def run(self, terms, variables, **kwargs):
|
||||
self.set_options(var_options=variables, direct=kwargs)
|
||||
|
||||
return terms
|
|
@ -0,0 +1,29 @@
|
|||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: world
|
||||
short_description: World lookup
|
||||
description: A world lookup.
|
||||
author:
|
||||
- Ansible Core Team
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- debug:
|
||||
msg: "{{ lookup('ns.col.world') }}"
|
||||
'''
|
||||
|
||||
RETURN = ''' # '''
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible import constants
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
def run(self, terms, variables, **kwargs):
|
||||
self.set_options(var_options=variables, direct=kwargs)
|
||||
|
||||
return terms
|
|
@ -0,0 +1,8 @@
|
|||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
# This is not an allowed import, but since this file is in a plugins/ subdirectory that is not checked,
|
||||
# the import sanity test will not complain.
|
||||
import lxml
|
|
@ -1,5 +1,6 @@
|
|||
plugins/modules/bad.py import
|
||||
plugins/modules/bad.py pylint:ansible-bad-module-import
|
||||
plugins/lookup/bad.py import
|
||||
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-function
|
||||
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import
|
||||
tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import-from
|
||||
|
|
|
@ -7,7 +7,13 @@ cd "${WORK_DIR}/ansible_collections/ns/col"
|
|||
|
||||
# rename the sanity ignore file to match the current ansible version and update import ignores with the python version
|
||||
ansible_version="$(python -c 'import ansible.release; print(".".join(ansible.release.__version__.split(".")[:2]))')"
|
||||
sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
|
||||
if [ "${ANSIBLE_TEST_PYTHON_VERSION}" == "2.6" ]; then
|
||||
# Non-module/module_utils plugins are not checked on this remote-only Python versions
|
||||
sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" | grep -v 'plugins/[^m].* import' > "tests/sanity/ignore-${ansible_version}.txt"
|
||||
else
|
||||
sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
|
||||
fi
|
||||
cat "tests/sanity/ignore-${ansible_version}.txt"
|
||||
|
||||
# common args for all tests
|
||||
common=(--venv --color --truncate 0 "${@}")
|
||||
|
|
|
@ -7,7 +7,13 @@ cd "${WORK_DIR}/ansible_collections/ns/col"
|
|||
|
||||
# rename the sanity ignore file to match the current ansible version and update import ignores with the python version
|
||||
ansible_version="$(python -c 'import ansible.release; print(".".join(ansible.release.__version__.split(".")[:2]))')"
|
||||
sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
|
||||
if [ "${ANSIBLE_TEST_PYTHON_VERSION}" == "2.6" ]; then
|
||||
# Non-module/module_utils plugins are not checked on this remote-only Python versions
|
||||
sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" | grep -v 'plugins/[^m].* import' > "tests/sanity/ignore-${ansible_version}.txt"
|
||||
else
|
||||
sed "s/ import$/ import-${ANSIBLE_TEST_PYTHON_VERSION}/;" < "tests/sanity/ignore.txt" > "tests/sanity/ignore-${ansible_version}.txt"
|
||||
fi
|
||||
cat "tests/sanity/ignore-${ansible_version}.txt"
|
||||
|
||||
# common args for all tests
|
||||
# each test will be run in a separate venv to verify that requirements have been properly specified
|
||||
|
|
Loading…
Reference in a new issue