1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Allow specific __future__ imports in modules

We do want to allow certain from __future__ imports in modules that make
it easier to code compatible python2 and python3.  Note that
unicode_literals is specifically left out and should never be allowed.
Now that python-3.4+ allows u"" there's no good reason to use
unicode_literals.

Also switch tables in the validate_modules documentation to simple table format
This commit is contained in:
Toshio Kuratomi 2017-07-27 03:37:32 -07:00
parent 6456891053
commit 3a2670e0fd
2 changed files with 95 additions and 120 deletions

View file

@ -57,127 +57,86 @@ Codes
Errors Errors
------ ------
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ ========= ===================
| code | sample message | code sample message
+=========+============================================================================================================================================+ --------- -------------------
| **1xx** | **Locations** | **1xx** **Locations**
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 101 Interpreter line is not ``#!/usr/bin/python``
| 101 | Interpreter line is not ``#!/usr/bin/python`` | 102 Interpreter line is not ``#!powershell``
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 103 Did not find a call to ``main()``
| 102 | Interpreter line is not ``#!powershell`` | 104 Call to ``main()`` not the last line
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 105 GPLv3 license header not found
| 103 | Did not find a call to ``main()`` | 106 Import found before documentation variables. All imports must appear below
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ ``DOCUMENTATION``/``EXAMPLES``/``RETURN``/``ANSIBLE_METADATA``
| 104 | Call to ``main()`` not the last line | 107 Imports should be directly below ``DOCUMENTATION``/``EXAMPLES``/``RETURN``/``ANSIBLE_METADATA``
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ ..
| 105 | GPLv3 license header not found | --------- -------------------
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ **2xx** **Imports**
| 106 | Import found before documentation variables. All imports must appear below ``DOCUMENTATION``/``EXAMPLES``/``RETURN``/``ANSIBLE_METADATA`` | 201 Did not find a ``module_utils`` import
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 203 ``requests`` import found, should use ``ansible.module_utils.urls`` instead
| 107 | Imports should be directly below ``DOCUMENTATION``/``EXAMPLES``/``RETURN``/``ANSIBLE_METADATA`` | 204 ``boto`` import found, new modules should use ``boto3``
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 205 ``sys.exit()`` call found. Should be ``exit_json``/``fail_json``
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 206 ``WANT_JSON`` not found in module
| **2xx** | **Imports** | 207 ``REPLACER_WINDOWS`` not found in module
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 208 ``module_utils`` imports should import specific components, not ``*``
| 201 | Did not find a ``module_utils`` import | 209 Only the following ``from __future__`` imports are allowed:
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ ``absolute_import``, ``division``, and ``print_function``.
| 203 | ``requests`` import found, should use ``ansible.module_utils.urls`` instead | ..
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ --------- -------------------
| 204 | ``boto`` import found, new modules should use ``boto3`` | **3xx** **Documentation**
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 301 No ``DOCUMENTATION`` provided
| 205 | ``sys.exit()`` call found. Should be ``exit_json``/``fail_json`` | 302 ``DOCUMENTATION`` is not valid YAML
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 303 ``DOCUMENTATION`` fragment missing
| 206 | ``WANT_JSON`` not found in module | 304 Unknown ``DOCUMENTATION`` error
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 305 Invalid ``DOCUMENTATION`` schema
| 207 | ``REPLACER_WINDOWS`` not found in module | 306 Module level ``version_added`` is not a valid version number
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 307 Module level ``version_added`` is incorrect
| 208 | ``module_utils`` imports should import specific components, not ``*`` | 308 ``version_added`` for new option is not a valid version number
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 309 ``version_added`` for new option is incorrect
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 310 No ``EXAMPLES`` provided
| **3xx** | **Documentation** | 311 ``EXAMPLES`` is not valid YAML
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 312 No ``RETURN`` documentation provided
| 301 | No ``DOCUMENTATION`` provided | 313 ``RETURN`` is not valid YAML
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 314 No ``ANSIBLE_METADATA`` provided
| 302 | ``DOCUMENTATION`` is not valid YAML | 315 ``ANSIBLE_METADATA`` is not valid YAML
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 316 Invalid ``ANSIBLE_METADATA`` schema
| 303 | ``DOCUMENTATION`` fragment missing | 317 option is marked as required but specifies a default.
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ Arguments with a default should not be marked as required
| 304 | Unknown ``DOCUMENTATION`` error | 318 Module deprecated, but DOCUMENTATION.deprecated is missing
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 319 ``RETURN`` fragments missing or invalid
| 305 | Invalid ``DOCUMENTATION`` schema | ..
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ --------- -------------------
| 306 | Module level ``version_added`` is not a valid version number | **4xx** **Syntax**
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 401 Python ``SyntaxError`` while parsing module
| 307 | Module level ``version_added`` is incorrect | 402 Indentation contains tabs
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 403 Type comparison using ``type()`` found. Use ``isinstance()`` instead
| 308 | ``version_added`` for new option is not a valid version number | ..
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ --------- -------------------
| 309 | ``version_added`` for new option is incorrect | **5xx** **Naming**
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 501 Official Ansible modules must have a ``.py`` extension for python
| 310 | No ``EXAMPLES`` provided | modules or a ``.ps1`` for powershell modules
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 502 Ansible module subdirectories must contain an ``__init__.py``
| 311 | ``EXAMPLES`` is not valid YAML | 503 Missing python documentation file
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ ========= ===================
| 312 | No ``RETURN`` documentation provided |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 313 | ``RETURN`` is not valid YAML |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 314 | No ``ANSIBLE_METADATA`` provided |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 315 | ``ANSIBLE_METADATA`` is not valid YAML |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 316 | Invalid ``ANSIBLE_METADATA`` schema |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 317 | option is marked as required but specifies a default. Arguments with a default should not be marked as required |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 318 | Module deprecated, but DOCUMENTATION.deprecated is missing |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 319 | ``RETURN`` fragments missing or invalid |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| **4xx** | **Syntax** |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 401 | Python ``SyntaxError`` while parsing module |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 402 | Indentation contains tabs |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 403 | Type comparison using ``type()`` found. Use ``isinstance()`` instead |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| **5xx** | **Naming** |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 501 | Official Ansible modules must have a ``.py`` extension for python modules or a ``.ps1`` for powershell modules |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 502 | Ansible module subdirectories must contain an ``__init__.py`` |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 503 | Missing python documentation file |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
Warnings Warnings
-------- --------
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ ========= ===================
| code | sample message | code sample message
+=========+============================================================================================================================================+ --------- -------------------
| **1xx** | **Locations** | **1xx** **Locations**
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 107 Imports should be directly below ``DOCUMENTATION``/``EXAMPLES``/``RETURN``/``ANSIBLE_METADATA`` for legacy modules
| 107 | Imports should be directly below ``DOCUMENTATION``/``EXAMPLES``/``RETURN``/``ANSIBLE_METADATA`` for legacy modules | ..
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ --------- -------------------
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ **2xx** **Imports**
| **2xx** | **Imports** | 208 ``module_utils`` imports should import specific components for legacy module, not ``*``
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 291 Try/Except ``HAS_`` expression missing
| 208 | ``module_utils`` imports should import specific components for legacy module, not ``*`` | 292 Did not find ``ansible.module_utils.basic`` import
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ ..
| 291 | Try/Except ``HAS_`` expression missing | --------- -------------------
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ **3xx** **Documentation**
| 292 | Did not find ``ansible.module_utils.basic`` import | 312 No ``RETURN`` documentation provided for legacy module
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 391 Unknown pre-existing ``DOCUMENTATION`` error
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+ 392 Pre-existing ``DOCUMENTATION`` fragment missing
| **3xx** | **Documentation** | ========= ===================
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 312 | No ``RETURN`` documentation provided for legacy module |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 391 | Unknown pre-existing ``DOCUMENTATION`` error |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+
| 392 | Pre-existing ``DOCUMENTATION`` fragment missing |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------+

