diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /tools/lint/python/check_compat.py | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/lint/python/check_compat.py')
-rwxr-xr-x | tools/lint/python/check_compat.py | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/tools/lint/python/check_compat.py b/tools/lint/python/check_compat.py new file mode 100755 index 0000000000..25a15fcedc --- /dev/null +++ b/tools/lint/python/check_compat.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import ast +import json +import sys + + +def parse_file(f): + with open(f, "rb") as fh: + content = fh.read() + try: + return ast.parse(content) + except SyntaxError as e: + err = { + "path": f, + "message": e.msg, + "lineno": e.lineno, + "column": e.offset, + "source": e.text, + "rule": "is-parseable", + } + print(json.dumps(err)) + + +def check_compat_py2(f): + """Check Python 2 and Python 3 compatibility for a file with Python 2""" + root = parse_file(f) + + # Ignore empty or un-parseable files. + if not root or not root.body: + return + + futures = set() + haveprint = False + future_lineno = 1 + may_have_relative_imports = False + for node in ast.walk(root): + if isinstance(node, ast.ImportFrom): + if node.module == "__future__": + future_lineno = node.lineno + futures |= set(n.name for n in node.names) + else: + may_have_relative_imports = True + elif isinstance(node, ast.Import): + may_have_relative_imports = True + elif isinstance(node, ast.Print): + haveprint = True + + err = { + "path": f, + "lineno": future_lineno, + "column": 1, + } + + if "absolute_import" not in futures and may_have_relative_imports: + err["rule"] = "require absolute_import" + err["message"] = "Missing from __future__ import absolute_import" + print(json.dumps(err)) + + if haveprint and "print_function" not in futures: + err["rule"] = "require print_function" + err["message"] = "Missing from __future__ import print_function" + print(json.dumps(err)) + + +def check_compat_py3(f): + """Check Python 3 compatibility of a file with Python 3.""" + parse_file(f) + + +if __name__ == "__main__": + if sys.version_info[0] == 2: + fn = check_compat_py2 + else: + fn = check_compat_py3 + + manifest = sys.argv[1] + with open(manifest, "r") as fh: + files = fh.read().splitlines() + + for f in files: + fn(f) + + sys.exit(0) |