Expand docs for the import sanity test. (#79768)

* Expand docs for the import sanity test.

* Remove note about Python 2.7 compat.

It should not be needed since there is a sanity test to enforce use of `__metaclass__ = type`.

* Improve introductory paragraph.

* Fix link typo.
pull/79835/head
Matt Clay 3 years ago committed by GitHub
parent 321848e98d
commit 2164d5699c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,59 +1,110 @@
import import
====== ======
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: Ansible :ref:`allows unchecked imports<allowed_unchecked_imports>` of some libraries from specific directories.
Importing any other Python library requires :ref:`handling import errors<handling_import_errors>`.
This enables support for sanity tests such as :ref:`testing_validate-modules` and provides better error messages to the user.
1. In modules: .. _handling_import_errors:
.. code-block:: python Handling import errors
----------------------
# Instead of 'import another_library', do: In modules
^^^^^^^^^^
import traceback Instead of using ``import another_library``:
try: .. code-block:: python
import another_library
except ImportError:
HAS_ANOTHER_LIBRARY = False
ANOTHER_LIBRARY_IMPORT_ERROR = traceback.format_exc()
else:
HAS_ANOTHER_LIBRARY = True
import traceback
# Later in module code: from ansible.module_utils.basic import missing_required_lib
module = AnsibleModule(...) try:
import another_library
except ImportError:
HAS_ANOTHER_LIBRARY = False
ANOTHER_LIBRARY_IMPORT_ERROR = traceback.format_exc()
else:
HAS_ANOTHER_LIBRARY = True
if not HAS_ANOTHER_LIBRARY: .. note::
# 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: The ``missing_required_lib`` import above will be used below.
.. code-block:: python Then in the module code:
# Instead of 'import another_library', do: .. code-block:: python
from ansible.module_utils.six import raise_from module = AnsibleModule(...)
try: if not HAS_ANOTHER_LIBRARY:
import another_library module.fail_json(
except ImportError as imp_exc: msg=missing_required_lib('another_library'),
ANOTHER_LIBRARY_IMPORT_ERROR = imp_exc exception=ANOTHER_LIBRARY_IMPORT_ERROR)
else:
ANOTHER_LIBRARY_IMPORT_ERROR = None
In plugins
^^^^^^^^^^
# Later in plugin code, for example in __init__ of the plugin: Instead of using ``import another_library``:
if ANOTHER_LIBRARY_IMPORT_ERROR: .. code-block:: python
raise_from(
AnsibleError('another_library must be installed to use this plugin'), try:
ANOTHER_LIBRARY_IMPORT_ERROR) import another_library
# If you target only newer Python 3 versions, you can also use the except ImportError as imp_exc:
# 'raise ... from ...' syntax. ANOTHER_LIBRARY_IMPORT_ERROR = imp_exc
else:
ANOTHER_LIBRARY_IMPORT_ERROR = None
Then in the plugin code, for example in ``__init__`` of the plugin:
.. code-block:: python
if ANOTHER_LIBRARY_IMPORT_ERROR:
raise AnsibleError('another_library must be installed to use this plugin') from ANOTHER_LIBRARY_IMPORT_ERROR
When used as base classes
^^^^^^^^^^^^^^^^^^^^^^^^^
.. important::
This solution builds on the previous two examples.
Make sure to pick the appropriate one before continuing with this solution.
Sometimes an import is used in a base class, for example:
.. code-block:: python
from another_library import UsefulThing
class CustomThing(UsefulThing):
pass
One option is make the entire class definition conditional:
.. code-block:: python
if not ANOTHER_LIBRARY_IMPORT_ERROR:
class CustomThing(UsefulThing):
pass
Another option is to define a substitute base class by modifying the exception handler:
.. code-block:: python
try:
from another_library import UsefulThing
except ImportError:
class UsefulThing:
pass
...
.. _allowed_unchecked_imports:
Allowed unchecked imports
-------------------------
Ansible allows the following unchecked imports from these specific directories: Ansible allows the following unchecked imports from these specific directories:

Loading…
Cancel
Save