python-minifier 3.1.1__py2-none-any.whl → 3.2.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.
@@ -72,7 +72,8 @@ def minify(
72
72
  remove_debug=False,
73
73
  remove_explicit_return_none=True,
74
74
  remove_builtin_exception_brackets=True,
75
- constant_folding=True
75
+ constant_folding=True,
76
+ prefer_single_line=False,
76
77
  ):
77
78
  """
78
79
  Minify a python module
@@ -107,6 +108,7 @@ def minify(
107
108
  :param bool remove_explicit_return_none: If explicit return None statements should be replaced with a bare return
108
109
  :param bool remove_builtin_exception_brackets: If brackets should be removed when raising exceptions with no arguments
109
110
  :param bool constant_folding: If literal expressions should be evaluated
111
+ :param bool prefer_single_line: If semi-colons should be preferred over newlines where there is no difference in output size
110
112
 
111
113
  :rtype: str
112
114
 
@@ -192,7 +194,7 @@ def minify(
192
194
  if convert_posargs_to_args:
193
195
  module = remove_posargs(module)
194
196
 
195
- minified = unparse(module)
197
+ minified = unparse(module, prefer_single_line=prefer_single_line)
196
198
 
197
199
  if preserve_shebang is True:
198
200
  shebang_line = _find_shebang(source)
@@ -219,7 +221,7 @@ def _find_shebang(source):
219
221
  return None
220
222
 
221
223
 
222
- def unparse(module):
224
+ def unparse(module, prefer_single_line=False):
223
225
  """
224
226
  Turn a module AST into python code
225
227
 
@@ -228,13 +230,14 @@ def unparse(module):
228
230
 
229
231
  :param module: The module to turn into python code
230
232
  :type: module: :class:`ast.Module`
233
+ :param bool prefer_single_line: If semi-colons should be preferred over newlines where there is no difference in output size
231
234
  :rtype: str
232
235
 
233
236
  """
234
237
 
235
238
  assert isinstance(module, ast.Module)
236
239
 
237
- printer = ModulePrinter()
240
+ printer = ModulePrinter(prefer_single_line=prefer_single_line)
238
241
  printer(module)
239
242
 
240
243
  try:
@@ -28,11 +28,15 @@ def minify(
28
28
  remove_debug: bool = ...,
29
29
  remove_explicit_return_none: bool = ...,
30
30
  remove_builtin_exception_brackets: bool = ...,
31
- constant_folding: bool = ...
31
+ constant_folding: bool = ...,
32
+ prefer_single_line: bool = ...
32
33
  ) -> Text: ...
33
34
 
34
35
 
35
- def unparse(module: ast.Module) -> Text: ...
36
+ def unparse(
37
+ module: ast.Module,
38
+ prefer_single_line: bool = ...
39
+ ) -> Text: ...
36
40
 
37
41
 
38
42
  def awslambda(
@@ -140,6 +140,13 @@ def parse_args():
140
140
  dest='in_place'
141
141
  )
142
142
 
143
+ parser.add_argument(
144
+ '--prefer-single-line',
145
+ action='store_true',
146
+ help='Prefer multiple statements on a single line separated by semicolons, instead of newlines, where there is no difference in output size',
147
+ dest='prefer_single_line',
148
+ )
149
+
143
150
  # Minification arguments
144
151
  minification_options = parser.add_argument_group('minification options', 'Options that affect how the source is minified')
145
152
  minification_options.add_argument(
@@ -373,7 +380,8 @@ def do_minify(source, filename, minification_args):
373
380
  remove_debug=minification_args.remove_debug,
374
381
  remove_explicit_return_none=minification_args.remove_explicit_return_none,
375
382
  remove_builtin_exception_brackets=minification_args.remove_exception_brackets,
376
- constant_folding=minification_args.constant_folding
383
+ constant_folding=minification_args.constant_folding,
384
+ prefer_single_line=minification_args.prefer_single_line,
377
385
  )
378
386
 
379
387
  # Encode minified result to bytes for comparison and output
@@ -11,7 +11,7 @@ class ExpressionPrinter(object):
11
11
  Builds the smallest possible exact representation of an ast
12
12
  """
13
13
 
14
- def __init__(self):
14
+ def __init__(self, prefer_single_line=False):
15
15
 
