Commits

Victor Stinner  committed 5082d11

Split builtins into builtin_funcs and builtin_types

  • Participants
  • Parent commits 5c9c621

Comments (0)

Files changed (5)

 
 Features enabled by default:
 
- - "builtins" (always enabled): enable optimization on builtin functions
- - "math" (always enabled): replace math constants by their value (ex: math.pi)
+ - "builtin_funcs": enable optimization on builtin functions
+ - "builtin_types": enable optimization on builtin types
+ - "math": replace math constants by their value (ex: math.pi)
    and call math functions at compile time (ex: math.log)
- - "string" (always enabled): functions and constants of the string module
+ - "string": functions and constants of the string module
 
 Other features:
 
 Version 0.3
 -----------
 
+ * Split "builtins" feature into "builtin_funcs" and "builtin_types"
  * Add pythonbin configuration feature
  * Add astoptimizer.patch_compile(config=None) function to simply hook the
    builtin compile() function

File astoptimizer/config.py

 
 ANY_TYPE = object()
 
-DEFAULT_FEATURES = ('builtins', 'math', 'string')
+DEFAULT_FEATURES = ('builtin_funcs', 'builtin_types', 'math', 'string')
 
 # Don't optimize operations on non-BMP strings because the
 # result is different on narrow and wide builds

File astoptimizer/config_builtin_funcs.py

