contrib/check-py3-compat.py
author Gregory Szorc <gregory.szorc@gmail.com>
Thu, 17 Nov 2016 20:17:51 -0800
changeset 30460 94ca0e13d1fc
parent 30117 b85fa6bf298b
child 32252 65cd7e705ff6
permissions -rwxr-xr-x
perf: add command for measuring revlog chunk operations Upcoming commits will teach revlogs to leverage the new compression engine API so that new compression formats can more easily be leveraged in revlogs. We want to be sure this refactoring doesn't regress performance. So this commit introduces "perfrevchunks" to explicitly test performance of reading, decompressing, and recompressing revlog chunks. Here is output when run on the mozilla-unified repo: $ hg perfrevlogchunks -c ! read ! wall 0.346603 comb 0.350000 user 0.340000 sys 0.010000 (best of 28) ! read w/ reused fd ! wall 0.337707 comb 0.340000 user 0.320000 sys 0.020000 (best of 30) ! read batch ! wall 0.013206 comb 0.020000 user 0.000000 sys 0.020000 (best of 221) ! read batch w/ reused fd ! wall 0.013259 comb 0.030000 user 0.010000 sys 0.020000 (best of 222) ! chunk ! wall 1.909939 comb 1.910000 user 1.900000 sys 0.010000 (best of 6) ! chunk batch ! wall 1.750677 comb 1.760000 user 1.740000 sys 0.020000 (best of 6) ! compress ! wall 5.668004 comb 5.670000 user 5.670000 sys 0.000000 (best of 3) $ hg perfrevlogchunks -m ! read ! wall 0.365834 comb 0.370000 user 0.350000 sys 0.020000 (best of 26) ! read w/ reused fd ! wall 0.350160 comb 0.350000 user 0.320000 sys 0.030000 (best of 28) ! read batch ! wall 0.024777 comb 0.020000 user 0.000000 sys 0.020000 (best of 119) ! read batch w/ reused fd ! wall 0.024895 comb 0.030000 user 0.000000 sys 0.030000 (best of 118) ! chunk ! wall 2.514061 comb 2.520000 user 2.480000 sys 0.040000 (best of 4) ! chunk batch ! wall 2.380788 comb 2.380000 user 2.360000 sys 0.020000 (best of 5) ! compress ! wall 9.815297 comb 9.820000 user 9.820000 sys 0.000000 (best of 3) We already see some interesting data, such as how much slower non-batched chunk reading is and that zlib compression appears to be >2x slower than decompression. I didn't have the data when I wrote this commit message, but I ran this on Mozilla's NFS-based Mercurial server and the time for reading with a reused file descriptor was faster. So I think it is worth testing both with and without file descriptor reuse so we can make informed decisions about recycling file descriptors.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
    13
import os
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    14
import sys
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
    15
import traceback
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    16
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    17
def check_compat_py2(f):
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    18
    """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
    19
    with open(f, 'rb') as fh:
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    20
        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
    21
    root = ast.parse(content)
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    22
27331
35e69407b1ac contrib: ignore empty files in check-py3-compat.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27279
diff changeset
    23
    # 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
    24
    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
    25
        return
35e69407b1ac contrib: ignore empty files in check-py3-compat.py
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27279
diff changeset
    26
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    27
    futures = set()
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    28
    haveprint = False
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    29
    for node in ast.walk(root):
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    30
        if isinstance(node, ast.ImportFrom):
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    31
            if node.module == '__future__':
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    32
                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
    33
        elif isinstance(node, ast.Print):
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    34
            haveprint = True
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    35
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    36
    if 'absolute_import' not in futures:
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    37
        print('%s not using absolute_import' % f)
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    38
    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
    39
        print('%s requires print_function' % f)
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    40
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    41
def check_compat_py3(f):
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    42
    """Check Python 3 compatibility of a file with Python 3."""
30117
b85fa6bf298b py3: make check-py3-compat.py import importlib only if necessary
Yuya Nishihara <yuya@tcha.org>
parents: 30095
diff changeset
    43
    import importlib  # not available on Python 2.6
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    44
    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
    45
        content = fh.read()
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    46
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    47
    try:
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    48
        ast.parse(content)
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    49
    except SyntaxError as e:
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    50
        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
    51
        return
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    52
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
    53
    # Try to import the module.
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
    54
    # 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
    55
    # 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
    56
    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
    57
        assert f.endswith('.py')
29763
8faac092bb0c py3: make check-py3-compat.py use correct module name at loading pure modules
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29550
diff changeset
    58
        name = f.replace('/', '.')[:-3].replace('.pure.', '.')
30095
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    59
        try:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    60
            importlib.import_module(name)
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    61
        except Exception as e:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    62
            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
    63
            # 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
    64
            # 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
    65
            # 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
    66
            # 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
    67
            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
    68
                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
    69
                    continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    70
                if 'importlib' in frame.filename:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    71
                    continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    72
                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
    73
                    continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    74
                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
    75
                    continue
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    76
                break
28584
d69172ddfdca tests: try to import modules with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28583
diff changeset
    77
30095
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    78
            if frame.filename:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    79
                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
    80
                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
    81
                      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
    82
            else:
e8aeeb28e35e py3: remove superfluous indent from check-py3-compat.py
Yuya Nishihara <yuya@tcha.org>
parents: 30094
diff changeset
    83
                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
    84
                      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
    85
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    86
if __name__ == '__main__':
28583
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    87
    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
    88
        fn = check_compat_py2
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    89
    else:
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    90
        fn = check_compat_py3
260ce2eed951 tests: perform an ast parse with Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28475
diff changeset
    91
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    92
    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
    93
        fn(f)
27279
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    94
40eb385f798f tests: add test for Python 3 compatibility
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    95
    sys.exit(0)