View file

@ -225,6 +225,8 @@ class ModuleValidator(Validator):
'setup.ps1' 'setup.ps1'
)) ))
WHITELIST_FUTURE_IMPORTS = frozenset(('absolute_import', 'division', 'print_function'))
def __init__(self, path, analyze_arg_spec=False, base_branch=None, git_cache=None, reporter=None): def __init__(self, path, analyze_arg_spec=False, base_branch=None, git_cache=None, reporter=None):
super(ModuleValidator, self).__init__(reporter=reporter or Reporter()) super(ModuleValidator, self).__init__(reporter=reporter or Reporter())
@ -558,6 +560,20 @@ class ModuleValidator(Validator):
for child in self.ast.body: for child in self.ast.body:
if isinstance(child, (ast.Import, ast.ImportFrom)): if isinstance(child, (ast.Import, ast.ImportFrom)):
if isinstance(child, ast.ImportFrom) and child.module == '__future__':
# allowed from __future__ imports
for future_import in child.names:
if future_import.name not in self.WHITELIST_FUTURE_IMPORTS:
self.reporter.error(
path=self.object_path,
code=209,
msg=('Only the following from __future__ imports are allowed: %s'
% ', '.join(self.WHITELIST_FUTURE_IMPORTS)),
line=child.lineno
)
break
else: # for-else. If we didn't find a problem nad break out of the loop, then this is a legal import
continue
import_lines.append(child.lineno) import_lines.append(child.lineno)
if child.lineno < min_doc_line: if child.lineno < min_doc_line:
self.reporter.error( self.reporter.error(