Mercurial > public > mercurial-scm > hg
annotate contrib/check-py3-compat.py @ 32369:3b88a7fa97d8
bdiff: switch to policy importer
# no-check-commit
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 13 Aug 2016 12:12:50 +0900 |
parents | 008d37c4d783 |
children | 017ad85e5ac8 |
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 |
27279
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
17 |
32212
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
18 # Modules that have both Python and C implementations. |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
19 _dualmodules = ( |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
20 'diffhelpers.py', |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
21 'mpatch.py', |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
22 'parsers.py', |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
23 ) |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
24 |
28583
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
25 def check_compat_py2(f): |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
26 """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
|
27 with open(f, 'rb') as fh: |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
28 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
|
29 root = ast.parse(content) |
27279
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
30 |
27331
35e69407b1ac
contrib: ignore empty files in check-py3-compat.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27279
diff
changeset
|
31 # 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
|
32 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
|
33 return |
35e69407b1ac
contrib: ignore empty files in check-py3-compat.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27279
diff
changeset
|
34 |
27279
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
35 futures = set() |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
36 haveprint = False |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
37 for node in ast.walk(root): |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
38 if isinstance(node, ast.ImportFrom): |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
39 if node.module == '__future__': |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
40 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
|
41 elif isinstance(node, ast.Print): |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
42 haveprint = True |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
43 |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
44 if 'absolute_import' not in futures: |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
45 print('%s not using absolute_import' % f) |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
46 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
|
47 print('%s requires print_function' % f) |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
48 |
28583
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
49 def check_compat_py3(f): |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
50 """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
|
51 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
|
52 content = fh.read() |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
53 |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
54 try: |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
55 ast.parse(content) |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
56 except SyntaxError as e: |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
57 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
|
58 return |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
59 |
28584
d69172ddfdca
tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28583
diff
changeset
|
60 # Try to import the module. |
d69172ddfdca
tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28583
diff
changeset
|
61 # For now we only support mercurial.* and hgext.* modules because figuring |
d69172ddfdca
tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28583
diff
changeset
|
62 # out module paths for things not in a package can be confusing. |
d69172ddfdca
tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28583
diff
changeset
|
63 if f.startswith(('hgext/', 'mercurial/')) and not f.endswith('__init__.py'): |
d69172ddfdca
tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28583
diff
changeset
|
64 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
|
65 name = f.replace('/', '.')[:-3] |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
66 if f.endswith(_dualmodules): |
65cd7e705ff6
policy: eliminate ".pure." from module name only if marked as dual
Yuya Nishihara <yuya@tcha.org>
parents:
30117
diff
changeset
|
67 name = name.replace('.pure.', '.') |
30095
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
68 try: |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
69 importlib.import_module(name) |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
70 except Exception as e: |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
71 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
|
72 # 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
|
73 # 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
|
74 # 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
|
75 # 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
|
76 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
|
77 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
|
78 continue |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
79 if 'importlib' in frame.filename: |
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 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
|
82 continue |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
83 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
|
84 continue |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
85 break |
28584
d69172ddfdca
tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28583
diff
changeset
|
86 |
30095
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
87 if frame.filename: |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
88 filename = os.path.basename(frame.filename) |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
89 print('%s: error importing: <%s> %s (error at %s:%d)' % ( |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
90 f, type(e).__name__, e, filename, frame.lineno)) |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
91 else: |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
92 print('%s: error importing module: <%s> %s (line %d)' % ( |
e8aeeb28e35e
py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents:
30094
diff
changeset
|
93 f, type(e).__name__, e, frame.lineno)) |
28584
d69172ddfdca
tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28583
diff
changeset
|
94 |
27279
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
95 if __name__ == '__main__': |
28583
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
96 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
|
97 fn = check_compat_py2 |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
98 else: |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
99 fn = check_compat_py3 |
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
100 |
27279
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
101 for f in sys.argv[1:]: |
28583
260ce2eed951
tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28475
diff
changeset
|
102 fn(f) |
27279
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
103 |
40eb385f798f
tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
104 sys.exit(0) |