mirror of https://github.com/ansible/ansible.git
Remove uses of assert in production code (#32079)
* Remove uses of assert in production code * Fix assertion * Add code smell test for assertions, currently limited to lib/ansible * Fix assertion * Add docs for no-assert * Remove new assert from enos * Fix assert in module_utils.connectionpull/14049/merge
parent
464ded80f5
commit
99d4f5bab4
@ -0,0 +1,16 @@
|
|||||||
|
Sanity Tests » no-assert
|
||||||
|
========================
|
||||||
|
|
||||||
|
Do not use ``assert`` in production Ansible python code. When running Python
|
||||||
|
with optimizations, Python will remove ``assert`` statements, potentially
|
||||||
|
allowing for unexpected behavior throughout the Ansible code base.
|
||||||
|
|
||||||
|
Instead of using ``assert`` you should utilize simple ``if`` statements,
|
||||||
|
that result in raising an exception. There is a new exception called
|
||||||
|
``AnsibleAssertionError`` that inherits from ``AnsibleError`` and
|
||||||
|
``AssertionError``. When possible, utilize a more specific exception
|
||||||
|
than ``AnsibleAssertionError``.
|
||||||
|
|
||||||
|
Modules will not have access to ``AnsibleAssertionError`` and should instead
|
||||||
|
raise ``AssertionError``, a more specific exception, or just use
|
||||||
|
``module.fail_json`` at the failure point.
|
@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
PATH = 'lib/ansible'
|
||||||
|
ASSERT_RE = re.compile(r'.*(?<![-:a-zA-Z#][ -])\bassert\b(?!:).*')
|
||||||
|
|
||||||
|
all_matches = defaultdict(list)
|
||||||
|
|
||||||
|
for dirpath, dirnames, filenames in os.walk(PATH):
|
||||||
|
for filename in filenames:
|
||||||
|
path = os.path.join(dirpath, filename)
|
||||||
|
if not os.path.isfile(path) or not path.endswith('.py'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
for i, line in enumerate(f.readlines()):
|
||||||
|
matches = ASSERT_RE.findall(line)
|
||||||
|
|
||||||
|
if matches:
|
||||||
|
all_matches[path].append((i + 1, line.index('assert') + 1, matches))
|
||||||
|
|
||||||
|
|
||||||
|
if all_matches:
|
||||||
|
print('Use of assert in production code is not recommended.')
|
||||||
|
print('Python will remove all assert statements if run with optimizations')
|
||||||
|
print('Alternatives:')
|
||||||
|
print(' if not isinstance(value, dict):')
|
||||||
|
print(' raise AssertionError("Expected a dict for value")')
|
||||||
|
|
||||||
|
for path, matches in all_matches.items():
|
||||||
|
for line_matches in matches:
|
||||||
|
for match in line_matches[2]:
|
||||||
|
print('%s:%d:%d: %s' % ((path,) + line_matches[:2] + (match,)))
|
||||||
|
sys.exit(1)
|
Loading…
Reference in New Issue