+"""
+Enable optimizations on the builtins functions, ex: len().
+"""
+from astoptimizer.compatibility import (
+    PYTHON2, PYTHON3,
+    INT_TYPES, FLOAT_TYPES, COMPLEX_TYPES,
+    BYTES_TYPE, UNICODE_TYPE, STR_TYPES,
+    IMMUTABLE_ITERABLE_TYPES, IMMUTABLE_TYPES)
+from astoptimizer.config import Function
+import sys
+
+def check_ord_args(config, args):
+    arg = args[0]
+    return (len(arg) == 1)
+
+def check_max_args(config, args):
+    arg = args[0]
+    if isinstance(arg, STR_TYPES):
+        return True
+    return all(isinstance(item, COMPLEX_TYPES) for item in arg)
+
+def check_sum_args(config, args):
+    arg = args[0]
+    if not all(isinstance(item, COMPLEX_TYPES) for item in arg):
+        return False
+    if len(args) == 2:
+        if not isinstance(args[1], COMPLEX_TYPES):
+            return False
+    return True
+
+def check_tuple_args(config, args):
+    if len(args) == 0:
+        return True
+    arg = args[0]
+    if not isinstance(arg, IMMUTABLE_ITERABLE_TYPES):
+        return False
+    if len(arg) > config.max_tuple_length:
+        return False
+    return all(isinstance(item, IMMUTABLE_TYPES) for item in arg)
+
+def check_len(config, result):
+    return (result <= config.max_size)
+
+if PYTHON2:
+    def check_str_args(config, args):
+        arg = args[0]
+        if isinstance(arg, UNICODE_TYPE):
+            return all(ord(char) <= 127 for char in arg)
+        else:
+            return True
+
+    def check_unicode_args(config, args):
+        arg = args[0]
+        if isinstance(arg, BYTES_TYPE):
+            return all(ord(byte) <= 127 for byte in arg)
+        else:
+            return True
+
+def check_pow(config, args):
+    if len(args) >= 3:
+        if not all(isinstance(arg, INT_TYPES) for arg in args[:2]):
+            return False
+
+    num = args[0]
+    exp = args[1]
+    if exp < 1.0 and exp != 0.0 and num < 0:
+        # pow(-25, 0.5) raises a ValueError
+        return False
+    if len(args) >= 3:
+        mod = args[2]
+        if mod == 0:
+            # pow(2, 1024, 0) raises a ValueError('pow() 3rd argument cannot be 0')
+            return False
+    return True
+
+def check_chr(config, args):
+    code = args[0]
+    return 0 <= code <= 0xff
+
+def check_unichr(config, args):
+    code = args[0]
+    if PYTHON3:
+        return 0 <= code <= 0x10ffff
+    else:
+        return 0 <= code <= sys.maxunicode
+
+def setup_config(config):
+    # pure builtin functions
+    config.add_func('abs', Function(abs, 1, COMPLEX_TYPES))
+    config.add_func('bool', Function(bool, 1, FLOAT_TYPES + STR_TYPES))
+    if PYTHON3:
+        config.add_func('chr', Function(chr, 1, INT_TYPES, check_args=check_unichr))
+    else:
+        config.add_func('chr', Function(chr, 1, INT_TYPES, check_args=check_chr))
+    config.add_func('divmod', Function(divmod, 2, FLOAT_TYPES, FLOAT_TYPES))
+    config.add_func('float', Function(float, 1, FLOAT_TYPES + STR_TYPES, catch=ValueError))
+    config.add_func('int', Function(int, 1, FLOAT_TYPES + STR_TYPES, catch=ValueError))
+    config.add_func('len', Function(len, 1, IMMUTABLE_ITERABLE_TYPES, check_result=check_len))
+    config.add_func('oct', Function(oct, 1, INT_TYPES))
+    config.add_func('ord', Function(ord, 1, STR_TYPES, check_args=check_ord_args))
+    config.add_func('min', Function(min, 1, STR_TYPES + (tuple, frozenset), check_args=check_max_args))
+    config.add_func('max', Function(max, 1, STR_TYPES + (tuple, frozenset), check_args=check_max_args))
+    config.add_func('pow', Function(pow, (2, 3), FLOAT_TYPES, FLOAT_TYPES, FLOAT_TYPES, check_args=check_pow))
+    config.add_func('repr', Function(repr, 1, STR_TYPES + COMPLEX_TYPES))
+    config.add_func('round', Function(round, (1, 2), FLOAT_TYPES, INT_TYPES))
+    if PYTHON3:
+        config.add_func('str', Function(str, 1, COMPLEX_TYPES + (UNICODE_TYPE,)))
+    else:
+        config.add_func('str', Function(str, 1, COMPLEX_TYPES + STR_TYPES, check_args=check_str_args))
+    config.add_func('sum', Function(sum, (1, 2), (tuple, frozenset), COMPLEX_TYPES, check_args=check_sum_args))
+    config.add_func('tuple', Function(tuple, (0, 1), IMMUTABLE_ITERABLE_TYPES, check_args=check_tuple_args))
+
+    if sys.version_info >= (2,6):
+        config.add_func('bin', Function(bin, 1, INT_TYPES))
+    if PYTHON2:
+        config.add_func('long', Function(long, 1, FLOAT_TYPES))
+        config.add_func('unichr', Function(unichr, 1, INT_TYPES, check_args=check_unichr))
+        config.add_func('unicode', Function(unicode, 1, STR_TYPES + COMPLEX_TYPES, check_args=check_unicode_args))
+

File astoptimizer/config_builtin_types.py

