annotate contrib/check-py3-compat.py @ 43659:99e231afc29c

black: blacken scripts test-check-format.t doesn't appear to detect Python scripts with shebangs. But my editor which is configured to auto run black on Python files does and it appears some files are not blackened. This commit blackens scripts that need it. # skip-blame reformatting Differential Revision: https://phab.mercurial-scm.org/D7420
author Gregory Szorc <gregory.szorc@gmail.com>
date Thu, 14 Nov 2019 20:35:11 -0800
parents 2372284d9457
children 9d2b2df2c2ba
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 #!/usr/bin/env python
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 #
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 # check-py3-compat - check Python 3 compatibility of Mercurial files
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4 #
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 #
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7 # This software may be used and distributed according to the terms of the
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 # GNU General Public License version 2 or any later version.
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
9
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
10 from __future__ import absolute_import, print_function
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
11
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
12 import ast
32280
9b81fb217820 py3: remove delayed import of importlib
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32212
diff changeset
13 import importlib
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
14 import os
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
15 import sys
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
16 import traceback
41555
ba7eaff26474 check-py3-compat: manually format and print warnings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41554
diff changeset
17 import warnings
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
18
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
19
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
20 def check_compat_py2(f):
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
21 """Check Python 3 compatibility for a file with Python 2"""
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
22 with open(f, 'rb') as fh:
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
23 content = fh.read()
28475
ae522fb493d4 test: make check-py3-compat.py ignore empty code more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 27331
diff changeset
24 root = ast.parse(content)
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
25
27331
35e69407b1ac contrib: ignore empty files in check-py3-compat.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27279
diff changeset
26 # Ignore empty files.
28475
ae522fb493d4 test: make check-py3-compat.py ignore empty code more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 27331
diff changeset
27 if not root.body:
27331
35e69407b1ac contrib: ignore empty files in check-py3-compat.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27279
diff changeset
28 return
35e69407b1ac contrib: ignore empty files in check-py3-compat.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27279
diff changeset
29
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
30 futures = set()
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
31 haveprint = False
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
32 for node in ast.walk(root):
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
33 if isinstance(node, ast.ImportFrom):
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
34 if node.module == '__future__':
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
35 futures |= set(n.name for n in node.names)
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
36 elif isinstance(node, ast.Print):
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
37 haveprint = True
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
38
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
39 if 'absolute_import' not in futures:
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
40 print('%s not using absolute_import' % f)
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
41 if haveprint and 'print_function' not in futures:
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
42 print('%s requires print_function' % f)
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
43
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
44
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
45 def check_compat_py3(f):
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
46 """Check Python 3 compatibility of a file with Python 3."""
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
47 with open(f, 'rb') as fh:
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
48 content = fh.read()
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
49
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
50 try:
41554
01417ca7f2e2 check-py3-compat: provide filename to ast.parse()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32421
diff changeset
51 ast.parse(content, filename=f)
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
52 except SyntaxError as e:
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
53 print('%s: invalid syntax: %s' % (f, e))
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
54 return
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
55
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
56 # Try to import the module.
32421
778dc37ce683 check: check modules in hgdemandimport
Siddharth Agarwal <sid0@fb.com>
parents: 32374
diff changeset
57 # For now we only support modules in packages because figuring out module
778dc37ce683 check: check modules in hgdemandimport
Siddharth Agarwal <sid0@fb.com>
parents: 32374
diff changeset
58 # paths for things not in a package can be confusing.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
59 if f.startswith(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
60 ('hgdemandimport/', 'hgext/', 'mercurial/')
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
61 ) and not f.endswith('__init__.py'):
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
62 assert f.endswith('.py')
32212
65cd7e705ff6 policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents: 30117
diff changeset
63 name = f.replace('/', '.')[:-3]
30095
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
64 try:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
65 importlib.import_module(name)
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
66 except Exception as e:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
67 exc_type, exc_value, tb = sys.exc_info()
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
68 # We walk the stack and ignore frames from our custom importer,
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
69 # import mechanisms, and stdlib modules. This kinda/sorta
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
70 # emulates CPython behavior in import.c while also attempting
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
71 # to pin blame on a Mercurial file.
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
72 for frame in reversed(traceback.extract_tb(tb)):
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
73 if frame.name == '_call_with_frames_removed':
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
74 continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
75 if 'importlib' in frame.filename:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
76 continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
77 if 'mercurial/__init__.py' in frame.filename:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
78 continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
79 if frame.filename.startswith(sys.prefix):
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
80 continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
81 break
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
82
30095
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
83 if frame.filename:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
84 filename = os.path.basename(frame.filename)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
85 print(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
86 '%s: error importing: <%s> %s (error at %s:%d)'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
87 % (f, type(e).__name__, e, filename, frame.lineno)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
88 )
30095
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
89 else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
90 print(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
91 '%s: error importing module: <%s> %s (line %d)'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
92 % (f, type(e).__name__, e, frame.lineno)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
93 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
94
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
95
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
96 if __name__ == '__main__':
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
97 if sys.version_info[0] == 2:
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
98 fn = check_compat_py2
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
99 else:
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
100 fn = check_compat_py3
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
101
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
102 for f in sys.argv[1:]:
41555
ba7eaff26474 check-py3-compat: manually format and print warnings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41554
diff changeset
103 with warnings.catch_warnings(record=True) as warns:
ba7eaff26474 check-py3-compat: manually format and print warnings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41554
diff changeset
104 fn(f)
ba7eaff26474 check-py3-compat: manually format and print warnings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41554
diff changeset
105
ba7eaff26474 check-py3-compat: manually format and print warnings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 41554
diff changeset
106 for w in warns:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
107 print(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
108 warnings.formatwarning(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
109 w.message, w.category, w.filename, w.lineno
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
110 ).rstrip()
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41555
diff changeset
111 )
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
112
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
113 sys.exit(0)