16
16
  self.precedences = {
17
17
  'Lambda': 2, # Lambda
@@ -34,7 +34,7 @@ class ExpressionPrinter(object):
34
34
  'Tuple': 18, 'Set': 18, 'List': 18, 'Dict': 18, 'ListComp': 18, 'SetComp': 18, 'DictComp': 18, 'GeneratorExp': 18, # Container
35
35
  }
36
36
 
37
- self.printer = TokenPrinter()
37
+ self.printer = TokenPrinter(prefer_single_line=prefer_single_line)
38
38
 
39
39
  def __call__(self, module):
40
40
  """
@@ -11,8 +11,8 @@ class ModulePrinter(ExpressionPrinter):
11
11
  Builds the smallest possible exact representation of an ast
12
12
  """
13
13
 
14
- def __init__(self, indent_char='\t'):
15
- super(ModulePrinter, self).__init__()
14
+ def __init__(self, indent_char='\t', prefer_single_line=False):
15
+ super(ModulePrinter, self).__init__(prefer_single_line=prefer_single_line)
16
16
  self.indent_char = indent_char
17
17
 
18
18
  def __call__(self, module):
@@ -306,7 +306,7 @@ class TokenPrinter(object):
306
306
  def end_statement(self):
307
307
  """ End a statement with a newline, or a semi-colon if it saves characters. """
308
308
 
309
- if self.indent == 0:
309
+ if self.indent == 0 and not self._prefer_single_line:
310
310
  self.newline()
311
311
  else:
312
312
  if self._code[-1] != ';':
@@ -10,36 +10,35 @@ from python_minifier.transforms.suite_transformer import SuiteTransformer
10
10
  from python_minifier.util import is_constant_node
11
11
 
12
12
 
13
- class FoldConstants(SuiteTransformer):
14
- """
15
- Fold Constants if it would reduce the size of the source
13
+ def is_foldable_constant(node):
16
14
  """
15
+ Check if a node is a constant expression that can participate in folding.
17
16
 
