python-minifier 2.11.2__py2-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. python_minifier/__init__.py +269 -0
  2. python_minifier/__init__.pyi +37 -0
  3. python_minifier/__main__.py +332 -0
  4. python_minifier/ast_compare.py +104 -0
  5. python_minifier/ast_compat.py +40 -0
  6. python_minifier/ast_printer.py +130 -0
  7. python_minifier/expression_printer.py +753 -0
  8. python_minifier/f_string.py +446 -0
  9. python_minifier/ministring.py +179 -0
  10. python_minifier/module_printer.py +862 -0
  11. python_minifier/py.typed +0 -0
  12. python_minifier/rename/__init__.py +6 -0
  13. python_minifier/rename/bind_names.py +192 -0
  14. python_minifier/rename/binding.py +495 -0
  15. python_minifier/rename/mapper.py +175 -0
  16. python_minifier/rename/name_generator.py +51 -0
  17. python_minifier/rename/rename_literals.py +249 -0
  18. python_minifier/rename/renamer.py +230 -0
  19. python_minifier/rename/resolve_names.py +106 -0
  20. python_minifier/rename/util.py +203 -0
  21. python_minifier/token_printer.py +299 -0
  22. python_minifier/transforms/__init__.py +0 -0
  23. python_minifier/transforms/combine_imports.py +76 -0
  24. python_minifier/transforms/constant_folding.py +114 -0
  25. python_minifier/transforms/remove_annotations.py +130 -0
  26. python_minifier/transforms/remove_annotations_options.py +35 -0
  27. python_minifier/transforms/remove_annotations_options.pyi +17 -0
  28. python_minifier/transforms/remove_asserts.py +26 -0
  29. python_minifier/transforms/remove_debug.py +53 -0
  30. python_minifier/transforms/remove_exception_brackets.py +124 -0
  31. python_minifier/transforms/remove_explicit_return_none.py +38 -0
  32. python_minifier/transforms/remove_literal_statements.py +61 -0
  33. python_minifier/transforms/remove_object_base.py +24 -0
  34. python_minifier/transforms/remove_pass.py +26 -0
  35. python_minifier/transforms/remove_posargs.py +13 -0
  36. python_minifier/transforms/suite_transformer.py +196 -0
  37. python_minifier/util.py +48 -0
  38. python_minifier-2.11.2.dist-info/LICENSE +21 -0
  39. python_minifier-2.11.2.dist-info/METADATA +177 -0
  40. python_minifier-2.11.2.dist-info/RECORD +44 -0
  41. python_minifier-2.11.2.dist-info/WHEEL +5 -0
  42. python_minifier-2.11.2.dist-info/entry_points.txt +3 -0
  43. python_minifier-2.11.2.dist-info/top_level.txt +1 -0
  44. python_minifier-2.11.2.dist-info/zip-safe +1 -0
