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.
Files changed (43) hide show
  1. python_minifier/__init__.py +14 -9
  2. python_minifier/__init__.pyi +8 -3
  3. python_minifier/__main__.py +77 -15
  4. python_minifier/ast_annotation/__init__.py +82 -0
  5. python_minifier/ast_compare.py +12 -14
  6. python_minifier/ast_compat.py +38 -0
  7. python_minifier/ast_printer.py +8 -5
  8. python_minifier/expression_printer.py +14 -13
  9. python_minifier/f_string.py +44 -45
  10. python_minifier/ministring.py +3 -3
  11. python_minifier/module_printer.py +19 -16
  12. python_minifier/rename/__init__.py +1 -1
  13. python_minifier/rename/bind_names.py +2 -1
  14. python_minifier/rename/binding.py +39 -40
  15. python_minifier/rename/mapper.py +66 -50
  16. python_minifier/rename/rename_literals.py +17 -15
  17. python_minifier/rename/renamer.py +26 -28
  18. python_minifier/rename/resolve_names.py +8 -7
  19. python_minifier/rename/util.py +7 -5
  20. python_minifier/token_printer.py +12 -1
  21. python_minifier/transforms/combine_imports.py +0 -1
  22. python_minifier/transforms/constant_folding.py +16 -10
  23. python_minifier/transforms/remove_annotations.py +18 -16
  24. python_minifier/transforms/remove_annotations_options.py +3 -1
  25. python_minifier/transforms/remove_annotations_options.pyi +8 -7
  26. python_minifier/transforms/remove_asserts.py +1 -2
  27. python_minifier/transforms/remove_debug.py +4 -3
  28. python_minifier/transforms/remove_exception_brackets.py +12 -7
  29. python_minifier/transforms/remove_explicit_return_none.py +5 -4
  30. python_minifier/transforms/remove_literal_statements.py +5 -6
  31. python_minifier/transforms/remove_object_base.py +2 -1
  32. python_minifier/transforms/remove_pass.py +1 -2
  33. python_minifier/transforms/remove_posargs.py +3 -4
  34. python_minifier/transforms/suite_transformer.py +6 -5
  35. python_minifier/util.py +12 -18
  36. {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/METADATA +2 -2
  37. python_minifier-3.0.0.dist-info/RECORD +45 -0
  38. python_minifier-2.11.2.dist-info/RECORD +0 -44
  39. {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/LICENSE +0 -0
  40. {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/WHEEL +0 -0
  41. {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/entry_points.txt +0 -0
  42. {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/top_level.txt +0 -0
  43. {python_minifier-2.11.2.dist-info → python_minifier-3.0.0.dist-info}/zip-safe +0 -0
@@ -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, arguments, func)
15
+ add_parent(arg, func)
17
16
  if hasattr(arg, 'annotation') and arg.annotation is not None:
18
- add_parent(arg.annotation, arguments, func.namespace)
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, arguments, func)
21
+ add_parent(arg, func)
23
22
  if arg.annotation is not None:
24
- add_parent(arg.annotation, arguments, func.namespace)
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, arguments, func.namespace)
27
+ add_parent(node, func.namespace)
29
28
 
30
29
  for node in arguments.defaults:
31
- add_parent(node, arguments, func.namespace)
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, arguments, func.namespace)
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, arguments, func)
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, arguments, func.namespace)
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, arguments, func)
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, parent=functiondef, namespace=functiondef)
58
+ add_parent(node, namespace=functiondef)
60
59
 
61
60
  for node in functiondef.decorator_list:
62
- add_parent(node, parent=functiondef, namespace=functiondef.namespace)
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, parent=functiondef, namespace=functiondef.namespace)
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, parent=functiondef, namespace=functiondef.namespace)
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, parent=classdef, namespace=classdef.namespace)
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, parent=classdef, namespace=classdef.namespace)
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, parent=classdef, namespace=classdef.namespace)
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, parent=classdef, namespace=classdef.namespace)
87
+ add_parent(classdef.kwargs, namespace=classdef.namespace)
89
88
 
90
89
  for node in classdef.body:
91
- add_parent(node, parent=classdef, namespace=classdef)
90
+ add_parent(node, namespace=classdef)
92
91
 
93
92
  for node in classdef.decorator_list:
94
- add_parent(node, parent=classdef, namespace=classdef.namespace)
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, parent=classdef, namespace=classdef.namespace)
97
+ add_parent(node, namespace=classdef.namespace)
98
+
99
99
 
