python-minifier 2.11.2__py2-none-any.whl → 3.0.0__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.
- python_minifier/__init__.py +14 -9
- python_minifier/__init__.pyi +8 -3
- python_minifier/__main__.py +77 -15
- python_minifier/ast_annotation/__init__.py +82 -0
- python_minifier/ast_compare.py +12 -14
- python_minifier/ast_compat.py +38 -0
- python_minifier/ast_printer.py +8 -5
- python_minifier/expression_printer.py +14 -13
- python_minifier/f_string.py +44 -45
- python_minifier/ministring.py +3 -3
- python_minifier/module_printer.py +19 -16
- python_minifier/rename/__init__.py +1 -1
- python_minifier/rename/bind_names.py +2 -1
- python_minifier/rename/binding.py +39 -40
- python_minifier/rename/mapper.py +66 -50
- python_minifier/rename/rename_literals.py +17 -15
- python_minifier/rename/renamer.py +26 -28
- python_minifier/rename/resolve_names.py +8 -7
- python_minifier/rename/util.py +7 -5
- python_minifier/token_printer.py +12 -1
- python_minifier/transforms/combine_imports.py +0 -1
- python_minifier/transforms/constant_folding.py +16 -10
- python_minifier/transforms/remove_annotations.py +18 -16
- python_minifier/transforms/remove_annotations_options.py +3 -1
- python_minifier/transforms/remove_annotations_options.pyi +8 -7
- python_minifier/transforms/remove_asserts.py +1 -2
- python_minifier/transforms/remove_debug.py +4 -3
- python_minifier/transforms/remove_exception_brackets.py +12 -7
- python_minifier/transforms/remove_explicit_return_none.py +5 -4
- python_minifier/transforms/remove_literal_statements.py +5 -6
- python_minifier/transforms/remove_object_base.py +2 -1
- python_minifier/transforms/remove_pass.py +1 -2
- python_minifier/transforms/remove_posargs.py +3 -4
- python_minifier/transforms/suite_transformer.py +6 -5
- python_minifier/util.py +12 -18
- {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/METADATA +2 -2
- python_minifier-3.0.0.dist-info/RECORD +45 -0
- python_minifier-2.11.2.dist-info/RECORD +0 -44
- {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/LICENSE +0 -0
- {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/WHEEL +0 -0
- {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/entry_points.txt +0 -0
- {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/top_level.txt +0 -0
- {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/zip-safe +0 -0
python_minifier/rename/mapper.py
CHANGED
|
@@ -3,48 +3,47 @@ For each node in an AST set the namespace to use for name binding and resolution
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import python_minifier.ast_compat as ast
|
|
6
|
+
from python_minifier.ast_annotation import get_parent
|
|
6
7
|
|
|
7
8
|
from python_minifier.rename.util import is_namespace
|
|
8
|
-
from python_minifier.util import is_ast_node
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def add_parent_to_arguments(arguments, func):
|
|
12
|
-
arguments.parent = func
|
|
13
12
|
arguments.namespace = func
|
|
14
13
|
|
|
15
14
|
for arg in getattr(arguments, 'posonlyargs', []) + arguments.args:
|
|
16
|
-
add_parent(arg,
|
|
15
|
+
add_parent(arg, func)
|
|
17
16
|
if hasattr(arg, 'annotation') and arg.annotation is not None:
|
|
18
|
-
add_parent(arg.annotation,
|
|
17
|
+
add_parent(arg.annotation, func.namespace)
|
|
19
18
|
|
|
20
19
|
if hasattr(arguments, 'kwonlyargs'):
|
|
21
20
|
for arg in arguments.kwonlyargs:
|
|
22
|
-
add_parent(arg,
|
|
21
|
+
add_parent(arg, func)
|
|
23
22
|
if arg.annotation is not None:
|
|
24
|
-
add_parent(arg.annotation,
|
|
23
|
+
add_parent(arg.annotation, func.namespace)
|
|
25
24
|
|
|
26
25
|
for node in arguments.kw_defaults:
|
|
27
26
|
if node is not None:
|
|
28
|
-
add_parent(node,
|
|
27
|
+
add_parent(node, func.namespace)
|
|
29
28
|
|
|
30
29
|
for node in arguments.defaults:
|
|
31
|
-
add_parent(node,
|
|
30
|
+
add_parent(node, func.namespace)
|
|
32
31
|
|
|
33
32
|
if arguments.vararg:
|
|
34
33
|
if hasattr(arguments, 'varargannotation') and arguments.varargannotation is not None:
|
|
35
|
-
add_parent(arguments.varargannotation,
|
|
34
|
+
add_parent(arguments.varargannotation, func.namespace)
|
|
36
35
|
elif isinstance(arguments.vararg, str):
|
|
37
36
|
pass
|
|
38
37
|
else:
|
|
39
|
-
add_parent(arguments.vararg,
|
|
38
|
+
add_parent(arguments.vararg, func)
|
|
40
39
|
|
|
41
40
|
if arguments.kwarg:
|
|
42
41
|
if hasattr(arguments, 'kwargannotation') and arguments.kwargannotation is not None:
|
|
43
|
-
add_parent(arguments.kwargannotation,
|
|
42
|
+
add_parent(arguments.kwargannotation, func.namespace)
|
|
44
43
|
elif isinstance(arguments.kwarg, str):
|
|
45
44
|
pass
|
|
46
45
|
else:
|
|
47
|
-
add_parent(arguments.kwarg,
|
|
46
|
+
add_parent(arguments.kwarg, func)
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
def add_parent_to_functiondef(functiondef):
|
|
@@ -56,17 +55,17 @@ def add_parent_to_functiondef(functiondef):
|
|
|
56
55
|
add_parent_to_arguments(functiondef.args, func=functiondef)
|
|
57
56
|
|
|
58
57
|
for node in functiondef.body:
|
|
59
|
-
add_parent(node,
|
|
58
|
+
add_parent(node, namespace=functiondef)
|
|
60
59
|
|
|
61
60
|
for node in functiondef.decorator_list:
|
|
62
|
-
add_parent(node,
|
|
61
|
+
add_parent(node, namespace=functiondef.namespace)
|
|
63
62
|
|
|
64
63
|
if hasattr(functiondef, 'type_params') and functiondef.type_params is not None:
|
|
65
64
|
for node in functiondef.type_params:
|
|
66
|
-
add_parent(node,
|
|
65
|
+
add_parent(node, namespace=functiondef.namespace)
|
|
67
66
|
|
|
68
67
|
if hasattr(functiondef, 'returns') and functiondef.returns is not None:
|
|
69
|
-
add_parent(functiondef.returns,
|
|
68
|
+
add_parent(functiondef.returns, namespace=functiondef.namespace)
|
|
70
69
|
|
|
71
70
|
|
|
72
71
|
def add_parent_to_classdef(classdef):
|
|
@@ -75,64 +74,77 @@ def add_parent_to_classdef(classdef):
|
|
|
75
74
|
"""
|
|
76
75
|
|
|
77
76
|
for node in classdef.bases:
|
|
78
|
-
add_parent(node,
|
|
77
|
+
add_parent(node, namespace=classdef.namespace)
|
|
79
78
|
|
|
80
79
|
if hasattr(classdef, 'keywords'):
|
|
81
80
|
for node in classdef.keywords:
|
|
82
|
-
add_parent(node,
|
|
81
|
+
add_parent(node, namespace=classdef.namespace)
|
|
83
82
|
|
|
84
83
|
if hasattr(classdef, 'starargs') and classdef.starargs is not None:
|
|
85
|
-
add_parent(classdef.starargs,
|
|
84
|
+
add_parent(classdef.starargs, namespace=classdef.namespace)
|
|
86
85
|
|
|
87
86
|
if hasattr(classdef, 'kwargs') and classdef.kwargs is not None:
|
|
88
|
-
add_parent(classdef.kwargs,
|
|
87
|
+
add_parent(classdef.kwargs, namespace=classdef.namespace)
|
|
89
88
|
|
|
90
89
|
for node in classdef.body:
|
|
91
|
-
add_parent(node,
|
|
90
|
+
add_parent(node, namespace=classdef)
|
|
92
91
|
|
|
93
92
|
for node in classdef.decorator_list:
|
|
94
|
-
add_parent(node,
|
|
93
|
+
add_parent(node, namespace=classdef.namespace)
|
|
95
94
|
|
|
96
95
|
if hasattr(classdef, 'type_params') and classdef.type_params is not None:
|
|
97
96
|
for node in classdef.type_params:
|
|
98
|
-
add_parent(node,
|
|
97
|
+
add_parent(node, namespace=classdef.namespace)
|
|
98
|
+
|
|
99
99
|
|
|
100
100
|
def add_parent_to_comprehension(node, namespace):
|
|
101
|
-
assert
|
|
101
|
+
assert isinstance(node, (ast.GeneratorExp, ast.SetComp, ast.DictComp, ast.ListComp))
|
|
102
102
|
|
|
103
103
|
if hasattr(node, 'elt'):
|
|
104
|
-
add_parent(node.elt,
|
|
104
|
+
add_parent(node.elt, namespace=node)
|
|
105
105
|
elif hasattr(node, 'key'):
|
|
106
|
-
add_parent(node.key,
|
|
107
|
-
add_parent(node.value,
|
|
106
|
+
add_parent(node.key, namespace=node)
|
|
107
|
+
add_parent(node.value, namespace=node)
|
|
108
108
|
|
|
109
109
|
iter_namespace = namespace
|
|
110
110
|
for generator in node.generators:
|
|
111
|
-
generator.parent = node
|
|
112
111
|
generator.namespace = node
|
|
113
112
|
|
|
114
|
-
add_parent(generator.target,
|
|
115
|
-
add_parent(generator.iter,
|
|
116
|
-
|
|
113
|
+
add_parent(generator.target, namespace=node)
|
|
114
|
+
add_parent(generator.iter, namespace=iter_namespace)
|
|
115
|
+
|
|
117
116
|
for if_ in generator.ifs:
|
|
118
|
-
add_parent(if_,
|
|
117
|
+
add_parent(if_, namespace=node)
|
|
119
118
|
|
|
119
|
+
iter_namespace = node
|
|
120
120
|
|
|
121
|
-
def
|
|
121
|
+
def namedexpr_namespace(node):
|
|
122
|
+
"""
|
|
123
|
+
Get the namespace for a NamedExpr target
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
if not isinstance(node, (ast.ListComp, ast.DictComp, ast.SetComp, ast.GeneratorExp)):
|
|
127
|
+
return node
|
|
128
|
+
|
|
129
|
+
return namedexpr_namespace(node.namespace)
|
|
130
|
+
|
|
131
|
+
def add_parent_to_namedexpr(node):
|
|
132
|
+
assert isinstance(node, ast.NamedExpr)
|
|
133
|
+
|
|
134
|
+
add_parent(node.target, namespace=namedexpr_namespace(node.namespace))
|
|
135
|
+
add_parent(node.value, namespace=node.namespace)
|
|
136
|
+
|
|
137
|
+
def add_parent(node, namespace=None):
|
|
122
138
|
"""
|
|
123
|
-
Add a parent attribute to child nodes
|
|
124
139
|
Add a namespace attribute to child nodes
|
|
125
140
|
|
|
126
|
-
:param node: The tree to add
|
|
141
|
+
:param node: The tree to add namespace properties to
|
|
127
142
|
:type node: :class:`ast.AST`
|
|
128
|
-
:param parent: The parent node of this node
|
|
129
|
-
:type parent: :class:`ast.AST`
|
|
130
143
|
:param namespace: The namespace Node that this node is in
|
|
131
144
|
:type namespace: ast.Lambda or ast.Module or ast.FunctionDef or ast.AsyncFunctionDef or ast.ClassDef or ast.DictComp or ast.SetComp or ast.ListComp or ast.Generator
|
|
132
145
|
|
|
133
146
|
"""
|
|
134
147
|
|
|
135
|
-
node.parent = parent if parent is not None else node
|
|
136
148
|
node.namespace = namespace if namespace is not None else node
|
|
137
149
|
|
|
138
150
|
if is_namespace(node):
|
|
@@ -140,35 +152,39 @@ def add_parent(node, parent=None, namespace=None):
|
|
|
140
152
|
node.global_names = set()
|
|
141
153
|
node.nonlocal_names = set()
|
|
142
154
|
|
|
143
|
-
if
|
|
155
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
144
156
|
add_parent_to_functiondef(node)
|
|
145
|
-
elif
|
|
157
|
+
elif isinstance(node, (ast.GeneratorExp, ast.SetComp, ast.DictComp, ast.ListComp)):
|
|
146
158
|
add_parent_to_comprehension(node, namespace=namespace)
|
|
147
159
|
elif isinstance(node, ast.Lambda):
|
|
148
160
|
add_parent_to_arguments(node.args, func=node)
|
|
149
|
-
add_parent(node.body,
|
|
161
|
+
add_parent(node.body, namespace=node)
|
|
150
162
|
elif isinstance(node, ast.ClassDef):
|
|
151
163
|
add_parent_to_classdef(node)
|
|
152
164
|
else:
|
|
153
165
|
for child in ast.iter_child_nodes(node):
|
|
154
|
-
add_parent(child,
|
|
166
|
+
add_parent(child, namespace=node)
|
|
155
167
|
|
|
156
168
|
return
|
|
157
169
|
|
|
158
170
|
if isinstance(node, ast.Global):
|
|
159
171
|
namespace.global_names.update(node.names)
|
|
160
|
-
if
|
|
172
|
+
if isinstance(node, ast.Nonlocal):
|
|
161
173
|
namespace.nonlocal_names.update(node.names)
|
|
162
174
|
|
|
163
|
-
if isinstance(node, ast.Name):
|
|
164
|
-
if isinstance(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
175
|
+
if isinstance(node, ast.Name) and isinstance(namespace, ast.ClassDef):
|
|
176
|
+
if isinstance(node.ctx, ast.Load):
|
|
177
|
+
namespace.nonlocal_names.add(node.id)
|
|
178
|
+
elif isinstance(node.ctx, ast.Store) and isinstance(get_parent(node), ast.AugAssign):
|
|
179
|
+
namespace.nonlocal_names.add(node.id)
|
|
180
|
+
|
|
181
|
+
if isinstance(node, ast.NamedExpr):
|
|
182
|
+
# NamedExpr is 'special'
|
|
183
|
+
add_parent_to_namedexpr(node)
|
|
184
|
+
return
|
|
169
185
|
|
|
170
186
|
for child in ast.iter_child_nodes(node):
|
|
171
|
-
add_parent(child,
|
|
187
|
+
add_parent(child, namespace=namespace)
|
|
172
188
|
|
|
173
189
|
|
|
174
190
|
def add_namespace(module):
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import python_minifier.ast_compat as ast
|
|
2
|
+
from python_minifier.ast_annotation import get_parent, set_parent
|
|
2
3
|
|
|
3
4
|
from python_minifier.rename.binding import Binding
|
|
4
5
|
from python_minifier.rename.util import insert
|
|
5
6
|
from python_minifier.transforms.suite_transformer import NodeVisitor
|
|
6
|
-
from python_minifier.util import
|
|
7
|
+
from python_minifier.util import is_constant_node
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def replace(old_node, new_node):
|
|
10
|
-
parent = old_node
|
|
11
|
-
new_node
|
|
11
|
+
parent = get_parent(old_node)
|
|
12
|
+
set_parent(new_node, parent)
|
|
12
13
|
new_node.namespace = old_node.namespace
|
|
13
14
|
|
|
14
15
|
for field, old_value in ast.iter_fields(parent):
|
|
@@ -43,7 +44,7 @@ class HoistedBinding(Binding):
|
|
|
43
44
|
|
|
44
45
|
@property
|
|
45
46
|
def value(self):
|
|
46
|
-
if
|
|
47
|
+
if is_constant_node(self._value_node, (ast.Str, ast.Bytes)):
|
|
47
48
|
return self._value_node.s
|
|
48
49
|
else:
|
|
49
50
|
return self._value_node.value
|
|
@@ -84,6 +85,7 @@ class HoistedBinding(Binding):
|
|
|
84
85
|
|
|
85
86
|
return rename_cost <= current_cost
|
|
86
87
|
|
|
88
|
+
|
|
87
89
|
class HoistedValue(object):
|
|
88
90
|
"""
|
|
89
91
|
HoistedValue comparator object
|
|
@@ -132,7 +134,7 @@ class HoistLiterals(NodeVisitor):
|
|
|
132
134
|
|
|
133
135
|
"""
|
|
134
136
|
|
|
135
|
-
if
|
|
137
|
+
if isinstance(node.namespace, (ast.FunctionDef, ast.Module, ast.AsyncFunctionDef)):
|
|
136
138
|
return node.namespace
|
|
137
139
|
return self.nearest_function_namespace(node.namespace)
|
|
138
140
|
|
|
@@ -154,18 +156,18 @@ class HoistLiterals(NodeVisitor):
|
|
|
154
156
|
|
|
155
157
|
"""
|
|
156
158
|
|
|
157
|
-
|
|
159
|
+
path = []
|
|
158
160
|
|
|
159
161
|
while True:
|
|
160
162
|
namespace = self.nearest_function_namespace(node)
|
|
161
|
-
|
|
163
|
+
path.insert(0, namespace)
|
|
162
164
|
|
|
163
165
|
if isinstance(namespace, ast.Module):
|
|
164
166
|
break
|
|
165
167
|
|
|
166
168
|
node = namespace
|
|
167
169
|
|
|
168
|
-
return
|
|
170
|
+
return path
|
|
169
171
|
|
|
170
172
|
def common_path(self, n1_path, n2_path):
|
|
171
173
|
|
|
@@ -201,7 +203,7 @@ class HoistLiterals(NodeVisitor):
|
|
|
201
203
|
|
|
202
204
|
def visit_Str(self, node):
|
|
203
205
|
|
|
204
|
-
if isinstance(node
|
|
206
|
+
if isinstance(get_parent(node), ast.Expr):
|
|
205
207
|
# This is literal statement
|
|
206
208
|
# The RemoveLiteralStatements transformer must have left it here, so ignore it.
|
|
207
209
|
return
|
|
@@ -213,11 +215,10 @@ class HoistLiterals(NodeVisitor):
|
|
|
213
215
|
|
|
214
216
|
def visit_JoinedStr(self, node):
|
|
215
217
|
for v in node.values:
|
|
216
|
-
if
|
|
218
|
+
if is_constant_node(v, ast.Str):
|
|
217
219
|
# Can't hoist this!
|
|
218
220
|
continue
|
|
219
|
-
|
|
220
|
-
self.visit(v)
|
|
221
|
+
self.visit(v)
|
|
221
222
|
|
|
222
223
|
def visit_NameConstant(self, node):
|
|
223
224
|
self.get_binding(node.value, node).add_reference(node)
|
|
@@ -235,15 +236,16 @@ class HoistLiterals(NodeVisitor):
|
|
|
235
236
|
if not self._ignore_slots:
|
|
236
237
|
return self.generic_visit(node)
|
|
237
238
|
|
|
238
|
-
if not
|
|
239
|
+
if not isinstance(node.namespace, ast.ClassDef):
|
|
239
240
|
return self.generic_visit(node)
|
|
240
241
|
|
|
241
242
|
for target in node.targets:
|
|
242
|
-
if
|
|
243
|
+
if isinstance(target, ast.Name) and target.id == '__slots__':
|
|
243
244
|
# This is a __slots__ assignment, don't hoist the literals
|
|
244
|
-
return
|
|
245
|
+
return None
|
|
245
246
|
|
|
246
247
|
return self.generic_visit(node)
|
|
247
248
|
|
|
249
|
+
|
|
248
250
|
def rename_literals(module):
|
|
249
251
|
HoistLiterals()(module)
|
|
@@ -55,7 +55,7 @@ def reservation_scope(namespace, binding):
|
|
|
55
55
|
|
|
56
56
|
"""
|
|
57
57
|
|
|
58
|
-
namespaces =
|
|
58
|
+
namespaces = {namespace}
|
|
59
59
|
|
|
60
60
|
for node in binding.references:
|
|
61
61
|
while node is not namespace:
|
|
@@ -112,7 +112,7 @@ class UniqueNameAssigner(object):
|
|
|
112
112
|
def __call__(self, module):
|
|
113
113
|
assert isinstance(module, ast.Module)
|
|
114
114
|
|
|
115
|
-
for
|
|
115
|
+
for _namespace, binding in sorted_bindings(module):
|
|
116
116
|
if binding.allow_rename:
|
|
117
117
|
binding.new_name = self.available_name()
|
|
118
118
|
|
|
@@ -154,6 +154,8 @@ class NameAssigner(object):
|
|
|
154
154
|
if self.is_available(prefix + name, reservation_scope):
|
|
155
155
|
return prefix + name
|
|
156
156
|
|
|
157
|
+
return None
|
|
158
|
+
|
|
157
159
|
def is_available(self, name, reservation_scope):
|
|
158
160
|
"""
|
|
159
161
|
Is a name unreserved in a reservation scope
|
|
@@ -165,11 +167,7 @@ class NameAssigner(object):
|
|
|
165
167
|
|
|
166
168
|
"""
|
|
167
169
|
|
|
168
|
-
for namespace in reservation_scope
|
|
169
|
-
if name in namespace.assigned_names:
|
|
170
|
-
return False
|
|
171
|
-
|
|
172
|
-
return True
|
|
170
|
+
return all(name not in namespace.assigned_names for namespace in reservation_scope)
|
|
173
171
|
|
|
174
172
|
def __call__(self, module, prefix_globals, reserved_globals=None):
|
|
175
173
|
assert isinstance(module, ast.Module)
|
|
@@ -184,6 +182,26 @@ class NameAssigner(object):
|
|
|
184
182
|
for name in reserved_globals:
|
|
185
183
|
module.assigned_names.add(name)
|
|
186
184
|
|
|
185
|
+
def should_rename(binding, name, scope):
|
|
186
|
+
if binding.should_rename(name):
|
|
187
|
+
return True
|
|
188
|
+
|
|
189
|
+
# It's no longer efficient to do this rename
|
|
190
|
+
|
|
191
|
+
if isinstance(binding, NameBinding):
|
|
192
|
+
# Check that the original name is still available
|
|
193
|
+
|
|
194
|
+
if binding.reserved == binding.name:
|
|
195
|
+
# We already reserved it (this is probably an arg)
|
|
196
|
+
return False
|
|
197
|
+
|
|
198
|
+
if not self.is_available(binding.name, scope):
|
|
199
|
+
# The original name has already been assigned to another binding,
|
|
200
|
+
# so we need to rename this anyway.
|
|
201
|
+
return True
|
|
202
|
+
|
|
203
|
+
return False
|
|
204
|
+
|
|
187
205
|
for namespace, binding in sorted_bindings(module):
|
|
188
206
|
scope = reservation_scope(namespace, binding)
|
|
189
207
|
|
|
@@ -194,27 +212,7 @@ class NameAssigner(object):
|
|
|
194
212
|
else:
|
|
195
213
|
name = self.available_name(scope)
|
|
196
214
|
|
|
197
|
-
|
|
198
|
-
if binding.should_rename(name):
|
|
199
|
-
return True
|
|
200
|
-
|
|
201
|
-
# It's no longer efficient to do this rename
|
|
202
|
-
|
|
203
|
-
if isinstance(binding, NameBinding):
|
|
204
|
-
# Check that the original name is still available
|
|
205
|
-
|
|
206
|
-
if binding.reserved == binding.name:
|
|
207
|
-
# We already reserved it (this is probably an arg)
|
|
208
|
-
return False
|
|
209
|
-
|
|
210
|
-
if not self.is_available(binding.name, scope):
|
|
211
|
-
# The original name has already been assigned to another binding,
|
|
212
|
-
# so we need to rename this anyway.
|
|
213
|
-
return True
|
|
214
|
-
|
|
215
|
-
return False
|
|
216
|
-
|
|
217
|
-
if should_rename():
|
|
215
|
+
if should_rename(binding, name, scope):
|
|
218
216
|
binding.rename(name)
|
|
219
217
|
else:
|
|
220
218
|
# Any existing name will become reserved
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import python_minifier.ast_compat as ast
|
|
2
2
|
|
|
3
3
|
from python_minifier.rename.binding import BuiltinBinding, NameBinding
|
|
4
|
-
from python_minifier.rename.util import get_global_namespace, get_nonlocal_namespace
|
|
5
|
-
from python_minifier.util import is_ast_node
|
|
4
|
+
from python_minifier.rename.util import builtins, get_global_namespace, get_nonlocal_namespace
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def get_binding(name, namespace):
|
|
@@ -34,6 +33,7 @@ def get_binding(name, namespace):
|
|
|
34
33
|
namespace.bindings.append(binding)
|
|
35
34
|
return binding
|
|
36
35
|
|
|
36
|
+
|
|
37
37
|
def get_binding_disallow_class_namespace_rename(name, namespace):
|
|
38
38
|
binding = get_binding(name, namespace)
|
|
39
39
|
|
|
@@ -43,6 +43,7 @@ def get_binding_disallow_class_namespace_rename(name, namespace):
|
|
|
43
43
|
|
|
44
44
|
return binding
|
|
45
45
|
|
|
46
|
+
|
|
46
47
|
def resolve_names(node):
|
|
47
48
|
"""
|
|
48
49
|
Resolve unbound names to a NameBinding
|
|
@@ -65,7 +66,7 @@ def resolve_names(node):
|
|
|
65
66
|
binding = get_binding_disallow_class_namespace_rename(node.name, node.namespace)
|
|
66
67
|
binding.add_reference(node)
|
|
67
68
|
|
|
68
|
-
elif
|
|
69
|
+
elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name in node.namespace.nonlocal_names:
|
|
69
70
|
binding = get_binding_disallow_class_namespace_rename(node.name, node.namespace)
|
|
70
71
|
binding.add_reference(node)
|
|
71
72
|
|
|
@@ -91,15 +92,15 @@ def resolve_names(node):
|
|
|
91
92
|
if isinstance(node.name, str) and node.name in node.namespace.nonlocal_names:
|
|
92
93
|
get_binding_disallow_class_namespace_rename(node.name, node.namespace).add_reference(node)
|
|
93
94
|
|
|
94
|
-
elif
|
|
95
|
+
elif isinstance(node, ast.Nonlocal):
|
|
95
96
|
for name in node.names:
|
|
96
97
|
get_binding_disallow_class_namespace_rename(name, node.namespace).add_reference(node)
|
|
97
|
-
elif
|
|
98
|
+
elif isinstance(node, (ast.MatchAs, ast.MatchStar)) and node.name in node.namespace.nonlocal_names:
|
|
98
99
|
get_binding_disallow_class_namespace_rename(node.name, node.namespace).add_reference(node)
|
|
99
|
-
elif
|
|
100
|
+
elif isinstance(node, ast.MatchMapping) and node.rest in node.namespace.nonlocal_names:
|
|
100
101
|
get_binding_disallow_class_namespace_rename(node.rest, node.namespace).add_reference(node)
|
|
101
102
|
|
|
102
|
-
elif
|
|
103
|
+
elif isinstance(node, ast.Exec):
|
|
103
104
|
get_global_namespace(node).tainted = True
|
|
104
105
|
|
|
105
106
|
for child in ast.iter_child_nodes(node):
|
python_minifier/rename/util.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import python_minifier.ast_compat as ast
|
|
2
1
|
import sys
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
import python_minifier.ast_compat as ast
|
|
4
|
+
|
|
5
|
+
from python_minifier.util import is_constant_node
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def create_is_namespace():
|
|
@@ -32,6 +33,7 @@ def iter_child_namespaces(node):
|
|
|
32
33
|
for c in iter_child_namespaces(child):
|
|
33
34
|
yield c
|
|
34
35
|
|
|
36
|
+
|
|
35
37
|
def get_global_namespace(node):
|
|
36
38
|
"""
|
|
37
39
|
Return the global namespace for a node
|
|
@@ -125,7 +127,7 @@ def insert(suite, new_node):
|
|
|
125
127
|
|
|
126
128
|
if not inserted:
|
|
127
129
|
if (isinstance(node, ast.ImportFrom) and node.module == '__future__') or (
|
|
128
|
-
isinstance(node, ast.Expr) and
|
|
130
|
+
isinstance(node, ast.Expr) and is_constant_node(node.value, ast.Str)
|
|
129
131
|
):
|
|
130
132
|
pass
|
|
131
133
|
else:
|
|
@@ -164,7 +166,7 @@ def find__all__(module):
|
|
|
164
166
|
if isinstance(name, ast.Name) and name.id == '__all__':
|
|
165
167
|
return True
|
|
166
168
|
|
|
167
|
-
elif
|
|
169
|
+
elif isinstance(node, (ast.AugAssign, ast.AnnAssign)):
|
|
168
170
|
if isinstance(node.target, ast.Name) and node.target.id == '__all__':
|
|
169
171
|
return True
|
|
170
172
|
|
|
@@ -178,7 +180,7 @@ def find__all__(module):
|
|
|
178
180
|
continue
|
|
179
181
|
|
|
180
182
|
for el in node.value.elts:
|
|
181
|
-
if
|
|
183
|
+
if is_constant_node(el, ast.Str):
|
|
182
184
|
names.append(el.s)
|
|
183
185
|
|
|
184
186
|
return names
|
python_minifier/token_printer.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import re
|
|
4
4
|
import sys
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
class TokenTypes(object):
|
|
7
8
|
NoToken = 0
|
|
8
9
|
Identifier = 1
|
|
@@ -15,6 +16,7 @@ class TokenTypes(object):
|
|
|
15
16
|
NewLine = 8
|
|
16
17
|
EndStatement = 9
|
|
17
18
|
|
|
19
|
+
|
|
18
20
|
class Delimiter(object):
|
|
19
21
|
def __init__(self, terminal_printer, delimiter=',', add_parens=False):
|
|
20
22
|
"""
|
|
@@ -74,6 +76,7 @@ class Delimiter(object):
|
|
|
74
76
|
else:
|
|
75
77
|
self._terminal_printer.delimiter(self._delimiter)
|
|
76
78
|
|
|
79
|
+
|
|
77
80
|
class TokenPrinter(object):
|
|
78
81
|
"""
|
|
79
82
|
Concatenates terminal symbols of the python grammar
|
|
@@ -88,7 +91,11 @@ class TokenPrinter(object):
|
|
|
88
91
|
self._prefer_single_line = prefer_single_line
|
|
89
92
|
self._allow_invalid_num_warnings = allow_invalid_num_warnings
|
|
90
93
|
|
|
91
|
-
|
|
94
|
+
# Initialize as unicode string on Python 2.7 to handle Unicode content
|
|
95
|
+
if sys.version_info[0] < 3:
|
|
96
|
+
self._code = u''
|
|
97
|
+
else:
|
|
98
|
+
self._code = ''
|
|
92
99
|
self.indent = 0
|
|
93
100
|
self.unicode_literals = False
|
|
94
101
|
self.previous_token = TokenTypes.NoToken
|
|
@@ -96,6 +103,10 @@ class TokenPrinter(object):
|
|
|
96
103
|
def __str__(self):
|
|
97
104
|
"""Return the output code."""
|
|
98
105
|
return self._code
|
|
106
|
+
|
|
107
|
+
def __unicode__(self):
|
|
108
|
+
"""Return the output code as unicode (for Python 2.7 compatibility)."""
|
|
109
|
+
return self._code
|
|
99
110
|
|
|
100
111
|
def identifier(self, name):
|
|
101
112
|
"""Add an identifier to the output code."""
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import python_minifier.ast_compat as ast
|
|
2
1
|
import math
|
|
3
2
|
import sys
|
|
4
3
|
|
|
4
|
+
import python_minifier.ast_compat as ast
|
|
5
|
+
from python_minifier.ast_annotation import get_parent
|
|
6
|
+
|
|
5
7
|
from python_minifier.ast_compare import compare_ast
|
|
6
8
|
from python_minifier.expression_printer import ExpressionPrinter
|
|
7
9
|
from python_minifier.transforms.suite_transformer import SuiteTransformer
|
|
8
|
-
from python_minifier.util import
|
|
10
|
+
from python_minifier.util import is_constant_node
|
|
11
|
+
|
|
9
12
|
|
|
10
13
|
class FoldConstants(SuiteTransformer):
|
|
11
14
|
"""
|
|
@@ -22,9 +25,9 @@ class FoldConstants(SuiteTransformer):
|
|
|
22
25
|
|
|
23
26
|
# Check this is a constant expression that could be folded
|
|
24
27
|
# We don't try to fold strings or bytes, since they have probably been arranged this way to make the source shorter and we are unlikely to beat that
|
|
25
|
-
if not
|
|
28
|
+
if not is_constant_node(node.left, (ast.Num, ast.NameConstant)):
|
|
26
29
|
return node
|
|
27
|
-
if not
|
|
30
|
+
if not is_constant_node(node.right, (ast.Num, ast.NameConstant)):
|
|
28
31
|
return node
|
|
29
32
|
|
|
30
33
|
if isinstance(node.op, ast.Div):
|
|
@@ -68,7 +71,7 @@ class FoldConstants(SuiteTransformer):
|
|
|
68
71
|
try:
|
|
69
72
|
folded_expression = unparse_expression(new_node)
|
|
70
73
|
folded_value = safe_eval(folded_expression)
|
|
71
|
-
except Exception
|
|
74
|
+
except Exception:
|
|
72
75
|
# This can happen if the value is too large to be represented as a literal
|
|
73
76
|
# or if the value is unparsed as nan, inf or -inf - which are not valid python literals
|
|
74
77
|
return node
|
|
@@ -91,7 +94,8 @@ class FoldConstants(SuiteTransformer):
|
|
|
91
94
|
return node
|
|
92
95
|
|
|
93
96
|
# New representation is shorter and has the same value, so use it
|
|
94
|
-
return self.add_child(new_node, node
|
|
97
|
+
return self.add_child(new_node, get_parent(node), node.namespace)
|
|
98
|
+
|
|
95
99
|
|
|
96
100
|
def equal_value_and_type(a, b):
|
|
97
101
|
if type(a) != type(b):
|
|
@@ -102,13 +106,15 @@ def equal_value_and_type(a, b):
|
|
|
102
106
|
|
|
103
107
|
return a == b
|
|
104
108
|
|
|
109
|
+
|
|
105
110
|
def safe_eval(expression):
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
empty_globals = {}
|
|
112
|
+
empty_locals = {}
|
|
108
113
|
|
|
109
114
|
# This will return the value, or could raise an exception
|
|
110
|
-
return eval(expression,
|
|
115
|
+
return eval(expression, empty_globals, empty_locals)
|
|
116
|
+
|
|
111
117
|
|
|
112
118
|
def unparse_expression(node):
|
|
113
119
|
expression_printer = ExpressionPrinter()
|
|
114
|
-
return expression_printer(node)
|
|
120
|
+
return expression_printer(node)
|