python-minifier 2.11.2__tar.gz → 2.11.3__tar.gz

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 (92) hide show
  1. {python_minifier-2.11.2/src/python_minifier.egg-info → python_minifier-2.11.3}/PKG-INFO +1 -1
  2. {python_minifier-2.11.2 → python_minifier-2.11.3}/setup.py +1 -1
  3. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/__init__.py +12 -8
  4. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/__init__.pyi +6 -1
  5. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/__main__.py +10 -7
  6. python_minifier-2.11.3/src/python_minifier/ast_annotation/__init__.py +82 -0
  7. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/ast_compare.py +1 -3
  8. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/ast_compat.py +38 -0
  9. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/ast_printer.py +8 -5
  10. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/expression_printer.py +14 -13
  11. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/f_string.py +13 -14
  12. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/ministring.py +3 -3
  13. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/module_printer.py +13 -14
  14. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/__init__.py +1 -1
  15. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/bind_names.py +2 -1
  16. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/binding.py +39 -40
  17. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/mapper.py +66 -50
  18. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/rename_literals.py +17 -15
  19. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/renamer.py +26 -28
  20. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/resolve_names.py +8 -7
  21. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/util.py +7 -5
  22. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/token_printer.py +3 -0
  23. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/combine_imports.py +0 -1
  24. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/constant_folding.py +16 -10
  25. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_annotations.py +18 -16
  26. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_annotations_options.py +3 -1
  27. python_minifier-2.11.3/src/python_minifier/transforms/remove_annotations_options.pyi +18 -0
  28. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_asserts.py +1 -2
  29. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_debug.py +4 -3
  30. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_exception_brackets.py +12 -7
  31. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_explicit_return_none.py +5 -4
  32. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_literal_statements.py +5 -6
  33. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_object_base.py +2 -1
  34. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/remove_pass.py +1 -2
  35. python_minifier-2.11.3/src/python_minifier/transforms/remove_posargs.py +12 -0
  36. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/suite_transformer.py +6 -5
  37. python_minifier-2.11.3/src/python_minifier/util.py +42 -0
  38. {python_minifier-2.11.2 → python_minifier-2.11.3/src/python_minifier.egg-info}/PKG-INFO +1 -1
  39. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier.egg-info/SOURCES.txt +3 -1
  40. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_assignment_expressions.py +5 -2
  41. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_await_fstring.py +3 -0
  42. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_bind_names.py +61 -7
  43. python_minifier-2.11.3/test/test_bind_names_namedexpr.py +259 -0
  44. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_bind_names_python2.py +1 -0
  45. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_bind_names_python312.py +10 -1
  46. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_bind_names_python313.py +10 -1
  47. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_bind_names_python33.py +1 -0
  48. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_combine_imports.py +17 -8
  49. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_comprehension_rename.py +6 -1
  50. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_decorator_expressions.py +5 -2
  51. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_dict_expansion.py +3 -0
  52. python_minifier-2.11.3/test/test_folding.py +151 -0
  53. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_fstring.py +19 -16
  54. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_generic_types.py +5 -2
  55. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_hoist_literals.py +41 -11
  56. python_minifier-2.11.3/test/test_import.py +32 -0
  57. python_minifier-2.11.3/test/test_is_constant_node.py +43 -0
  58. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_iterable_unpacking.py +3 -0
  59. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_match.py +15 -10
  60. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_match_rename.py +55 -46
  61. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_name_generator.py +1 -0
  62. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_nonlocal.py +9 -6
  63. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_posargs.py +5 -1
  64. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_annotations.py +96 -62
  65. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_assert.py +18 -6
  66. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_debug.py +29 -23
  67. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_exception_brackets.py +13 -2
  68. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_literal_statements.py +8 -2
  69. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_pass.py +18 -6
  70. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_rename_builtins.py +9 -7
  71. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_rename_locals.py +69 -55
  72. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_slice.py +1 -0
  73. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_type_param_defaults.py +7 -1
  74. python_minifier-2.11.2/src/python_minifier/transforms/remove_annotations_options.pyi +0 -17
  75. python_minifier-2.11.2/src/python_minifier/transforms/remove_posargs.py +0 -13
  76. python_minifier-2.11.2/src/python_minifier/util.py +0 -48
  77. python_minifier-2.11.2/test/test_folding.py +0 -136
  78. python_minifier-2.11.2/test/test_import.py +0 -30
  79. python_minifier-2.11.2/test/test_is_ast_node.py +0 -40
  80. {python_minifier-2.11.2 → python_minifier-2.11.3}/LICENSE +0 -0
  81. {python_minifier-2.11.2 → python_minifier-2.11.3}/README.md +0 -0
  82. {python_minifier-2.11.2 → python_minifier-2.11.3}/setup.cfg +0 -0
  83. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/py.typed +0 -0
  84. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/rename/name_generator.py +0 -0
  85. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier/transforms/__init__.py +0 -0
  86. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier.egg-info/dependency_links.txt +0 -0
  87. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier.egg-info/entry_points.txt +0 -0
  88. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier.egg-info/top_level.txt +0 -0
  89. {python_minifier-2.11.2 → python_minifier-2.11.3}/src/python_minifier.egg-info/zip-safe +0 -0
  90. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_preserve_shebang.py +0 -0
  91. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_explicit_return_none.py +0 -0
  92. {python_minifier-2.11.2 → python_minifier-2.11.3}/test/test_remove_object.py +3 -3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python_minifier
