summaryrefslogtreecommitdiffstats
path: root/test/sanity/code-smell/ansible-test-future-boilerplate.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/sanity/code-smell/ansible-test-future-boilerplate.py')
-rw-r--r--test/sanity/code-smell/ansible-test-future-boilerplate.py59
1 files changed, 59 insertions, 0 deletions
diff --git a/test/sanity/code-smell/ansible-test-future-boilerplate.py b/test/sanity/code-smell/ansible-test-future-boilerplate.py
new file mode 100644
index 0000000..9a62225
--- /dev/null
+++ b/test/sanity/code-smell/ansible-test-future-boilerplate.py
@@ -0,0 +1,59 @@
+from __future__ import annotations
+
+import ast
+import sys
+
+
+def main():
+ # The following directories contain code which must work under Python 2.x.
+ py2_compat = (
+ 'test/lib/ansible_test/_util/target/',
+ )
+
+ for path in sys.argv[1:] or sys.stdin.read().splitlines():
+ if any(path.startswith(prefix) for prefix in py2_compat):
+ continue
+
+ with open(path, 'rb') as path_fd:
+ lines = path_fd.read().splitlines()
+
+ missing = True
+ if not lines:
+ # Files are allowed to be empty of everything including boilerplate
+ missing = False
+
+ invalid_future = []
+
+ for text in lines:
+ if text == b'from __future__ import annotations':
+ missing = False
+ break
+
+ if text.startswith(b'from __future__ ') or text == b'__metaclass__ = type':
+ invalid_future.append(text.decode())
+
+ if missing:
+ with open(path) as file:
+ contents = file.read()
+
+ # noinspection PyBroadException
+ try:
+ node = ast.parse(contents)
+
+ # files consisting of only assignments have no need for future import boilerplate
+ # the only exception would be division during assignment, but we'll overlook that for simplicity
+ # the most likely case is that of a documentation only python file
+ if all(isinstance(statement, ast.Assign) for statement in node.body):
+ missing = False
+ except Exception: # pylint: disable=broad-except
+ pass # the compile sanity test will report this error
+
+ if missing:
+ print('%s: missing: from __future__ import annotations' % path)
+
+ for text in invalid_future:
+ print('%s: invalid: %s' % (path, text))
+
+
+if __name__ == '__main__':
+ main()