100
100
  def add_parent_to_comprehension(node, namespace):
101
- assert is_ast_node(node, (ast.GeneratorExp, 'SetComp', 'DictComp', 'ListComp'))
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, parent=node, namespace=node)
104
+ add_parent(node.elt, namespace=node)
105
105
  elif hasattr(node, 'key'):
106
- add_parent(node.key, parent=node, namespace=node)
107
- add_parent(node.value, parent=node, namespace=node)
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, parent=generator, namespace=node)
115
- add_parent(generator.iter, parent=generator, namespace=iter_namespace)
116
- iter_namespace = node
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_, parent=generator, namespace=node)
117
+ add_parent(if_, namespace=node)
119
118
 
119
+ iter_namespace = node
120
120
 
121
- def add_parent(node, parent=None, namespace=None):
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 parent and namespace properties to
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 is_ast_node(node, (ast.FunctionDef, 'AsyncFunctionDef')):
155
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
144
156
  add_parent_to_functiondef(node)
145
- elif is_ast_node(node, (ast.GeneratorExp, 'SetComp', 'DictComp', 'ListComp')):
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, parent=node, namespace=node)
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, parent=node, namespace=node)
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 is_ast_node(node, 'Nonlocal'):
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(namespace, ast.ClassDef):
165
- if isinstance(node.ctx, ast.Load):
166
- namespace.nonlocal_names.add(node.id)
167
- elif isinstance(node.ctx, ast.Store) and isinstance(node.parent, ast.AugAssign):
168
- namespace.nonlocal_names.add(node.id)
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, parent=node, namespace=namespace)
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 is_ast_node
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.parent
11
- new_node.parent = parent
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 is_ast_node(self._value_node, (ast.Str, 'Bytes')):
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 is_ast_node(node.namespace, (ast.FunctionDef, ast.Module, 'AsyncFunctionDef')):
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
- l = []
159
+ path = []
158
160
 
159
161
  while True:
160
162
  namespace = self.nearest_function_namespace(node)
161
- l.insert(0, namespace)
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 l
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.parent, ast.Expr):
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 is_ast_node(v, ast.Str):
218
+ if is_constant_node(v, ast.Str):
217
219
  # Can't hoist this!
218
220
  continue
219
- else:
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 is_ast_node(node.namespace, ast.ClassDef):
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 is_ast_node(target, ast.Name) and target.id == '__slots__':
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 = set([namespace])
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 namespace, binding in sorted_bindings(module):
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
- def should_rename():
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, builtins
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 is_ast_node(node, (ast.FunctionDef, 'AsyncFunctionDef')) and node.name in node.namespace.nonlocal_names:
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 is_ast_node(node, 'Nonlocal'):
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 is_ast_node(node, ('MatchAs', 'MatchStar')) and node.name in node.namespace.nonlocal_names:
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 is_ast_node(node, 'MatchMapping') and node.rest in node.namespace.nonlocal_names:
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 is_ast_node(node, 'Exec'):
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):
@@ -1,7 +1,8 @@
1
- import python_minifier.ast_compat as ast
2
1
  import sys
3
2
 
4
- from python_minifier.util import is_ast_node
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 is_ast_node(node.value, ast.Str)
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 is_ast_node(node, (ast.AugAssign, 'AnnAssign')):
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 is_ast_node(el, ast.Str):
183
+ if is_constant_node(el, ast.Str):
182
184
  names.append(el.s)
183
185
 
184
186
  return names
@@ -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
- self._code = ''
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."""
@@ -30,7 +30,6 @@ class CombineImports(SuiteTransformer):
30
30
  if alias:
31
31
  yield self.add_child(ast.Import(names=alias), parent=parent, namespace=namespace)
32
32
 
33
-
34
33
  def _combine_import_from(self, node_list, parent):
35
34
 
36
35
  prev_import = None
@@ -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 is_ast_node
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 is_ast_node(node.left, (ast.Num, 'NameConstant')):
28
+ if not is_constant_node(node.left, (ast.Num, ast.NameConstant)):
26
29
  return node
27
- if not is_ast_node(node.right, (ast.Num, 'NameConstant')):
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 as e:
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.parent, node.namespace)
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
- globals = {}
107
- locals = {}
111
+ empty_globals = {}
112
+ empty_locals = {}
108
113
 
109
114
  # This will return the value, or could raise an exception
110
- return eval(expression, globals, locals)
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)