3
- Version: 2.11.2
3
+ Version: 2.11.3
4
4
  Summary: Transform Python source code into it's most compact representation
5
5
  Home-page: https://github.com/dflook/python-minifier
6
6
  Author: Daniel Flook
@@ -28,7 +28,7 @@ setup(
28
28
  long_description_content_type='text/markdown',
29
29
 
30
30
  python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <3.14',
31
- version='2.11.2',
31
+ version='2.11.3',
32
32
 
33
33
  classifiers=[
34
34
  'Development Status :: 5 - Production/Stable',
@@ -4,29 +4,30 @@ a 'minified' representation of the same source code.
4
4
 
5
5
  """
6
6
 
7
- import python_minifier.ast_compat as ast
8
7
  import re
9
8
 
9
+ import python_minifier.ast_compat as ast
10
+ from python_minifier.ast_annotation import add_parent
11
+
10
12
  from python_minifier.ast_compare import CompareError, compare_ast
11
13
  from python_minifier.module_printer import ModulePrinter
12
14
  from python_minifier.rename import (
13
- rename_literals,
14
- bind_names,
15
- resolve_names,
16
- rename,
15
+ add_namespace,
17
16
  allow_rename_globals,
18
17
  allow_rename_locals,
19
- add_namespace,
18
+ bind_names,
19
+ rename,
20
+ rename_literals,
21
+ resolve_names
20
22
  )
21
-
22
23
  from python_minifier.transforms.combine_imports import CombineImports
23
24
  from python_minifier.transforms.constant_folding import FoldConstants
24
25
  from python_minifier.transforms.remove_annotations import RemoveAnnotations
25
26
  from python_minifier.transforms.remove_annotations_options import RemoveAnnotationsOptions
26
27
  from python_minifier.transforms.remove_asserts import RemoveAsserts
27
28
  from python_minifier.transforms.remove_debug import RemoveDebug
28
- from python_minifier.transforms.remove_explicit_return_none import RemoveExplicitReturnNone
29
29
  from python_minifier.transforms.remove_exception_brackets import remove_no_arg_exception_call
30
+ from python_minifier.transforms.remove_explicit_return_none import RemoveExplicitReturnNone
30
31
  from python_minifier.transforms.remove_literal_statements import RemoveLiteralStatements
31
32
  from python_minifier.transforms.remove_object_base import RemoveObject
32
33
  from python_minifier.transforms.remove_pass import RemovePass
@@ -115,6 +116,7 @@ def minify(
115
116
  # This will raise if the source file can't be parsed
116
117
  module = ast.parse(source, filename)
117
118
 
119
+ add_parent(module)
118
120
  add_namespace(module)
119
121
 
120
122
  if remove_literal_statements:
@@ -198,6 +200,7 @@ def minify(
198
200
 
199
201
  return minified
200
202
 
203
+
201
204
  def _find_shebang(source):
202
205
  """
203
206
  Find a shebang line in source
@@ -214,6 +217,7 @@ def _find_shebang(source):
214
217
 
215
218
  return None
216
219
 
220
+
217
221
  def unparse(module):
218
222
  """
219
223
  Turn a module AST into python code
@@ -1,11 +1,14 @@
1
1
  import ast
2
- from typing import List, Text, AnyStr, Optional, Any, Union
2
+
3
+ from typing import Any, AnyStr, List, Optional, Text, Union
3
4
 
4
5
  from .transforms.remove_annotations_options import RemoveAnnotationsOptions as RemoveAnnotationsOptions
5
6
 
7
+
6
8
  class UnstableMinification(RuntimeError):
7
9
  def __init__(self, exception: Any, source: Any, minified: Any): ...
8
10
 
11
+
9
12
  def minify(
10
13
  source: AnyStr,
11
14
  filename: Optional[str] = ...,
@@ -28,8 +31,10 @@ def minify(
28
31
  constant_folding: bool = ...
29
32
  ) -> Text: ...
30
33
 
34
+
31
35
  def unparse(module: ast.Module) -> Text: ...
32
36
 
37
+
33
38
  def awslambda(
34
39
  source: AnyStr,
35
40
  filename: Optional[Text] = ...,
@@ -7,14 +7,17 @@ import sys
7
7
  from python_minifier import minify
8
8
  from python_minifier.transforms.remove_annotations_options import RemoveAnnotationsOptions
9
9
 
10
+
10
11
  if sys.version_info >= (3, 8):
11
12
  from importlib import metadata
13
+
12
14
  try:
13
15
  version = metadata.version('python-minifier')
14
16
  except metadata.PackageNotFoundError:
15
17
  version = '0.0.0'
16
18
  else:
17
- from pkg_resources import get_distribution, DistributionNotFound
19
+ from pkg_resources import DistributionNotFound, get_distribution
20
+
18
21
  try:
19
22
  version = get_distribution('python_minifier').version
20
23
  except DistributionNotFound:
@@ -170,25 +173,25 @@ def parse_args():
170
173
  minification_options.add_argument(
171
174
  '--no-preserve-shebang',
172
175
  action='store_false',
173
- help='Preserve any shebang line from the source',
176
+ help='Disable preserving any shebang line from the source',
174
177
  dest='preserve_shebang',
175
178
  )
176
179
  minification_options.add_argument(
177
180
  '--remove-asserts',
178
181
  action='store_true',
179
- help='Remove assert statements',
182
+ help='Enable removing assert statements',
180
183
  dest='remove_asserts',
181
184
  )
182
185
  minification_options.add_argument(
183
186
  '--remove-debug',
184
187
  action='store_true',
185
- help='Remove conditional statements that test __debug__ is True',
188
+ help='Enable removing conditional statements that test __debug__ is True',
186
189
  dest='remove_debug',
187
190
  )
188
191
  minification_options.add_argument(
189
192
  '--no-remove-explicit-return-none',
190
193
  action='store_false',
191
- help='Replace explicit return None with a bare return',
194
+ help='Disable replacing explicit return None with a bare return',
192
195
  dest='remove_explicit_return_none',
193
196
  )
194
197
  minification_options.add_argument(
@@ -268,9 +271,9 @@ def source_modules(args):
268
271
 
269
272
  for path_arg in args.path:
270
273
  if os.path.isdir(path_arg):
271
- for root, dirs, files in os.walk(path_arg, onerror=error, followlinks=True):
274
+ for root, _dirs, files in os.walk(path_arg, onerror=error, followlinks=True):
272
275
  for file in files:
273
- if file.endswith('.py') or file.endswith('.pyw'):
276
+ if file.endswith(('.py', '.pyw')):
274
277
  yield os.path.join(root, file)
275
278
  else:
276
279
  yield path_arg
@@ -0,0 +1,82 @@
1
+ """
2
+ This module provides utilities for annotating Abstract Syntax Tree (AST) nodes with parent references.
3
+ """
4
+
5
+ import ast
6
+
7
+ class _NoParent(ast.AST):
8
+ """A placeholder class used to indicate that a node has no parent."""
9
+
10
+ def __repr__(self):
11
+ # type: () -> str
12
+ return 'NoParent()'
13
+
14
+ def add_parent(node, parent=_NoParent()):
15
+ # type: (ast.AST, ast.AST) -> None
16
+ """
17
+ Recursively adds a parent reference to each node in the AST.
18
+
19
+ >>> tree = ast.parse('a = 1')
20
+ >>> add_parent(tree)
21
+ >>> get_parent(tree.body[0]) == tree
22
+ True
23
+
24
+ :param node: The current AST node.
25
+ :param parent: The parent :class:`ast.AST` node.
26
+ """
27
+
28
+ node._parent = parent # type: ignore[attr-defined]
29
+ for child in ast.iter_child_nodes(node):
30
+ add_parent(child, node)
31
+
32
+ def get_parent(node):
33
+ # type: (ast.AST) -> ast.AST
34
+ """
35
+ Retrieves the parent of the given AST node.
36
+
37
+ >>> tree = ast.parse('a = 1')
38
+ >>> add_parent(tree)
39
+ >>> get_parent(tree.body[0]) == tree
40
+ True
41
+
42
+ :param node: The AST node whose parent is to be retrieved.
43
+ :return: The parent AST node.
44
+ :raises ValueError: If the node has no parent.
45
+ """
46
+
47
+ if not hasattr(node, '_parent') or isinstance(node._parent, _NoParent): # type: ignore[attr-defined]
48
+ raise ValueError('Node has no parent')
49
+
50
+ return node._parent # type: ignore[attr-defined]
51
+
52
+ def set_parent(node, parent):
53
+ # type: (ast.AST, ast.AST) -> None
54
+ """
55
+ Replace the parent of the given AST node.
56
+
57
+ Create a simple AST:
58
+ >>> tree = ast.parse('a = func()')
59
+ >>> add_parent(tree)
60
+ >>> isinstance(tree.body[0], ast.Assign) and isinstance(tree.body[0].value, ast.Call)
61
+ True
62
+ >>> assign = tree.body[0]
63
+ >>> call = tree.body[0].value
64
+ >>> get_parent(call) == assign
65
+ True
66
+
67
+ Replace the parent of the call node:
68
+ >>> tree.body[0] = call
69
+ >>> set_parent(call, tree)
70
+ >>> get_parent(call) == tree
71
+ True
72
+ >>> from python_minifier.ast_printer import print_ast
73
+ >>> print(print_ast(tree))
74
+ Module(body=[
75
+ Call(Name('func'))
76
+ ])
77
+
78
+ :param node: The AST node whose parent is to be set.
79
+ :param parent: The parent AST node.
80
+ """
81
+
82
+ node._parent = parent # type: ignore[attr-defined]
@@ -1,7 +1,5 @@
1
1
  import python_minifier.ast_compat as ast
2
2
 
3
- from python_minifier.util import is_ast_node
4
-
5
3
 
6
4
  class CompareError(RuntimeError):
7
5
  """
@@ -18,7 +16,7 @@ class CompareError(RuntimeError):
18
16
 
19
17
  def namespace(self, node):
20
18
  if hasattr(node, 'namespace'):
21
- if is_ast_node(node.namespace, (ast.FunctionDef, ast.ClassDef, 'AsyncFunctionDef')):
19
+ if isinstance(node.namespace, (ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)):
22
20
  return self.namespace(node.namespace) + '.' + node.namespace.name
23
21
  elif isinstance(node.namespace, ast.Module):
24
22
  return ''
@@ -8,6 +8,7 @@ deprecation warnings.
8
8
 
9
9
  from ast import *
10
10
 
11
+
11
12
  # Ideally we don't import anything else
12
13
 
13
14
  if 'TypeAlias' in globals():
@@ -16,6 +17,7 @@ if 'TypeAlias' in globals():
16
17
  Constant.n = property(lambda self: self.value, lambda self, value: setattr(self, 'value', value)) # type: ignore[assignment]
17
18
  Constant.s = property(lambda self: self.value, lambda self, value: setattr(self, 'value', value)) # type: ignore[assignment]
18
19
 
20
+
19
21
  # These classes are redefined from the ones in ast that complain about deprecation
20
22
  # They will continue to work once they are removed from ast
21
23
 
@@ -23,18 +25,54 @@ if 'TypeAlias' in globals():
23
25
  def __new__(cls, s, *args, **kwargs):
24
26
  return Constant(value=s, *args, **kwargs)
25
27
 
28
+
26
29
  class Bytes(Constant): # type: ignore[no-redef]
27
30
  def __new__(cls, s, *args, **kwargs):
28
31
  return Constant(value=s, *args, **kwargs)
29
32
 
33
+
30
34
  class Num(Constant): # type: ignore[no-redef]
31
35
  def __new__(cls, n, *args, **kwargs):
32
36
  return Constant(value=n, *args, **kwargs)
33
37
 
38
+
34
39
  class NameConstant(Constant): # type: ignore[no-redef]
35
40
  def __new__(cls, *args, **kwargs):
36
41
  return Constant(*args, **kwargs)
37
42
 
43
+
38
44
  class Ellipsis(Constant): # type: ignore[no-redef]
39
45
  def __new__(cls, *args, **kwargs):
40
46
  return Constant(value=literal_eval('...'), *args, **kwargs)
47
+
48
+
49
+ # Create a dummy class for missing AST nodes
50
+ for _node_type in [
51
+ 'AnnAssign',
52
+ 'AsyncFor',
53
+ 'AsyncFunctionDef',
54
+ 'AsyncFunctionDef',
55
+ 'AsyncWith',
56
+ 'Bytes',
57
+ 'Constant',
58
+ 'DictComp',
59
+ 'Exec',
60
+ 'ListComp',
61
+ 'MatchAs',
62
+ 'MatchMapping',
63
+ 'MatchStar',
64
+ 'NameConstant',
65
+ 'NamedExpr',
66
+ 'Nonlocal',
67
+ 'ParamSpec',
68
+ 'SetComp',
69
+ 'Starred',
70
+ 'TryStar',
71
+ 'TypeVar',
72
+ 'TypeVarTuple',
73
+ 'YieldFrom',
74
+ 'arg',
75
+ 'withitem',
76
+ ]:
77
+ if _node_type not in globals():
78
+ globals()[_node_type] = type(_node_type, (AST,), {})
@@ -12,7 +12,8 @@ fields or field names may be omitted for clarity. It should still be precise and
12
12
 
13
13
  import python_minifier.ast_compat as ast
14
14
 
15
- from python_minifier.util import is_ast_node
15
+ from python_minifier.util import is_constant_node
16
+
16
17
 
17
18
  INDENT = ' '
18
19
 
@@ -63,24 +64,26 @@ default_fields = {
63
64
  'AugAssign': 'op',
64
65
  }
65
66
 
67
+
66
68
  def is_literal(node, field):
67
69
  if hasattr(ast, 'Constant') and isinstance(node, ast.Constant) and field == 'value':
68
70
  return True
69
71
 
70
- if is_ast_node(node, ast.Num) and field == 'n':
72
+ if is_constant_node(node, ast.Num) and field == 'n':
71
73
  return True
72
74
 
73
- if is_ast_node(node, ast.Str) and field == 's':
75
+ if is_constant_node(node, ast.Str) and field == 's':
74
76
  return True
75
77
 
76
- if is_ast_node(node, 'Bytes') and field == 's':
78
+ if is_constant_node(node, ast.Bytes) and field == 's':
77
79
  return True
78
80
 
79
- if is_ast_node(node, 'NameConstant') and field == 'value':
81
+ if is_constant_node(node, ast.NameConstant) and field == 'value':
80
82
  return True
81
83
 
82
84
  return False
83
85
 
86
+
84
87
  def print_ast(node):
85
88
  if not isinstance(node, ast.AST):
86
89
  return repr(node)
@@ -1,9 +1,9 @@
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
5
4
 
6
- from python_minifier.token_printer import TokenPrinter, Delimiter
5
+ from python_minifier.token_printer import Delimiter, TokenPrinter
6
+ from python_minifier.util import is_constant_node
7
7
 
8
8
 
9
9
  class ExpressionPrinter(object):
@@ -69,7 +69,7 @@ class ExpressionPrinter(object):
69
69
 
70
70
  # Python2 parses negative ints as an ast.Num with a negative value.
71
71
  # Make sure the Num get the precedence of the USub operator in this case.
72
- if sys.version_info < (3, 0) and is_ast_node(node, ast.Num):
72
+ if sys.version_info < (3, 0) and is_constant_node(node, ast.Num):
73
73
  if str(node.n)[0] == '-':
74
74
  return self.precedences['USub']
75
75
 
@@ -156,7 +156,7 @@ class ExpressionPrinter(object):
156
156
  if key is None:
157
157
  self.printer.operator('**')
158
158
 
159
- if 0 < self.precedence(datum) <=7:
159
+ if 0 < self.precedence(datum) <= 7:
160
160
  self.printer.delimiter('(')
161
161
  self._expression(datum)
162
162
  self.printer.delimiter(')')
@@ -208,7 +208,7 @@ class ExpressionPrinter(object):
208
208
  def visit_UnaryOp(self, node):
209
209
  self.visit(node.op)
210
210
 
211
- if sys.version_info < (3, 0) and isinstance(node.op, ast.USub) and is_ast_node(node.operand, ast.Num):
211
+ if sys.version_info < (3, 0) and isinstance(node.op, ast.USub) and is_constant_node(node.operand, ast.Num):
212
212
  # For: -(1), which is parsed as a UnaryOp(USub, Num(1)).
213
213
  # Without this special case it would be printed as -1
214
214
  # This is fine, but python 2 will then parse it at Num(-1) so the AST wouldn't round-trip.
@@ -428,7 +428,7 @@ class ExpressionPrinter(object):
428
428
  value_precedence = self.precedence(node.value)
429
429
  attr_precedence = self.precedence(node)
430
430
 
431
- if (value_precedence != 0 and (attr_precedence > value_precedence)) or is_ast_node(node.value, ast.Num):
431
+ if (value_precedence != 0 and (attr_precedence > value_precedence)) or is_constant_node(node.value, ast.Num):
432
432
  self.printer.delimiter('(')
433
433
  self._expression(node.value)
434
434
  self.printer.delimiter(')')
@@ -462,7 +462,7 @@ class ExpressionPrinter(object):
462
462
  self.visit_Slice(node.slice)
463
463
  elif isinstance(node.slice, ast.ExtSlice):
464
464
  self.visit_ExtSlice(node.slice)
465
- elif is_ast_node(node.slice, ast.Ellipsis):
465
+ elif is_constant_node(node.slice, ast.Ellipsis):
466
466
  self.visit_Ellipsis(node)
467
467
  elif sys.version_info >= (3, 9) and isinstance(node.slice, ast.Tuple):
468
468
  self.visit_Tuple(node.slice)
@@ -629,7 +629,8 @@ class ExpressionPrinter(object):
629
629
  def visit_arg(self, node):
630
630
  if isinstance(node, ast.Name):
631
631
  # Python 2 uses Name nodes
632
- return self.visit_Name(node)
632
+ self.visit_Name(node)
633
+ return
633
634
 
634
635
  self.printer.identifier(node.arg)
635
636
 
@@ -648,7 +649,7 @@ class ExpressionPrinter(object):
648
649
  self._expression(node.body)
649
650
 
650
651
  def _expression(self, expression):
651
- if is_ast_node(expression, (ast.Yield, 'YieldFrom')):
652
+ if isinstance(expression, (ast.Yield, ast.YieldFrom)):
652
653
  self.printer.delimiter('(')
653
654
  self._yield_expr(expression)
654
655
  self.printer.delimiter(')')
@@ -656,7 +657,7 @@ class ExpressionPrinter(object):
656
657
  self.printer.delimiter('(')
657
658
  self.visit_Tuple(expression)
658
659
  self.printer.delimiter(')')
659
- elif is_ast_node(expression, 'NamedExpr'):
660
+ elif isinstance(expression, ast.NamedExpr):
660
661
  self.printer.delimiter('(')
661
662
  self.visit_NamedExpr(expression)
662
663
  self.printer.delimiter(')')
@@ -664,11 +665,11 @@ class ExpressionPrinter(object):
664
665
  self.visit(expression)
665
666
 
666
667
  def _testlist(self, test):
667
- if is_ast_node(test, (ast.Yield, 'YieldFrom')):
668
+ if isinstance(test, (ast.Yield, ast.YieldFrom)):
668
669
  self.printer.delimiter('(')
669
670
  self._yield_expr(test)
670
671
  self.printer.delimiter(')')
671
- elif is_ast_node(test, 'NamedExpr'):
672
+ elif isinstance(test, ast.NamedExpr):
672
673
  self.printer.delimiter('(')
673
674
  self.visit_NamedExpr(test)
674
675
  self.printer.delimiter(')')
@@ -6,17 +6,17 @@ Mostly because FStrings feel like a hack.
6
6
 
7
7
  """
8
8
 
9
- import python_minifier.ast_compat as ast
10
9
  import copy
11
10
  import re
12
11
 
12
+ import python_minifier.ast_compat as ast
13
+
13
14
  from python_minifier import UnstableMinification
14
- from python_minifier.ast_compare import CompareError
15
- from python_minifier.ast_compare import compare_ast
15
+ from python_minifier.ast_compare import CompareError, compare_ast
16
16
  from python_minifier.expression_printer import ExpressionPrinter
17
17
  from python_minifier.ministring import MiniString
18
18
  from python_minifier.token_printer import TokenTypes
19
- from python_minifier.util import is_ast_node
19
+ from python_minifier.util import is_constant_node
20
20
 
21
21
 
22
22
  class FString(object):
@@ -36,7 +36,7 @@ class FString(object):
36
36
  c = ast.parse(code, 'FString candidate', mode='eval')
37
37
  compare_ast(self.node, c.body)
38
38
  return True
39
- except Exception as e:
39
+ except Exception:
40
40
  return False
41
41
 
42
42
  def complete_debug_specifier(self, partial_specifier_candidates, value_node):
@@ -70,7 +70,7 @@ class FString(object):
70
70
  nested_allowed.remove(quote)
71
71
 
72
72
  for v in self.node.values:
73
- if is_ast_node(v, ast.Str):
73
+ if is_constant_node(v, ast.Str):
74
74
 
75
75
  # Could this be used as a debug specifier?
76
76
  if len(candidates) < 10:
@@ -79,12 +79,12 @@ class FString(object):
79
79
  # Maybe!
80
80
  try:
81
81
  debug_specifier_candidates = [x + '{' + v.s for x in candidates]
82
- except Exception as e:
82
+ except Exception:
83
83
  continue
84
84
 
85
85
  try:
86
86
  candidates = [x + self.str_for(v.s, quote) for x in candidates]
87
- except Exception as e:
87
+ except Exception:
88
88
  continue
89
89
  elif isinstance(v, ast.FormattedValue):
90
90
  try:
@@ -93,15 +93,14 @@ class FString(object):
93
93
  x + y for x in candidates for y in FormattedValue(v, nested_allowed, self.pep701).get_candidates()
94
94
  ] + completed
95
95
  debug_specifier_candidates = []
96
- except Exception as e:
96
+ except Exception:
97
97
  continue
98
98
  else:
99
99
  raise RuntimeError('Unexpected JoinedStr value')
100
100
 
101
101
  actual_candidates += ['f' + quote + x + quote for x in candidates]
102
102
 
103
- actual_candidates = filter(self.is_correct_ast, actual_candidates)
104
- return actual_candidates
103
+ return filter(self.is_correct_ast, actual_candidates)
105
104
 
106
105
  def str_for(self, s, quote):
107
106
  return s.replace('{', '{{').replace('}', '}}')
@@ -270,7 +269,7 @@ class Str(object):
270
269
  elif c != quote:
271
270
  return quote
272
271
 
273
- raise ValueError('Couldn\'t find a quote')
272
+ raise ValueError("Couldn't find a quote")
274
273
 
275
274
  def _literals(self):
276
275
  l = ''
@@ -349,7 +348,7 @@ class FormatSpec(object):
349
348
 
350
349
  candidates = ['']
351
350
  for v in self.node.values:
352
- if is_ast_node(v, ast.Str):
351
+ if is_constant_node(v, ast.Str):
353
352
  candidates = [x + self.str_for(v.s) for x in candidates]
354
353
  elif isinstance(v, ast.FormattedValue):
355
354
  candidates = [
@@ -397,7 +396,7 @@ class Bytes(object):
397
396
  elif chr(c) != quote:
398
397
  return quote
399
398
 
400
- raise ValueError('Couldn\'t find a quote')
399
+ raise ValueError("Couldn't find a quote")
401
400
 
402
401
  def _literals(self):
403
402
  l = ''
@@ -32,7 +32,7 @@ class MiniString(object):
32
32
 
33
33
  try:
34
34
  eval(self.quote + s + self.quote)
35
- except (UnicodeDecodeError, UnicodeEncodeError) as e:
35
+ except (UnicodeDecodeError, UnicodeEncodeError):
36
36
  if self.safe_mode:
37
37
  raise
38
38
 
@@ -63,7 +63,7 @@ class MiniString(object):
63
63
  }
64
64
 
65
65
  for c in self._s:
66
- if c in escaped.keys():
66
+ if c in escaped:
67
67
  s += escaped[c]
68
68
  else:
69
69
  if self.safe_mode:
@@ -95,7 +95,7 @@ class MiniString(object):
95
95
  }
96
96
 
97
97
  for c in self._s:
98
- if c in escaped.keys():
98
+ if c in escaped:
99
99
  s += escaped[c]
100
100
  else:
101
101
  if self.safe_mode: