python-minifier 2.11.2__py2-none-any.whl → 2.11.3__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 +12 -8
  2. python_minifier/__init__.pyi +6 -1
  3. python_minifier/__main__.py +10 -7
  4. python_minifier/ast_annotation/__init__.py +82 -0
  5. python_minifier/ast_compare.py +1 -3
  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 +13 -14
  10. python_minifier/ministring.py +3 -3
  11. python_minifier/module_printer.py +13 -14
  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 +3 -0
  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-2.11.3.dist-info}/METADATA +1 -1
  37. python_minifier-2.11.3.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-2.11.3.dist-info}/LICENSE +0 -0
  40. {python_minifier-2.11.2.dist-info → python_minifier-2.11.3.dist-info}/WHEEL +0 -0
  41. {python_minifier-2.11.2.dist-info → python_minifier-2.11.3.dist-info}/entry_points.txt +0 -0
  42. {python_minifier-2.11.2.dist-info → python_minifier-2.11.3.dist-info}/top_level.txt +0 -0
  43. {python_minifier-2.11.2.dist-info → python_minifier-2.11.3.dist-info}/zip-safe +0 -0
@@ -1,9 +1,9 @@
1
- import python_minifier.ast_compat as ast
2
1
  import sys
3
2
 
3
+ import python_minifier.ast_compat as ast
4
+
4
5
  from .expression_printer import ExpressionPrinter
5
6
  from .token_printer import Delimiter
6
- from .util import is_ast_node
7
7
 
8
8
 
9
9
  class ModulePrinter(ExpressionPrinter):
@@ -55,7 +55,7 @@ class ModulePrinter(ExpressionPrinter):
55
55
  def visit_Expr(self, node):
56
56
  assert isinstance(node, ast.Expr)
57
57
 
58
- if is_ast_node(node.value, (ast.Yield, 'YieldFrom')):
58
+ if isinstance(node.value, (ast.Yield, ast.YieldFrom)):
59
59
  self._yield_expr(node.value)
60
60
  else:
61
61
  self._testlist(node.value)
@@ -82,7 +82,7 @@ class ModulePrinter(ExpressionPrinter):
82
82
  self.printer.delimiter('=')
83
83
 
84
84
  # Yield nodes that are the sole node on the right hand side of an assignment do not need parens
85
- if is_ast_node(node.value, (ast.Yield, 'YieldFrom')):
85
+ if isinstance(node.value, (ast.Yield, ast.YieldFrom)):
86
86
  self._yield_expr(node.value)
87
87
  else:
88
88
  self._testlist(node.value)
@@ -97,7 +97,7 @@ class ModulePrinter(ExpressionPrinter):
97
97
  self.printer.delimiter('=')
98
98
 
99
99
  # Yield nodes that are the sole node on the right hand side of an assignment do not need parens
100
- if is_ast_node(node.value, (ast.Yield, 'YieldFrom')):
100
+ if isinstance(node.value, (ast.Yield, ast.YieldFrom)):
101
101
  self._yield_expr(node.value)
102
102
  else:
103
103
  self._testlist(node.value)
@@ -143,7 +143,7 @@ class ModulePrinter(ExpressionPrinter):
143
143
 
144
144
  self.printer.keyword('return')
145
145
  if isinstance(node.value, ast.Tuple):
146
- if sys.version_info < (3, 8) and [n for n in node.value.elts if is_ast_node(n, 'Starred')]:
146
+ if sys.version_info < (3, 8) and [n for n in node.value.elts if isinstance(n, ast.Starred)]:
147
147
  self.printer.delimiter('(')
148
148
  self._testlist(node.value)
149
149
  self.printer.delimiter(')')
@@ -243,7 +243,7 @@ class ModulePrinter(ExpressionPrinter):
243
243
  assert isinstance(node, ast.ImportFrom)
244
244
 
245
245
  self.printer.keyword('from')
246
- for i in range(node.level):
246
+ for _i in range(node.level):
247
247
  self.printer.delimiter('.')
248
248
  if node.module is not None:
249
249
  self.printer.identifier(node.module)
@@ -326,7 +326,7 @@ class ModulePrinter(ExpressionPrinter):
326
326
  self._suite(node.orelse)
327
327
 
328
328
  def visit_For(self, node, is_async=False):