+"""
+Enable optimizations on the builtins types, ex: unicode.encode().
+"""
+
+from astoptimizer.compatibility import (
+    PYTHON3,
+    INT_TYPES,
+    NATIVE_STR, BYTES_TYPE, UNICODE_TYPE, STR_TYPES,
+    IMMUTABLE_ITERABLE_TYPES)
+from astoptimizer.config import Function, Method, ANY_TYPE
+import codecs
+import sys
+
+def check_encoding(encoding):
+    try:
+        encoding = codecs.lookup(encoding).name
+    except LookupError:
+        return False
+    if encoding not in ('ascii', 'iso8859-1', 'utf-8'):
+        return False
+    return True
+
+def check_str_decode_args(config, obj, args):
+    if not check_encoding(args[0]):
+        return False
+    if len(args) == 2:
+        errors = args[1]
+        if errors not in ('strict', 'replace', 'ignore'):
+            return False
+    return True
+
+def check_str_encode_args(config, obj, args):
+    if not check_encoding(args[0]):
+        return False
+    if len(args) == 2:
+        errors = args[1]
+        if errors not in ('strict', 'replace', 'ignore', 'backslashreplace'):
+            return False
+    return True
+
+def check_index_args(config, obj, args):
+    return (args[0] in obj)
+
+def check_fill_args(config, obj, args):
+    if len(args) != 2:
+        return True
+    fill = args[1]
+    return len(fill) == 1
+
+def check_str_join(config, obj, args):
+    arg = args[0]
+    str_type = type(obj)
+    if not isinstance(arg, str_type):
+        return all(isinstance(item, str_type) for item in arg)
+    else:
+        return True
+
+def setup_config(config):
+    # bytes, str, unicode
+    config.add_method(Method(BYTES_TYPE, 'decode', (1, 2), NATIVE_STR, NATIVE_STR, check_args=check_str_decode_args))
+    config.add_method(Method(UNICODE_TYPE, 'encode', (1, 2), NATIVE_STR, NATIVE_STR, check_args=check_str_encode_args))
+    for str_type in STR_TYPES:
+        config.add_method(Method(str_type, 'count', 1, str_type))
+        config.add_method(Method(str_type, 'find', 1, str_type))
+        config.add_method(Method(str_type, 'rfind', 1, str_type))
+        config.add_method(Method(str_type, 'index', 1, str_type, check_args=check_index_args))
+        config.add_method(Method(str_type, 'rindex', 1, str_type, check_args=check_index_args))
+
+        config.add_method(Method(str_type, 'startswith', 1, str_type))
+        config.add_method(Method(str_type, 'endswith', 1, str_type))
+
+        config.add_method(Method(str_type, 'ljust', (1, 2), INT_TYPES, str_type, check_args=check_fill_args))
+        config.add_method(Method(str_type, 'rjust', (1, 2), INT_TYPES, str_type, check_args=check_fill_args))
+        config.add_method(Method(str_type, 'center', (1, 2), INT_TYPES, str_type, check_args=check_fill_args))
+        config.add_method(Method(str_type, 'zfill', 1, INT_TYPES))
+
+        config.add_method(Method(str_type, 'rstrip', (0, 1), str_type))
+        config.add_method(Method(str_type, 'lstrip', (0, 1), str_type))
+        config.add_method(Method(str_type, 'strip', (0, 1), str_type))
+
+        config.add_method(Method(str_type, 'replace', 2, str_type, str_type))
+
+        # don't optimize split, rsplit, splitlines because the result is a list
+        config.add_method(Method(str_type, 'partition', 1, str_type))
+        config.add_method(Method(str_type, 'rpartition', 1, str_type))
+
+        if PYTHON3 and str_type == BYTES_TYPE:
+            config.add_method(Method(str_type, 'join', 1, (tuple, frozenset), check_args=check_str_join))
+        else:
+            config.add_method(Method(str_type, 'join', 1, (tuple, frozenset) + (str_type,), check_args=check_str_join))
+
+        config.add_method(Method(str_type, 'expandtabs', (0, 1), INT_TYPES))
+        # str methods depend on the locale on Python 2
+        if PYTHON3 or str_type == UNICODE_TYPE:
+            for method in (
+                'capitalize', 'lower', 'upper', 'title', 'swapcase',
+                'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
+                'istitle', 'isupper',
+            ):
+                config.add_method(Method(str_type, method, 0))
+
+        # FIXME: str.format
+        # FIXME: str.translate
+
+    # tuple
+    if sys.version_info >= (2, 6):
+        config.add_method(Method(tuple, 'count', 1, ANY_TYPE))
+        config.add_method(Method(tuple, 'index', 1, ANY_TYPE, check_args=check_index_args))
+
+    # frozenset
+    METHODS = [
+        'copy', 'difference', 'intersection', 'union', 'symmetric_difference',
+        'issubset', 'issuperset',
+    ]
+    if sys.version_info >= (2, 6):
+        METHODS.append('isdisjoint')
+    for method in METHODS:
+        config.add_method(Method(frozenset, method, 1, IMMUTABLE_ITERABLE_TYPES))
+
+    # int
+    for int_type in INT_TYPES:
+        config.add_method(Method(int_type, 'bit_length', 0))
+
+    # float
+    if sys.version_info >= (2,6):
+        config.add_method(Method(float, 'is_integer', 0))
+        config.add_method(Method(float, 'as_integer_ratio', 0))
+        config.add_method(Method(float, 'hex', 0))
+        config.add_func('float.fromhex', Function(float.fromhex, 1, NATIVE_STR))
+