18
- def __init__(self):
19
- super(FoldConstants, self).__init__()
17
+ We can asume that children have already been folded, so foldable constants are either:
18
+ - Simple literals (Num, NameConstant)
19
+ - UnaryOp(USub/Invert) on a Num - these don't fold to shorter forms,
20
+ so they remain after child visiting. UAdd and Not would have been
21
+ folded away since they always produce shorter results.
22
+ """
23
+ if is_constant_node(node, (ast.Num, ast.NameConstant)):
24
+ return True
20
25
 
21
- def visit_BinOp(self, node):
26
+ if isinstance(node, ast.UnaryOp):
27
+ if isinstance(node.op, (ast.USub, ast.Invert)):
28
+ return is_constant_node(node.operand, ast.Num)
22
29
 
23
- node.left = self.visit(node.left)
24
- node.right = self.visit(node.right)
30
+ return False
25
31
 
26
- # Check this is a constant expression that could be folded
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
28
- if not is_constant_node(node.left, (ast.Num, ast.NameConstant)):
29
- return node
30
- if not is_constant_node(node.right, (ast.Num, ast.NameConstant)):
31
- return node
32
32
 
33
- if isinstance(node.op, ast.Div):
34
- # Folding div is subtle, since it can have different results in Python 2 and Python 3
35
- # Do this once target version options have been implemented
36
- return node
33
+ class FoldConstants(SuiteTransformer):
34
+ """
35
+ Fold Constants if it would reduce the size of the source
36
+ """
37
37
 
38
- if isinstance(node.op, ast.Pow):
39
- # This can be folded, but it is unlikely to reduce the size of the source
40
- # It can also be slow to evaluate
41
- return node
38
+ def __init__(self):
39
+ super(FoldConstants, self).__init__()
42
40
 
41
+ def fold(self, node):
43
42
  # Evaluate the expression
44
43
  try:
45
44
  original_expression = unparse_expression(node)
@@ -96,6 +95,44 @@ class FoldConstants(SuiteTransformer):
96
95
  # New representation is shorter and has the same value, so use it
97
96
  return self.add_child(new_node, get_parent(node), node.namespace)
98
97
 
98
+ def visit_BinOp(self, node):
99
+
100
+ node.left = self.visit(node.left)
101
+ node.right = self.visit(node.right)
102
+
103
+ # Check this is a constant expression that could be folded
104
+ # 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
105
+ if not is_foldable_constant(node.left):
106
+ return node
107
+ if not is_foldable_constant(node.right):
108
+ return node
109
+
110
+ if isinstance(node.op, ast.Div):
111
+ # Folding div is subtle, since it can have different results in Python 2 and Python 3
112
+ # Do this once target version options have been implemented
113
+ return node
114
+
115
+ if isinstance(node.op, ast.Pow):
116
+ # This can be folded, but it is unlikely to reduce the size of the source
117
+ # It can also be slow to evaluate
118
+ return node
119
+
120
+ return self.fold(node)
121
+
122
+ def visit_UnaryOp(self, node):
123
+
124
+ node.operand = self.visit(node.operand)
125
+
126
+ # Only fold if the operand is a foldable constant
127
+ if not is_foldable_constant(node.operand):
128
+ return node
129
+
130
+ # Only fold these unary operators
131
+ if not isinstance(node.op, (ast.USub, ast.UAdd, ast.Invert, ast.Not)):
132
+ return node
133
+
134
+ return self.fold(node)
135
+
99
136
 
100
137
  def equal_value_and_type(a, b):
101
138
  if type(a) != type(b):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-minifier
3
- Version: 3.1.1
3
+ Version: 3.2.0
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
@@ -1,16 +1,16 @@
1
- python_minifier/__init__.py,sha256=Q95ufDbd7hadjVtJZYclsJqX9S4NsKZSpqCui0Fw7oI,9542
2
- python_minifier/__init__.pyi,sha256=-xLoKXbQsV7ko_YzyXL9WkI2vmGc6yn4AW5biK_GJXE,1233
3
- python_minifier/__main__.py,sha256=r7_Vh9n-aoc4jd5CERKO3KqJeqXHeWoycDRlvV7xTFM,14053
1
+ python_minifier/__init__.py,sha256=L77ebjrfZzWX9Xdpza_Z2Io0WyPRl24euDpXl0-8l8k,9933
2
+ python_minifier/__init__.pyi,sha256=PM-ZRAim7MdSSn4-ts3KrgagxoeCXTL5S2lGEVSjU9I,1311
3
+ python_minifier/__main__.py,sha256=4hpug2STfQwMKQS2adA_19aQm0vke38Y6ZYNAzShm-0,14397
4
4
  python_minifier/ast_compare.py,sha256=KQyS9TGA1SoCs8uu4iks1IINFb_pEj7x38Q4oiERWnI,3381
5
5
  python_minifier/ast_compat.py,sha256=DFJ7WmrEfYXfaby8EWt1aRlcqVPPoXD4Fh9Hnb9dLCU,2250
6
6
  python_minifier/ast_printer.py,sha256=TlkyKl9_9ScWeop3W1TwXZ46MJWINfkJ7NvmULpwt4A,3254
7
- python_minifier/expression_printer.py,sha256=rBegwnqsjT_buJwSqK_piLwnfCwPyshzUUYgShoZPB4,22676
7
+ python_minifier/expression_printer.py,sha256=DYun-j66MOdY3aTNRdfokFyJASc1uCNzAxuUG401D6Y,22739
8
8
  python_minifier/f_string.py,sha256=eXYXaxEMSB3iHY_M_RXYpeloJV-7TYnhWIGge0KYCk8,18314
9
9
  python_minifier/ministring.py,sha256=R0xaAZqMlLu1Jm0aBVSI0n8KZiZV7PTs4RE4UbCmTy8,4359
10
- python_minifier/module_printer.py,sha256=zVdsUXm2GkdbIbNUyuavaOWRhn7FP93UqRibhuiokfQ,25602
10
+ python_minifier/module_printer.py,sha256=kLQqRAqkg1-UDvjvz_7R2UBkV_yoDKVheVR9P6LbckA,25665
11
11
  python_minifier/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  python_minifier/t_string.py,sha256=z3KzWaSDqvy701SY3dm8VSkiJuiUfopSWGNIm-nDpAo,13261
13
- python_minifier/token_printer.py,sha256=MoVyC_ufvTXtI5bAIq6XdWDrkUTF6oYBmto3ILfq_KU,9983
13
+ python_minifier/token_printer.py,sha256=mF56xx-rdq51gWzVvewh4LpobPfPcFAxOQ3GSMsTJi0,10016
14
14
  python_minifier/util.py,sha256=60iT3XkKlPlZhXQ1NuLB27Wv3ihl-gBC_WjOjEiFn-Q,1184
15
15
  python_minifier/ast_annotation/__init__.py,sha256=BJ4gyS-_bytIZf0SP8JJG6FECWf8MUaUi3vOAfD60qQ,2259
16
16
  python_minifier/rename/__init__.py,sha256=8DLEFgliakf_5T_m-l1Nd35QxKpM4h7RJyFVpjsxjWA,375
@@ -24,7 +24,7 @@ python_minifier/rename/resolve_names.py,sha256=VbePyUUqggvvcF3fAC6XMv6b3Kmb_cmlO
24
24
  python_minifier/rename/util.py,sha256=ItJykxM_QRjIePMcKYo-LngmP5hLQZK-bOZIefg1cKA,5469
25
25
  python_minifier/transforms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  python_minifier/transforms/combine_imports.py,sha256=7DkNBsTLiiEw01Epa2xj8zkAyVMG3pCTJNlZktqDwDI,2297
27
- python_minifier/transforms/constant_folding.py,sha256=wcCtjHa0WfYHI0Encs3IPHjZgumkN-ijNerMZgXu_g4,4538
27
+ python_minifier/transforms/constant_folding.py,sha256=05i7hKmtAGKj26HvBY75OHdNo-OfAm6Q-aFIdij6y-0,5663
28
28
  python_minifier/transforms/remove_annotations.py,sha256=qUCdl42yvq1g7B43d88EOz6Jf51A5zogYBlFHGnyugU,4938
29
29
  python_minifier/transforms/remove_annotations_options.py,sha256=kzg-gEPwhrCZxsuzdpEWjqnhsyF89hnIPv1t-IRty64,1889
30
30
  python_minifier/transforms/remove_annotations_options.pyi,sha256=jZp8hUQ-BfqU1qA_nsPiluMM-1jznSX3pzbmysvKv-c,518
@@ -37,10 +37,10 @@ python_minifier/transforms/remove_object_base.py,sha256=j4se6OXyZK1lr_ABmGT0Oivu
37
37
  python_minifier/transforms/remove_pass.py,sha256=S9e59nBEZ8rBBifvAhbPRDTfUA7s8_a7pSIsZbFZD2A,735
38
38
  python_minifier/transforms/remove_posargs.py,sha256=aV0wFnGiDXu4uQBQP7-cB1uLSF3mamIq5-txvDg8BVo,314
39
39
  python_minifier/transforms/suite_transformer.py,sha256=WZCVkkBSniWeEtBybVweeMmy-A1wC3lBIYSgxCHelBU,6324
40
- python_minifier-3.1.1.dist-info/LICENSE,sha256=FzsyDHb8pAZupSGFjIOuHcHMlFf6N-aIxq9gOYGbNyE,1069
41
- python_minifier-3.1.1.dist-info/METADATA,sha256=szq8DMXjTaRYTE-tUW8lKyMiojWV2yyu6l2wGSaxu5k,6502
42
- python_minifier-3.1.1.dist-info/WHEEL,sha256=1VPi6hfNQaRRNuEdK_3dv9o8COtLGnHWJghhj4CQ28k,92
43
- python_minifier-3.1.1.dist-info/entry_points.txt,sha256=aS7ZUWQeeys8lAbrmmEa2__Bg-anH1tUMyi9cKdTbO4,60
44
- python_minifier-3.1.1.dist-info/top_level.txt,sha256=4SRDfWKi_KMq7LDrjlzUFoDCs6INYPtxc1Pun4z8LsU,16
45
- python_minifier-3.1.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
46
- python_minifier-3.1.1.dist-info/RECORD,,
40
+ python_minifier-3.2.0.dist-info/LICENSE,sha256=FzsyDHb8pAZupSGFjIOuHcHMlFf6N-aIxq9gOYGbNyE,1069
41
+ python_minifier-3.2.0.dist-info/METADATA,sha256=aM3kblW9A58nv9sWw2x_ebASoSGuuO-3u5MSuxItNzk,6502
42
+ python_minifier-3.2.0.dist-info/WHEEL,sha256=1VPi6hfNQaRRNuEdK_3dv9o8COtLGnHWJghhj4CQ28k,92
43
+ python_minifier-3.2.0.dist-info/entry_points.txt,sha256=aS7ZUWQeeys8lAbrmmEa2__Bg-anH1tUMyi9cKdTbO4,60
44
+ python_minifier-3.2.0.dist-info/top_level.txt,sha256=4SRDfWKi_KMq7LDrjlzUFoDCs6INYPtxc1Pun4z8LsU,16
45
+ python_minifier-3.2.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
46
+ python_minifier-3.2.0.dist-info/RECORD,,