329
- assert isinstance(node, ast.For) or (hasattr(ast, 'AsyncFor') and isinstance(node, ast.AsyncFor))
329
+ assert isinstance(node, (ast.For, ast.AsyncFor))
330
330
 
331
331
  self.printer.newline()
332
332
 
@@ -362,7 +362,7 @@ class ModulePrinter(ExpressionPrinter):
362
362
  self._suite(node.orelse)
363
363
 
364
364
  def visit_Try(self, node, star=False):
365
- assert is_ast_node(node, (ast.Try, 'TryStar'))
365
+ assert isinstance(node, (ast.Try, ast.TryStar))
366
366
 
367
367
  self.printer.newline()
368
368
  self.printer.keyword('try')
@@ -440,7 +440,7 @@ class ModulePrinter(ExpressionPrinter):
440
440
  self._suite(node.body)
441
441
 
442
442
  def visit_With(self, node, is_async=False):
443
- assert is_ast_node(node, (ast.With, 'AsyncWith'))
443
+ assert isinstance(node, (ast.With, ast.AsyncWith))
444
444
 
445
445
  self.printer.newline()
446
446
 
@@ -469,7 +469,7 @@ class ModulePrinter(ExpressionPrinter):
469
469
  self._suite(node.body)
470
470
 
471
471
  def visit_withitem(self, node):
472
- assert is_ast_node(node, ('withitem', ast.With))
472
+ assert isinstance(node, (ast.withitem, ast.With))
473
473
 
474
474
  self._expression(node.context_expr)
475
475
 
@@ -478,7 +478,7 @@ class ModulePrinter(ExpressionPrinter):
478
478
  self._expression(node.optional_vars)
479
479
 
480
480
  def visit_FunctionDef(self, node, is_async=False):
481
- assert is_ast_node(node, (ast.FunctionDef, 'AsyncFunctionDef'))
481
+ assert isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
482
482
 
483
483
  self.printer.newline()
484
484
 
@@ -670,7 +670,7 @@ class ModulePrinter(ExpressionPrinter):
670
670
  for kwd, pattern in zip(node.kwd_attrs, node.kwd_patterns):
671
671
  delimiter.new_item()
672
672
 
673
- self.printer.identifier(kwd)
673
+ self.printer.identifier(kwd)
674
674
  self.printer.delimiter('=')
675
675
 
676
676
  self.pattern(pattern)
@@ -859,4 +859,3 @@ class ModulePrinter(ExpressionPrinter):
859
859
 
860
860
  for node in node_list:
861
861
  statements[node.__class__.__name__](node)
862
-
@@ -3,4 +3,4 @@ from python_minifier.rename.mapper import add_namespace
3
3
  from python_minifier.rename.rename_literals import rename_literals
4
4
  from python_minifier.rename.renamer import rename
5
5
  from python_minifier.rename.resolve_names import resolve_names
6
- from python_minifier.rename.util import allow_rename_locals, allow_rename_globals
6
+ from python_minifier.rename.util import allow_rename_globals, allow_rename_locals
@@ -1,7 +1,7 @@
1
1
  import python_minifier.ast_compat as ast
2
2
 
3
3
  from python_minifier.rename.binding import NameBinding
4
- from python_minifier.rename.util import arg_rename_in_place, get_global_namespace, get_nonlocal_namespace, builtins
4
+ from python_minifier.rename.util import arg_rename_in_place, builtins, get_global_namespace
5
5
  from python_minifier.transforms.suite_transformer import NodeVisitor
6
6
 
7
7
 
@@ -180,6 +180,7 @@ class NameBinder(NodeVisitor):
180
180
 
181
181
  get_global_namespace(node.namespace).preserved.add(node.name)
182
182
 
183
+
183
184
  def bind_names(module):
184
185
  """
185
186
  Bind names to their local namespace
@@ -1,7 +1,6 @@
1
1
  import python_minifier.ast_compat as ast
2
2
 
3
3
  from python_minifier.rename.util import arg_rename_in_place, insert
4
- from python_minifier.util import is_ast_node
5
4
 
6
5
 
7
6
  class Binding(object):
@@ -105,11 +104,11 @@ class Binding(object):
105
104
  # Python 2 Param context
106
105
  if not arg_rename_in_place(node):
107
106
  arg_rename = True
108
- elif is_ast_node(node, (ast.ClassDef, ast.FunctionDef, 'AsyncFunctionDef')):
107
+ elif isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
109
108
  pass
110
109
  elif isinstance(node, ast.ExceptHandler):
111
110
  pass
112
- elif is_ast_node(node, (ast.Global, 'Nonlocal')):
111
+ elif isinstance(node, (ast.Global, ast.Nonlocal)):
113
112
  pass
114
113
  elif isinstance(node, ast.alias):
115
114
  if node.asname is None:
@@ -119,22 +118,22 @@ class Binding(object):
119
118
  pass
120
119
  if node.kwarg == self._name:
121
120
  pass
122
- elif is_ast_node(node, 'arg'):
121
+ elif isinstance(node, ast.arg):
123
122
  if not arg_rename_in_place(node):
124
123
  arg_rename = True
125
124
 
126
- elif is_ast_node(node, 'MatchAs'):
125
+ elif isinstance(node, ast.MatchAs):
127
126
  if node.name is None:
128
127
  additional_bytes += 4 # ' as '
129
- elif is_ast_node(node, 'MatchStar'):
128
+ elif isinstance(node, ast.MatchStar):
130
129
  pass
131
- elif is_ast_node(node, 'MatchMapping'):
130
+ elif isinstance(node, ast.MatchMapping):
132
131
  pass
133
- elif is_ast_node(node, 'TypeVar'):
132
+ elif isinstance(node, ast.TypeVar):
134
133
  pass
135
- elif is_ast_node(node, 'TypeVarTuple'):
134
+ elif isinstance(node, ast.TypeVarTuple):
136
135
  pass
137
- elif is_ast_node(node, 'ParamSpec'):
136
+ elif isinstance(node, ast.ParamSpec):
138
137
  pass
139
138
 
140
139
  else:
@@ -160,11 +159,11 @@ class Binding(object):
160
159
  mentions += 1
161
160
  arg_rename = True
162
161
 
163
- elif is_ast_node(node, (ast.ClassDef, ast.FunctionDef, 'AsyncFunctionDef')):
162
+ elif isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
164
163
  pass
165
164
  elif isinstance(node, ast.ExceptHandler):
166
165
  pass
167
- elif is_ast_node(node, (ast.Global, 'Nonlocal')):
166
+ elif isinstance(node, (ast.Global, ast.Nonlocal)):
168
167
  pass
169
168
  elif isinstance(node, ast.alias):
170
169
  if node.asname is None:
@@ -172,22 +171,22 @@ class Binding(object):
172
171
  mentions += 1
173
172
  elif isinstance(node, ast.arguments):
174
173
  pass
175
- elif is_ast_node(node, 'arg'):
174
+ elif isinstance(node, ast.arg):
176
175
  if not arg_rename_in_place(node):
177
176
  mentions += 1
178
177
  arg_rename = True
179
178
 
180
- elif is_ast_node(node, 'MatchAs'):
179
+ elif isinstance(node, ast.MatchAs):
181
180
  pass
182
- elif is_ast_node(node, 'MatchStar'):
181
+ elif isinstance(node, ast.MatchStar):
183
182
  pass
184
- elif is_ast_node(node, 'MatchMapping'):
183
+ elif isinstance(node, ast.MatchMapping):
185
184
  pass
186
- elif is_ast_node(node, 'TypeVar'):
185
+ elif isinstance(node, ast.TypeVar):
187
186
  pass
188
- elif is_ast_node(node, 'TypeVarTuple'):
187
+ elif isinstance(node, ast.TypeVarTuple):
189
188
  pass
190
- elif is_ast_node(node, 'ParamSpec'):
189
+ elif isinstance(node, ast.ParamSpec):
191
190
  pass
192
191
 
193
192
  else:
@@ -210,11 +209,11 @@ class Binding(object):
210
209
  else:
211
210
  # Python 2 Param context
212
211
  arg_rename = True
213
- elif is_ast_node(node, (ast.ClassDef, ast.FunctionDef, 'AsyncFunctionDef')):
212
+ elif isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
214
213
  mentions += 1
215
214
  elif isinstance(node, ast.ExceptHandler):
216
215
  mentions += 1
217
- elif is_ast_node(node, (ast.Global, 'Nonlocal')):
216
+ elif isinstance(node, (ast.Global, ast.Nonlocal)):
218
217
  mentions += len([n for n in node.names if n == self._name])
219
218
  elif isinstance(node, ast.alias):
220
219
  mentions += 1
@@ -223,20 +222,20 @@ class Binding(object):
223
222
  mentions += 1
224
223
  if node.kwarg == self._name:
225
224
  mentions += 1
226
- elif is_ast_node(node, 'arg'):
225
+ elif isinstance(node, ast.arg):
227
226
  arg_rename = True
228
227
 
229
- elif is_ast_node(node, 'MatchAs'):
228
+ elif isinstance(node, ast.MatchAs):
230
229
  mentions += 1
231
- elif is_ast_node(node, 'MatchStar'):
230
+ elif isinstance(node, ast.MatchStar):
232
231
  mentions += 1
233
- elif is_ast_node(node, 'MatchMapping'):
232
+ elif isinstance(node, ast.MatchMapping):
234
233
  mentions += 1
235
- elif is_ast_node(node, 'TypeVar'):
234
+ elif isinstance(node, ast.TypeVar):
236
235
  mentions += 1
237
- elif is_ast_node(node, 'TypeVarTuple'):
236
+ elif isinstance(node, ast.TypeVarTuple):
238
237
  mentions += 1
239
- elif is_ast_node(node, 'ParamSpec'):
238
+ elif isinstance(node, ast.ParamSpec):
240
239
  mentions += 1
241
240
 
242
241
  else:
@@ -273,7 +272,7 @@ class Binding(object):
273
272
 
274
273
  """
275
274
 
276
- raise NotImplementedError()
275
+ raise NotImplementedError
277
276
 
278
277
  def rename(self, new_name):
279
278
  """
@@ -283,7 +282,7 @@ class Binding(object):
283
282
 
284
283
  """
285
284
 
286
- raise NotImplementedError()
285
+ raise NotImplementedError
287
286
 
288
287
 
289
288
  class NameBinding(Binding):
@@ -362,7 +361,7 @@ class NameBinding(Binding):
362
361
  else:
363
362
  assert func_namespace_binding is node.namespace
364
363
 
365
- elif is_ast_node(node, (ast.FunctionDef, 'AsyncFunctionDef')):
364
+ elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
366
365
  node.name = new_name
367
366
  elif isinstance(node, ast.ClassDef):
368
367
  node.name = new_name
@@ -371,7 +370,7 @@ class NameBinding(Binding):
371
370
  node.asname = None
372
371
  else:
373
372
  node.asname = new_name
374
- elif is_ast_node(node, 'arg'):
373
+ elif isinstance(node, ast.arg):
375
374
 
376
375
  if arg_rename_in_place(node):
377
376
  node.arg = new_name
@@ -384,7 +383,7 @@ class NameBinding(Binding):
384
383
 
385
384
  elif isinstance(node, ast.ExceptHandler):
386
385
  node.name = new_name
387
- elif is_ast_node(node, (ast.Global, 'Nonlocal')):
386
+ elif isinstance(node, (ast.Global, ast.Nonlocal)):
388
387
  node.names = [new_name if n == self._name else n for n in node.names]
389
388
  elif isinstance(node, ast.arguments):
390
389
 
@@ -398,17 +397,17 @@ class NameBinding(Binding):
398
397
  node.kwarg = new_name
399
398
  node.kwarg_renamed = True
400
399
 
401
- elif is_ast_node(node, 'MatchAs'):
400
+ elif isinstance(node, ast.MatchAs):
402
401
  node.name = new_name
403
- elif is_ast_node(node, 'MatchStar'):
402
+ elif isinstance(node, ast.MatchStar):
404
403
  node.name = new_name
405
- elif is_ast_node(node, 'MatchMapping'):
404
+ elif isinstance(node, ast.MatchMapping):
406
405
  node.rest = new_name
407
- elif is_ast_node(node, 'TypeVar'):
406
+ elif isinstance(node, ast.TypeVar):
408
407
  node.name = new_name
409
- elif is_ast_node(node, 'TypeVarTuple'):
408
+ elif isinstance(node, ast.TypeVarTuple):
410
409
  node.name = new_name
411
- elif is_ast_node(node, 'ParamSpec'):
410
+ elif isinstance(node, ast.ParamSpec):
412
411
  node.name = new_name
413
412
 
414
413
  if func_namespace_binding is not None:
@@ -492,4 +491,4 @@ class BuiltinBinding(NameBinding):
492
491
  if not isinstance(node.ctx, ast.Load):
493
492
  return True
494
493
 
495
- return False
494
+ return False
@@ -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):