File astoptimizer/config_builtins.py

-"""
-Enable optimizations on the builtins functions (ex: len()) and types (ex:
-unicode.encode()).
-"""
-
-from astoptimizer.compatibility import (
-    PYTHON2, PYTHON3,
-    INT_TYPES, FLOAT_TYPES, COMPLEX_TYPES,
-    NATIVE_STR, BYTES_TYPE, UNICODE_TYPE, STR_TYPES,
-    IMMUTABLE_ITERABLE_TYPES, IMMUTABLE_TYPES)
-from astoptimizer.config import Function, Method, ANY_TYPE
-import codecs
-import sys
-
-def check_ord_args(config, args):
-    arg = args[0]
-    return (len(arg) == 1)
-
-def check_max_args(config, args):
-    arg = args[0]
-    if isinstance(arg, STR_TYPES):
-        return True
-    return all(isinstance(item, COMPLEX_TYPES) for item in arg)
-
-def check_sum_args(config, args):
-    arg = args[0]
-    if not all(isinstance(item, COMPLEX_TYPES) for item in arg):
-        return False
-    if len(args) == 2:
-        if not isinstance(args[1], COMPLEX_TYPES):
-            return False
-    return True
-
-def check_tuple_args(config, args):
-    if len(args) == 0:
-        return True
-    arg = args[0]
-    if not isinstance(arg, IMMUTABLE_ITERABLE_TYPES):
-        return False
-    if len(arg) > config.max_tuple_length:
-        return False
-    return all(isinstance(item, IMMUTABLE_TYPES) for item in arg)
-
-def check_len(config, result):
-    return (result <= config.max_size)
-
-if PYTHON2:
-    def check_str_args(config, args):
-        arg = args[0]
-        if isinstance(arg, UNICODE_TYPE):
-            return all(ord(char) <= 127 for char in arg)
-        else:
-            return True
-
-    def check_unicode_args(config, args):
-        arg = args[0]
-        if isinstance(arg, BYTES_TYPE):
-            return all(ord(byte) <= 127 for byte in arg)
-        else:
-            return True
-
-def check_encoding(encoding):
-    try:
-        encoding = codecs.lookup(encoding).name
-    except LookupError:
-        return False
-    if encoding not in ('ascii', 'iso8859-1', 'utf-8'):
-        return False
-    return True
-
-def check_str_decode_args(config, obj, args):
-    if not check_encoding(args[0]):
-        return False
-    if len(args) == 2:
-        errors = args[1]
-        if errors not in ('strict', 'replace', 'ignore'):
-            return False
-    return True
-
-def check_str_encode_args(config, obj, args):
-    if not check_encoding(args[0]):
-        return False
-    if len(args) == 2:
-        errors = args[1]
-        if errors not in ('strict', 'replace', 'ignore', 'backslashreplace'):
-            return False
-    return True
-
-def check_index_args(config, obj, args):
-    return (args[0] in obj)
-
-def check_pow(config, args):
-    if len(args) >= 3:
-        if not all(isinstance(arg, INT_TYPES) for arg in args[:2]):
-            return False
-
-    num = args[0]
-    exp = args[1]
-    if exp < 1.0 and exp != 0.0 and num < 0:
-        # pow(-25, 0.5) raises a ValueError
-        return False
-    if len(args) >= 3:
-        mod = args[2]
-        if mod == 0:
-            # pow(2, 1024, 0) raises a ValueError('pow() 3rd argument cannot be 0')
-            return False
-    return True
-
-def check_chr(config, args):
-    code = args[0]
-    return 0 <= code <= 0xff
-
-def check_unichr(config, args):
-    code = args[0]
-    if PYTHON3:
-        return 0 <= code <= 0x10ffff
-    else:
-        return 0 <= code <= sys.maxunicode
-
-def check_fill_args(config, obj, args):
-    if len(args) != 2:
-        return True
-    fill = args[1]
-    return len(fill) == 1
-
-def check_str_join(config, obj, args):
-    arg = args[0]
-    str_type = type(obj)
-    if not isinstance(arg, str_type):
-        return all(isinstance(item, str_type) for item in arg)
-    else:
-        return True
-
-def setup_config(config):
-    # pure builtin functions
-    config.add_func('abs', Function(abs, 1, COMPLEX_TYPES))
-    config.add_func('bool', Function(bool, 1, FLOAT_TYPES + STR_TYPES))
-    if PYTHON3:
-        config.add_func('chr', Function(chr, 1, INT_TYPES, check_args=check_unichr))
-    else:
-        config.add_func('chr', Function(chr, 1, INT_TYPES, check_args=check_chr))
-    config.add_func('divmod', Function(divmod, 2, FLOAT_TYPES, FLOAT_TYPES))
-    config.add_func('float', Function(float, 1, FLOAT_TYPES + STR_TYPES, catch=ValueError))
-    config.add_func('int', Function(int, 1, FLOAT_TYPES + STR_TYPES, catch=ValueError))
-    config.add_func('len', Function(len, 1, IMMUTABLE_ITERABLE_TYPES, check_result=check_len))
-    config.add_func('oct', Function(oct, 1, INT_TYPES))
-    config.add_func('ord', Function(ord, 1, STR_TYPES, check_args=check_ord_args))
-    config.add_func('min', Function(min, 1, STR_TYPES + (tuple, frozenset), check_args=check_max_args))
-    config.add_func('max', Function(max, 1, STR_TYPES + (tuple, frozenset), check_args=check_max_args))
-    config.add_func('pow', Function(pow, (2, 3), FLOAT_TYPES, FLOAT_TYPES, FLOAT_TYPES, check_args=check_pow))
-    config.add_func('repr', Function(repr, 1, STR_TYPES + COMPLEX_TYPES))
-    config.add_func('round', Function(round, (1, 2), FLOAT_TYPES, INT_TYPES))
-    if PYTHON3:
-        config.add_func('str', Function(str, 1, COMPLEX_TYPES + (UNICODE_TYPE,)))
-    else:
-        config.add_func('str', Function(str, 1, COMPLEX_TYPES + STR_TYPES, check_args=check_str_args))
-    config.add_func('sum', Function(sum, (1, 2), (tuple, frozenset), COMPLEX_TYPES, check_args=check_sum_args))
-    config.add_func('tuple', Function(tuple, (0, 1), IMMUTABLE_ITERABLE_TYPES, check_args=check_tuple_args))
-
-    if sys.version_info >= (2,6):
-        config.add_func('bin', Function(bin, 1, INT_TYPES))
-    if PYTHON2:
-        config.add_func('long', Function(long, 1, FLOAT_TYPES))
-        config.add_func('unichr', Function(unichr, 1, INT_TYPES, check_args=check_unichr))
-        config.add_func('unicode', Function(unicode, 1, STR_TYPES + COMPLEX_TYPES, check_args=check_unicode_args))
-
-    # bytes, str, unicode
-    config.add_method(Method(BYTES_TYPE, 'decode', (1, 2), NATIVE_STR, NATIVE_STR, check_args=check_str_decode_args))
-    config.add_method(Method(UNICODE_TYPE, 'encode', (1, 2), NATIVE_STR, NATIVE_STR, check_args=check_str_encode_args))
-    for str_type in STR_TYPES:
-        config.add_method(Method(str_type, 'count', 1, str_type))
-        config.add_method(Method(str_type, 'find', 1, str_type))
-        config.add_method(Method(str_type, 'rfind', 1, str_type))
-        config.add_method(Method(str_type, 'index', 1, str_type, check_args=check_index_args))
-        config.add_method(Method(str_type, 'rindex', 1, str_type, check_args=check_index_args))
-
-        config.add_method(Method(str_type, 'startswith', 1, str_type))
-        config.add_method(Method(str_type, 'endswith', 1, str_type))
-
-        config.add_method(Method(str_type, 'ljust', (1, 2), INT_TYPES, str_type, check_args=check_fill_args))
-        config.add_method(Method(str_type, 'rjust', (1, 2), INT_TYPES, str_type, check_args=check_fill_args))
-        config.add_method(Method(str_type, 'center', (1, 2), INT_TYPES, str_type, check_args=check_fill_args))
-        config.add_method(Method(str_type, 'zfill', 1, INT_TYPES))
-
-        config.add_method(Method(str_type, 'rstrip', (0, 1), str_type))
-        config.add_method(Method(str_type, 'lstrip', (0, 1), str_type))
-        config.add_method(Method(str_type, 'strip', (0, 1), str_type))
-
-        config.add_method(Method(str_type, 'replace', 2, str_type, str_type))
-
-        # don't optimize split, rsplit, splitlines because the result is a list
-        config.add_method(Method(str_type, 'partition', 1, str_type))
-        config.add_method(Method(str_type, 'rpartition', 1, str_type))
-
-        if PYTHON3 and str_type == BYTES_TYPE:
-            config.add_method(Method(str_type, 'join', 1, (tuple, frozenset), check_args=check_str_join))
-        else:
-            config.add_method(Method(str_type, 'join', 1, (tuple, frozenset) + (str_type,), check_args=check_str_join))
-
-        config.add_method(Method(str_type, 'expandtabs', (0, 1), INT_TYPES))
-        # str methods depend on the locale on Python 2
-        if PYTHON3 or str_type == UNICODE_TYPE:
-            for method in (
-                'capitalize', 'lower', 'upper', 'title', 'swapcase',
-                'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
-                'istitle', 'isupper',
-            ):
-                config.add_method(Method(str_type, method, 0))
-
-        # FIXME: str.format
-        # FIXME: str.translate
-
-    # tuple
-    if sys.version_info >= (2, 6):
-        config.add_method(Method(tuple, 'count', 1, ANY_TYPE))
-        config.add_method(Method(tuple, 'index', 1, ANY_TYPE, check_args=check_index_args))
-
-    # frozenset
-    METHODS = [
-        'copy', 'difference', 'intersection', 'union', 'symmetric_difference',
-        'issubset', 'issuperset',
-    ]
-    if sys.version_info >= (2, 6):
-        METHODS.append('isdisjoint')
-    for method in METHODS:
-        config.add_method(Method(frozenset, method, 1, IMMUTABLE_ITERABLE_TYPES))
-
-    # int
-    for int_type in INT_TYPES:
-        config.add_method(Method(int_type, 'bit_length', 0))
-
-    # float
-    if sys.version_info >= (2,6):
-        config.add_method(Method(float, 'is_integer', 0))
-        config.add_method(Method(float, 'as_integer_ratio', 0))
-        config.add_method(Method(float, 'hex', 0))
-        config.add_func('float.fromhex', Function(float.fromhex, 1, NATIVE_STR))
-