@@ -0,0 +1,104 @@
1
+ import python_minifier.ast_compat as ast
2
+
3
+ from python_minifier.util import is_ast_node
4
+
5
+
6
+ class CompareError(RuntimeError):
7
+ """
8
+ Raised when an AST compares unequal.
9
+ """
10
+
11
+ def __init__(self, lnode, rnode, msg=None):
12
+ self.lnode = lnode
13
+ self.rnode = rnode
14
+ self.msg = msg
15
+
16
+ def __repr__(self):
17
+ return 'NodeError(%r, %r)' % (self.lnode, self.rnode)
18
+
19
+ def namespace(self, node):
20
+ if hasattr(node, 'namespace'):
21
+ if is_ast_node(node.namespace, (ast.FunctionDef, ast.ClassDef, 'AsyncFunctionDef')):
22
+ return self.namespace(node.namespace) + '.' + node.namespace.name
23
+ elif isinstance(node.namespace, ast.Module):
24
+ return ''
25
+ else:
26
+ return repr(node.namespace.__class__)
27
+
28
+ return None
29
+
30
+ def __str__(self):
31
+ error = ''
32
+
33
+ if self.msg:
34
+ error += self.msg
35
+
36
+ if self.namespace(self.lnode):
37
+ error += ' in namespace ' + self.namespace(self.lnode)
38
+
39
+ if self.lnode and hasattr(self.lnode, 'lineno'):
40
+ error += ' at source %i:%i' % (self.lnode.lineno, self.lnode.col_offset)
41
+
42
+ return error
43
+
44
+
45
+ def compare_ast(l_ast, r_ast):
46
+ """
47
+ Compare Python Abstract Syntax Trees
48
+
49
+ >>> compare_ast(l_ast, r_ast)
50
+
51
+ If the AST's are not identical, an exception will be raised.
52
+
53
+ """
54
+
55
+ def counter():
56
+ i = 0
57
+ while True:
58
+ yield i
59
+ i += 1
60
+
61
+ if type(l_ast) != type(r_ast):
62
+ raise CompareError(l_ast, r_ast, msg='Nodes do not match! %r != %r' % (l_ast, r_ast))
63
+
64
+ for field in set(l_ast._fields + r_ast._fields):
65
+
66
+ if field == 'kind' and isinstance(l_ast, ast.Constant):
67
+ continue
68
+
69
+ if isinstance(getattr(l_ast, field, None), list):
70
+
71
+ l_list = getattr(l_ast, field, None)
72
+ r_list = getattr(r_ast, field, None)
73
+
74
+ if len(l_list) != len(r_list):
75
+ raise CompareError(
76
+ l_list,
77
+ r_list,
78
+ 'List does not have the same number of elements! len(%s.%s)=%r, len(%s.%s)=%r'
79
+ % (type(l_ast), field, len(l_list), type(r_ast), field, len(r_list)),
80
+ )
81
+
82
+ for i, l, r in zip(counter(), l_list, r_list):
83
+ if isinstance(l, ast.AST) or isinstance(r, ast.AST):
84
+ compare_ast(l, r)
85
+ elif l != r:
86
+ raise CompareError(
87
+ l_ast,
88
+ r_ast,
89
+ 'Fields do not match! %s.%s[%i]=%r, %s.%s[%i]=%r'
90
+ % (type(l_ast), field, i, l, type(r_ast), field, i, r),
91
+ )
92
+
93
+ else:
94
+ l = getattr(l_ast, field, None)
95
+ r = getattr(r_ast, field, None)
96
+
97
+ if isinstance(l, ast.AST) or isinstance(r, ast.AST):
98
+ compare_ast(l, r)
99
+ elif l != r:
100
+ raise CompareError(
101
+ l_ast,
102
+ r_ast,
103
+ 'Fields do not match! %s.%s=%r, %s.%s=%r' % (type(l_ast), field, l, type(r_ast), field, r),
104
+ )
@@ -0,0 +1,40 @@
1
+ """
2
+ The is a backwards compatible shim for the ast module.
3
+
4
+ This is the best way to make the ast module work the same in both python 2 and 3.
5
+ This is essentially what the ast module was doing until 3.12, when it started throwing
6
+ deprecation warnings.
7
+ """
8
+
9
+ from ast import *
10
+
11
+ # Ideally we don't import anything else
12
+
13
+ if 'TypeAlias' in globals():
14
+
15
+ # Add n and s properties to Constant so it can stand in for Num, Str and Bytes
16
+ Constant.n = property(lambda self: self.value, lambda self, value: setattr(self, 'value', value)) # type: ignore[assignment]
17
+ Constant.s = property(lambda self: self.value, lambda self, value: setattr(self, 'value', value)) # type: ignore[assignment]
18
+
19
+ # These classes are redefined from the ones in ast that complain about deprecation
20
+ # They will continue to work once they are removed from ast
21
+
22
+ class Str(Constant): # type: ignore[no-redef]
23
+ def __new__(cls, s, *args, **kwargs):
24
+ return Constant(value=s, *args, **kwargs)
25
+
26
+ class Bytes(Constant): # type: ignore[no-redef]
27
+ def __new__(cls, s, *args, **kwargs):
28
+ return Constant(value=s, *args, **kwargs)
29
+
30
+ class Num(Constant): # type: ignore[no-redef]
31
+ def __new__(cls, n, *args, **kwargs):
32
+ return Constant(value=n, *args, **kwargs)
33
+
34
+ class NameConstant(Constant): # type: ignore[no-redef]
35
+ def __new__(cls, *args, **kwargs):
36
+ return Constant(*args, **kwargs)
37
+
38
+ class Ellipsis(Constant): # type: ignore[no-redef]
39
+ def __new__(cls, *args, **kwargs):
40
+ return Constant(value=literal_eval('...'), *args, **kwargs)
@@ -0,0 +1,130 @@
1
+ """
2
+ Print a representation of an AST
3
+
4
+ This prints a human readable representation of the nodes in the AST.
5
+ The goal is to make it easy to see what the AST looks like, and to
6
+ make it easy to compare two ASTs.
7
+
8
+ This is not intended to be a complete representation of the AST, some
9
+ fields or field names may be omitted for clarity. It should still be precise and unambiguous.
10
+
11
+ """
12
+
13
+ import python_minifier.ast_compat as ast
14
+
15
+ from python_minifier.util import is_ast_node
16
+
17
+ INDENT = ' '
18
+
19
+ # The field name that can be omitted for each node
20
+ # Either it's the only field or would otherwise be obvious
21
+ default_fields = {
22
+ 'Constant': 'value',
23
+ 'Num': 'n',
24
+ 'Str': 's',
25
+ 'Bytes': 's',
26
+ 'NameConstant': 'value',
27
+ 'FormattedValue': 'value',
28
+ 'JoinedStr': 'values',
29
+ 'List': 'elts',
30
+ 'Tuple': 'elts',
31
+ 'Set': 'elts',
32
+ 'Name': 'id',
33
+ 'Expr': 'value',
34
+ 'UnaryOp': 'op',
35
+ 'BinOp': 'op',
36
+ 'BoolOp': 'op',
37
+ 'Call': 'func',
38
+ 'Index': 'value',
39
+ 'ExtSlice': 'dims',
40
+ 'Assert': 'test',
41
+ 'Delete': 'targets',
42
+ 'Import': 'names',
43
+ 'If': 'test',
44
+ 'While': 'test',
45
+ 'Try': 'handlers',
46
+ 'TryExcept': 'handlers',
47
+ 'With': 'items',
48
+ 'withitem': 'context_expr',
49
+ 'FunctionDef': 'name',
50
+ 'arg': 'arg',
51
+ 'Return': 'value',
52
+ 'Yield': 'value',
53
+ 'YieldFrom': 'value',
54
+ 'Global': 'names',
55
+ 'Nonlocal': 'names',
56
+ 'ClassDef': 'name',
57
+ 'AsyncFunctionDef': 'name',
58
+ 'Await': 'value',
59
+ 'AsyncWith': 'items',
60
+ 'Raise': 'exc',
61
+ 'Subscript': 'value',
62
+ 'Attribute': 'value',
63
+ 'AugAssign': 'op',
64
+ }
65
+
66
+ def is_literal(node, field):
67
+ if hasattr(ast, 'Constant') and isinstance(node, ast.Constant) and field == 'value':
68
+ return True
69
+
70
+ if is_ast_node(node, ast.Num) and field == 'n':
71
+ return True
72
+
73
+ if is_ast_node(node, ast.Str) and field == 's':
74
+ return True
75
+
76
+ if is_ast_node(node, 'Bytes') and field == 's':
77
+ return True
78
+
79
+ if is_ast_node(node, 'NameConstant') and field == 'value':
80
+ return True
81
+
82
+ return False
83
+
84
+ def print_ast(node):
85
+ if not isinstance(node, ast.AST):
86
+ return repr(node)
87
+
88
+ s = ''
89
+
90
+ node_name = node.__class__.__name__
91
+ s += node_name
92
+ s += '('
93
+
94
+ first = True
95
+ for field, value in ast.iter_fields(node):
96
+ if not value and not is_literal(node, field):
97
+ # Don't bother printing fields that are empty, except for literals
98
+ continue
99
+
100
+ if field == 'ctx':
101
+ # Don't print the ctx, it's always apparent from context
102
+ continue
103
+
104
+ if first:
105
+ first = False
106
+ else:
107
+ s += ', '
108
+
109
+ if default_fields.get(node_name) != field:
110
+ s += field + '='
111
+
112
+ if isinstance(value, ast.AST):
113
+ s += print_ast(value)
114
+ elif isinstance(value, list):
115
+ s += '['
116
+ first_list = True
117
+ for item in value:
118
+ if first_list:
119
+ first_list = False
120
+ else:
121
+ s += ','
122
+
123
+ for line in print_ast(item).splitlines():
124
+ s += '\n' + INDENT + line
125
+ s += '\n]'
126
+ else:
127
+ s += repr(value)
128
+
129
+ s += ')'
130
+ return s