python-minifier 3.2.0__tar.gz → 3.4.0__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.
- {python_minifier-3.2.0/src/python_minifier.egg-info → python_minifier-3.4.0}/PKG-INFO +5 -4
- {python_minifier-3.2.0 → python_minifier-3.4.0}/README.md +2 -2
- {python_minifier-3.2.0 → python_minifier-3.4.0}/setup.py +3 -2
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/__init__.py +9 -3
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/__init__.pyi +2 -1
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/__main__.py +10 -1
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/expression_printer.py +10 -6
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/module_printer.py +6 -1
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/mapper.py +3 -1
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/rename_literals.py +3 -1
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/token_printer.py +2 -2
- python_minifier-3.4.0/src/python_minifier/transforms/combine_imports.py +119 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/constant_folding.py +33 -2
- python_minifier-3.4.0/src/python_minifier/transforms/remove_dead_branches.py +273 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_debug.py +14 -12
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/suite_transformer.py +45 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0/src/python_minifier.egg-info}/PKG-INFO +5 -4
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier.egg-info/SOURCES.txt +4 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/subprocess_compat.py +1 -1
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_combine_imports.py +19 -0
- python_minifier-3.4.0/test/test_comprehension_unpacking.py +188 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_folding.py +132 -2
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_is_constant_node.py +2 -2
- python_minifier-3.4.0/test/test_lazy_imports.py +338 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_match.py +28 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_assert.py +56 -0
- python_minifier-3.4.0/test/test_remove_dead_branches.py +695 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_debug.py +157 -5
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_pass.py +79 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_unicode_cli.py +6 -9
- python_minifier-3.2.0/src/python_minifier/transforms/combine_imports.py +0 -75
- {python_minifier-3.2.0 → python_minifier-3.4.0}/LICENSE +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/MANIFEST.in +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/setup.cfg +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/ast_annotation/__init__.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/ast_compare.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/ast_compat.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/ast_printer.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/f_string.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/ministring.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/py.typed +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/README.md +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/__init__.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/bind_names.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/binding.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/name_generator.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/renamer.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/resolve_names.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/util.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/t_string.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/__init__.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_annotations.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_annotations_options.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_annotations_options.pyi +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_asserts.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_exception_brackets.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_explicit_return_none.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_literal_statements.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_object_base.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_pass.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/remove_posargs.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/util.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier.egg-info/dependency_links.txt +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier.egg-info/entry_points.txt +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier.egg-info/top_level.txt +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier.egg-info/zip-safe +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/ast_annotation/test_add_parent.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/conftest.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/helpers.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/requirements.txt +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_assignment_expressions.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_await_fstring.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_best_effort_cli.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_bind_names.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_bind_names_namedexpr.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_bind_names_python2.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_bind_names_python312.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_bind_names_python313.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_bind_names_python33.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_comprehension_rename.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_decorator_expressions.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_dict_expansion.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_fstring.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_generic_types.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_hoist_literals.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_import.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_iterable_unpacking.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_match_rename.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_name_generator.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_nonlocal.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_posargs.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_prefer_single_line.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_preserve_shebang.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_raw_fstring_backslash.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_raw_tstring_backslash.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_annotations.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_exception_brackets.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_explicit_return_none.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_literal_statements.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_remove_object.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_rename_builtins.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_rename_locals.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_slice.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_template_strings.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_tuple_with_bug.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_type_param_defaults.py +0 -0
- {python_minifier-3.2.0 → python_minifier-3.4.0}/test/test_utf8_encoding.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python_minifier
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.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
|
|
@@ -26,13 +26,14 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
26
26
|
Classifier: Programming Language :: Python :: 3.12
|
|
27
27
|
Classifier: Programming Language :: Python :: 3.13
|
|
28
28
|
Classifier: Programming Language :: Python :: 3.14
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
29
30
|
Classifier: Programming Language :: Python :: 2
|
|
30
31
|
Classifier: Programming Language :: Python :: 2.7
|
|
31
32
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
32
33
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
33
34
|
Classifier: Intended Audience :: Developers
|
|
34
35
|
Classifier: Topic :: Software Development
|
|
35
|
-
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <3.
|
|
36
|
+
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <3.16
|
|
36
37
|
Description-Content-Type: text/markdown
|
|
37
38
|
License-File: LICENSE
|
|
38
39
|
Dynamic: author
|
|
@@ -54,7 +55,7 @@ Transforms Python source code into its most compact representation.
|
|
|
54
55
|
|
|
55
56
|
[Try it out!](https://python-minifier.com)
|
|
56
57
|
|
|
57
|
-
python-minifier currently supports Python 2.7 and Python 3.3 to 3.
|
|
58
|
+
python-minifier currently supports Python 2.7 and Python 3.3 to 3.15. Previous releases supported Python 2.6.
|
|
58
59
|
|
|
59
60
|
* [PyPI](https://pypi.org/project/python-minifier/)
|
|
60
61
|
* [Documentation](https://dflook.github.io/python-minifier/)
|
|
@@ -160,7 +161,7 @@ and outputs source code compatible with the version of the interpreter it is run
|
|
|
160
161
|
This means that if you minify code written for Python 3.11 using python-minifier running with Python 3.12,
|
|
161
162
|
the minified code may only run with Python 3.12.
|
|
162
163
|
|
|
163
|
-
python-minifier runs with and can minify code written for Python 2.7 and Python 3.3 to 3.
|
|
164
|
+
python-minifier runs with and can minify code written for Python 2.7 and Python 3.3 to 3.15.
|
|
164
165
|
|
|
165
166
|
## Usage
|
|
166
167
|
|
|
@@ -4,7 +4,7 @@ Transforms Python source code into its most compact representation.
|
|
|
4
4
|
|
|
5
5
|
[Try it out!](https://python-minifier.com)
|
|
6
6
|
|
|
7
|
-
python-minifier currently supports Python 2.7 and Python 3.3 to 3.
|
|
7
|
+
python-minifier currently supports Python 2.7 and Python 3.3 to 3.15. Previous releases supported Python 2.6.
|
|
8
8
|
|
|
9
9
|
* [PyPI](https://pypi.org/project/python-minifier/)
|
|
10
10
|
* [Documentation](https://dflook.github.io/python-minifier/)
|
|
@@ -110,7 +110,7 @@ and outputs source code compatible with the version of the interpreter it is run
|
|
|
110
110
|
This means that if you minify code written for Python 3.11 using python-minifier running with Python 3.12,
|
|
111
111
|
the minified code may only run with Python 3.12.
|
|
112
112
|
|
|
113
|
-
python-minifier runs with and can minify code written for Python 2.7 and Python 3.3 to 3.
|
|
113
|
+
python-minifier runs with and can minify code written for Python 2.7 and Python 3.3 to 3.15.
|
|
114
114
|
|
|
115
115
|
## Usage
|
|
116
116
|
|
|
@@ -26,8 +26,8 @@ setup(
|
|
|
26
26
|
long_description=long_desc,
|
|
27
27
|
long_description_content_type='text/markdown',
|
|
28
28
|
|
|
29
|
-
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <3.
|
|
30
|
-
version='3.
|
|
29
|
+
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <3.16',
|
|
30
|
+
version='3.4.0',
|
|
31
31
|
|
|
32
32
|
classifiers=[
|
|
33
33
|
'Development Status :: 5 - Production/Stable',
|
|
@@ -46,6 +46,7 @@ setup(
|
|
|
46
46
|
'Programming Language :: Python :: 3.12',
|
|
47
47
|
'Programming Language :: Python :: 3.13',
|
|
48
48
|
'Programming Language :: Python :: 3.14',
|
|
49
|
+
'Programming Language :: Python :: 3.15',
|
|
49
50
|
'Programming Language :: Python :: 2',
|
|
50
51
|
'Programming Language :: Python :: 2.7',
|
|
51
52
|
'Programming Language :: Python :: Implementation :: CPython',
|
|
@@ -25,6 +25,7 @@ from python_minifier.transforms.constant_folding import FoldConstants
|
|
|
25
25
|
from python_minifier.transforms.remove_annotations import RemoveAnnotations
|
|
26
26
|
from python_minifier.transforms.remove_annotations_options import RemoveAnnotationsOptions
|
|
27
27
|
from python_minifier.transforms.remove_asserts import RemoveAsserts
|
|
28
|
+
from python_minifier.transforms.remove_dead_branches import RemoveDeadBranches
|
|
28
29
|
from python_minifier.transforms.remove_debug import RemoveDebug
|
|
29
30
|
from python_minifier.transforms.remove_exception_brackets import remove_no_arg_exception_call
|
|
30
31
|
from python_minifier.transforms.remove_explicit_return_none import RemoveExplicitReturnNone
|
|
@@ -74,6 +75,7 @@ def minify(
|
|
|
74
75
|
remove_builtin_exception_brackets=True,
|
|
75
76
|
constant_folding=True,
|
|
76
77
|
prefer_single_line=False,
|
|
78
|
+
remove_dead_branches=True
|
|
77
79
|
):
|
|
78
80
|
"""
|
|
79
81
|
Minify a python module
|
|
@@ -109,6 +111,7 @@ def minify(
|
|
|
109
111
|
:param bool remove_builtin_exception_brackets: If brackets should be removed when raising exceptions with no arguments
|
|
110
112
|
:param bool constant_folding: If literal expressions should be evaluated
|
|
111
113
|
:param bool prefer_single_line: If semi-colons should be preferred over newlines where there is no difference in output size
|
|
114
|
+
:param bool remove_dead_branches: If if-statements with a constant False test should be removed
|
|
112
115
|
|
|
113
116
|
:rtype: str
|
|
114
117
|
|
|
@@ -155,12 +158,15 @@ def minify(
|
|
|
155
158
|
if remove_debug:
|
|
156
159
|
module = RemoveDebug()(module)
|
|
157
160
|
|
|
158
|
-
if remove_explicit_return_none:
|
|
159
|
-
module = RemoveExplicitReturnNone()(module)
|
|
160
|
-
|
|
161
161
|
if constant_folding:
|
|
162
162
|
module = FoldConstants()(module)
|
|
163
163
|
|
|
164
|
+
if remove_dead_branches:
|
|
165
|
+
module = RemoveDeadBranches()(module)
|
|
166
|
+
|
|
167
|
+
if remove_explicit_return_none:
|
|
168
|
+
module = RemoveExplicitReturnNone()(module)
|
|
169
|
+
|
|
164
170
|
bind_names(module)
|
|
165
171
|
resolve_names(module)
|
|
166
172
|
|
|
@@ -29,7 +29,8 @@ def minify(
|
|
|
29
29
|
remove_explicit_return_none: bool = ...,
|
|
30
30
|
remove_builtin_exception_brackets: bool = ...,
|
|
31
31
|
constant_folding: bool = ...,
|
|
32
|
-
prefer_single_line: bool =
|
|
32
|
+
prefer_single_line: bool = ...,
|
|
33
|
+
remove_dead_branches: bool = ...
|
|
33
34
|
) -> Text: ...
|
|
34
35
|
|
|
35
36
|
|
|
@@ -10,7 +10,6 @@ from python_minifier.transforms.remove_annotations_options import RemoveAnnotati
|
|
|
10
10
|
|
|
11
11
|
class MinificationNotBeneficialError(Exception):
|
|
12
12
|
"""Raised when minification results in larger output than the original."""
|
|
13
|
-
pass
|
|
14
13
|
|
|
15
14
|
def stdout_write_bytes(data):
|
|
16
15
|
"""Write bytes to stdout with proper Python 2.7/3.x compatibility."""
|
|
@@ -250,6 +249,12 @@ def parse_args():
|
|
|
250
249
|
help='Disable evaluating literal expressions',
|
|
251
250
|
dest='constant_folding',
|
|
252
251
|
)
|
|
252
|
+
minification_options.add_argument(
|
|
253
|
+
'--no-remove-dead-branches',
|
|
254
|
+
action='store_false',
|
|
255
|
+
help='Disable removing branches that are never executed',
|
|
256
|
+
dest='remove_dead_branches',
|
|
257
|
+
)
|
|
253
258
|
|
|
254
259
|
annotation_options = parser.add_argument_group('remove annotations options', 'Options that affect how annotations are removed')
|
|
255
260
|
annotation_options.add_argument(
|
|
@@ -305,6 +310,10 @@ def parse_args():
|
|
|
305
310
|
sys.stderr.write('error: --remove-class-attribute-annotations would do nothing when used with --no-remove-annotations\n')
|
|
306
311
|
sys.exit(1)
|
|
307
312
|
|
|
313
|
+
if args.remove_debug and not args.remove_dead_branches:
|
|
314
|
+
sys.stderr.write('error: --remove-debug would do nothing when used with --no-remove-dead-branches\n')
|
|
315
|
+
sys.exit(1)
|
|
316
|
+
|
|
308
317
|
return args
|
|
309
318
|
|
|
310
319
|
|
|
@@ -221,9 +221,7 @@ class ExpressionPrinter(object):
|
|
|
221
221
|
right_precedence = self.precedence(node.operand)
|
|
222
222
|
op_precedence = self.precedence(node)
|
|
223
223
|
|
|
224
|
-
if right_precedence != 0 and
|
|
225
|
-
(op_precedence > right_precedence)
|
|
226
|
-
):
|
|
224
|
+
if right_precedence != 0 and op_precedence > right_precedence:
|
|
227
225
|
self.printer.delimiter('(')
|
|
228
226
|
self._expression(node.operand)
|
|
229
227
|
self.printer.delimiter(')')
|
|
@@ -526,9 +524,15 @@ class ExpressionPrinter(object):
|
|
|
526
524
|
|
|
527
525
|
def visit_DictComp(self, node):
|
|
528
526
|
self.printer.delimiter('{')
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
527
|
+
|
|
528
|
+
if node.value is None:
|
|
529
|
+
self.printer.operator('**')
|
|
530
|
+
self._expression(node.key)
|
|
531
|
+
else:
|
|
532
|
+
self._expression(node.key)
|
|
533
|
+
self.printer.delimiter(':')
|
|
534
|
+
self._expression(node.value)
|
|
535
|
+
|
|
532
536
|
[self.visit_comprehension(x) for x in node.generators]
|
|
533
537
|
self.printer.delimiter('}')
|
|
534
538
|
|
|
@@ -234,6 +234,8 @@ class ModulePrinter(ExpressionPrinter):
|
|
|
234
234
|
def visit_Import(self, node):
|
|
235
235
|
assert isinstance(node, ast.Import)
|
|
236
236
|
|
|
237
|
+
if getattr(node, 'is_lazy', 0) == 1:
|
|
238
|
+
self.printer.keyword('lazy')
|
|
237
239
|
self.printer.keyword('import')
|
|
238
240
|
|
|
239
241
|
delimiter = Delimiter(self.printer)
|
|
@@ -246,6 +248,9 @@ class ModulePrinter(ExpressionPrinter):
|
|
|
246
248
|
def visit_ImportFrom(self, node):
|
|
247
249
|
assert isinstance(node, ast.ImportFrom)
|
|
248
250
|
|
|
251
|
+
if getattr(node, 'is_lazy', 0) == 1:
|
|
252
|
+
self.printer.keyword('lazy')
|
|
253
|
+
|
|
249
254
|
self.printer.keyword('from')
|
|
250
255
|
for _i in range(node.level):
|
|
251
256
|
self.printer.delimiter('.')
|
|
@@ -602,7 +607,7 @@ class ModulePrinter(ExpressionPrinter):
|
|
|
602
607
|
|
|
603
608
|
if node.guard is not None:
|
|
604
609
|
self.printer.keyword('if')
|
|
605
|
-
self.
|
|
610
|
+
self._expression(node.guard)
|
|
606
611
|
|
|
607
612
|
self.printer.delimiter(':')
|
|
608
613
|
self._suite(node.body)
|
|
@@ -104,7 +104,9 @@ def add_parent_to_comprehension(node, namespace):
|
|
|
104
104
|
add_parent(node.elt, namespace=node)
|
|
105
105
|
elif hasattr(node, 'key'):
|
|
106
106
|
add_parent(node.key, namespace=node)
|
|
107
|
-
|
|
107
|
+
|
|
108
|
+
if node.value is not None:
|
|
109
|
+
add_parent(node.value, namespace=node)
|
|
108
110
|
|
|
109
111
|
iter_namespace = namespace
|
|
110
112
|
for generator in node.generators:
|
{python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/rename/rename_literals.py
RENAMED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
|
|
1
3
|
import python_minifier.ast_compat as ast
|
|
2
4
|
from python_minifier.ast_annotation import get_parent, set_parent
|
|
3
5
|
|
|
@@ -118,7 +120,7 @@ class HoistLiterals(NodeVisitor):
|
|
|
118
120
|
def __call__(self, module, ignore_slots=True):
|
|
119
121
|
self.module = module
|
|
120
122
|
self._ignore_slots = ignore_slots
|
|
121
|
-
self._hoisted =
|
|
123
|
+
self._hoisted = OrderedDict()
|
|
122
124
|
self.visit(module)
|
|
123
125
|
self.place_bindings()
|
|
124
126
|
|
|
@@ -130,7 +130,7 @@ class TokenPrinter(object):
|
|
|
130
130
|
'or', 'pass', 'raise', 'return',
|
|
131
131
|
'try', 'while', 'with', 'yield', '_',
|
|
132
132
|
'case', 'match', 'print', 'exec',
|
|
133
|
-
'type'
|
|
133
|
+
'type', 'lazy'
|
|
134
134
|
]
|
|
135
135
|
|
|
136
136
|
if self.previous_token in [TokenTypes.Identifier, TokenTypes.Keyword, TokenTypes.SoftKeyword, TokenTypes.NumberLiteral]:
|
|
@@ -138,7 +138,7 @@ class TokenPrinter(object):
|
|
|
138
138
|
|
|
139
139
|
self._code += kw
|
|
140
140
|
|
|
141
|
-
if kw in ['_', 'case', 'match', 'type']:
|
|
141
|
+
if kw in ['_', 'case', 'match', 'type', 'lazy']:
|
|
142
142
|
self.previous_token = TokenTypes.SoftKeyword
|
|
143
143
|
else:
|
|
144
144
|
self.previous_token = TokenTypes.Keyword
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import python_minifier.ast_compat as ast
|
|
2
|
+
|
|
3
|
+
from python_minifier.transforms.suite_transformer import SuiteTransformer
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def import_kwargs(import_node):
|
|
7
|
+
lazy = getattr(import_node, 'is_lazy', None)
|
|
8
|
+
if lazy is None:
|
|
9
|
+
return {}
|
|
10
|
+
return {'is_lazy': lazy}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CombineImports(SuiteTransformer):
|
|
14
|
+
"""
|
|
15
|
+
Combine multiple import statements where possible
|
|
16
|
+
|
|
17
|
+
This doesn't change the order of imports
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def _combine_import(self, node_list, parent):
|
|
22
|
+
|
|
23
|
+
prev_import = None
|
|
24
|
+
alias = []
|
|
25
|
+
|
|
26
|
+
def can_merge_with_previous_group(statement):
|
|
27
|
+
if not isinstance(statement, ast.Import):
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
if prev_import is None:
|
|
31
|
+
return True
|
|
32
|
+
|
|
33
|
+
if getattr(statement, 'is_lazy', None) != getattr(prev_import, 'is_lazy', None):
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
return True
|
|
37
|
+
|
|
38
|
+
def can_create_group(statement):
|
|
39
|
+
return isinstance(statement, ast.Import)
|
|
40
|
+
|
|
41
|
+
for statement in node_list:
|
|
42
|
+
if can_merge_with_previous_group(statement):
|
|
43
|
+
prev_import = statement
|
|
44
|
+
alias += statement.names
|
|
45
|
+
else:
|
|
46
|
+
if alias:
|
|
47
|
+
yield self.add_child(ast.Import(names=alias, **import_kwargs(prev_import)), parent=parent, namespace=prev_import.namespace)
|
|
48
|
+
prev_import = None
|
|
49
|
+
alias = []
|
|
50
|
+
|
|
51
|
+
if can_create_group(statement):
|
|
52
|
+
prev_import = statement
|
|
53
|
+
alias += statement.names
|
|
54
|
+
else:
|
|
55
|
+
yield statement
|
|
56
|
+
|
|
57
|
+
if alias:
|
|
58
|
+
yield self.add_child(ast.Import(names=alias, **import_kwargs(prev_import)), parent=parent, namespace=prev_import.namespace)
|
|
59
|
+
|
|
60
|
+
def _combine_import_from(self, node_list, parent):
|
|
61
|
+
|
|
62
|
+
prev_import = None
|
|
63
|
+
alias = []
|
|
64
|
+
|
|
65
|
+
def can_merge_with_previous_group(statement):
|
|
66
|
+
if not isinstance(statement, ast.ImportFrom):
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
if len(statement.names) == 1 and statement.names[0].name == '*':
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
if prev_import is None:
|
|
73
|
+
return True
|
|
74
|
+
|
|
75
|
+
if getattr(statement, 'is_lazy', None) != getattr(prev_import, 'is_lazy', None):
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
if statement.module == prev_import.module and statement.level == prev_import.level:
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
def can_create_group(statement):
|
|
84
|
+
if not isinstance(statement, ast.ImportFrom):
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
if len(statement.names) == 1 and statement.names[0].name == '*':
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
return True
|
|
91
|
+
|
|
92
|
+
for statement in node_list:
|
|
93
|
+
if can_merge_with_previous_group(statement):
|
|
94
|
+
prev_import = statement
|
|
95
|
+
alias += statement.names
|
|
96
|
+
else:
|
|
97
|
+
if alias:
|
|
98
|
+
yield self.add_child(
|
|
99
|
+
ast.ImportFrom(module=prev_import.module, names=alias, level=prev_import.level, **import_kwargs(prev_import)), parent=parent, namespace=prev_import.namespace
|
|
100
|
+
)
|
|
101
|
+
prev_import = None
|
|
102
|
+
alias = []
|
|
103
|
+
|
|
104
|
+
if can_create_group(statement):
|
|
105
|
+
prev_import = statement
|
|
106
|
+
alias += statement.names
|
|
107
|
+
else:
|
|
108
|
+
yield statement
|
|
109
|
+
|
|
110
|
+
if alias:
|
|
111
|
+
yield self.add_child(
|
|
112
|
+
ast.ImportFrom(module=prev_import.module, names=alias, level=prev_import.level, **import_kwargs(prev_import)), parent=parent, namespace=prev_import.namespace
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def suite(self, node_list, parent):
|
|
116
|
+
a = list(self._combine_import(node_list, parent))
|
|
117
|
+
b = list(self._combine_import_from(a, parent))
|
|
118
|
+
|
|
119
|
+
return [self.visit(n) for n in b]
|
{python_minifier-3.2.0 → python_minifier-3.4.0}/src/python_minifier/transforms/constant_folding.py
RENAMED
|
@@ -14,7 +14,7 @@ def is_foldable_constant(node):
|
|
|
14
14
|
"""
|
|
15
15
|
Check if a node is a constant expression that can participate in folding.
|
|
16
16
|
|
|
17
|
-
We can
|
|
17
|
+
We can assume that children have already been folded, so foldable constants are either:
|
|
18
18
|
- Simple literals (Num, NameConstant)
|
|
19
19
|
- UnaryOp(USub/Invert) on a Num - these don't fold to shorter forms,
|
|
20
20
|
so they remain after child visiting. UAdd and Not would have been
|
|
@@ -42,7 +42,14 @@ class FoldConstants(SuiteTransformer):
|
|
|
42
42
|
# Evaluate the expression
|
|
43
43
|
try:
|
|
44
44
|
original_expression = unparse_expression(node)
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.Invert) and is_constant_node(node.operand, ast.NameConstant) and isinstance(node.operand.value, bool):
|
|
47
|
+
# ~ on a bool is deprecated from python 3.12, to be removed in 3.16.
|
|
48
|
+
if sys.version_info >= (3, 16):
|
|
49
|
+
return node
|
|
50
|
+
original_value = ~int(node.operand.value)
|
|
51
|
+
else:
|
|
52
|
+
original_value = safe_eval(original_expression)
|
|
46
53
|
except Exception:
|
|
47
54
|
return node
|
|
48
55
|
|
|
@@ -119,6 +126,30 @@ class FoldConstants(SuiteTransformer):
|
|
|
119
126
|
|
|
120
127
|
return self.fold(node)
|
|
121
128
|
|
|
129
|
+
def visit_BoolOp(self, node):
|
|
130
|
+
node.values = [self.visit(v) for v in node.values]
|
|
131
|
+
|
|
132
|
+
# Check this is a constant expression that could be folded
|
|
133
|
+
if not all(is_foldable_constant(v) for v in node.values):
|
|
134
|
+
return node
|
|
135
|
+
|
|
136
|
+
return self.fold(node)
|
|
137
|
+
|
|
138
|
+
def visit_Compare(self, node):
|
|
139
|
+
node.left = self.visit(node.left)
|
|
140
|
+
node.comparators = [self.visit(c) for c in node.comparators]
|
|
141
|
+
|
|
142
|
+
operands = [node.left] + node.comparators
|
|
143
|
+
if not all(is_foldable_constant(n) for n in operands):
|
|
144
|
+
return node
|
|
145
|
+
|
|
146
|
+
if any(isinstance(op, (ast.Is, ast.IsNot)) for op in node.ops):
|
|
147
|
+
# Identity is only language-guaranteed for the singletons
|
|
148
|
+
if not all(is_constant_node(n, ast.NameConstant) for n in operands):
|
|
149
|
+
return node
|
|
150
|
+
|
|
151
|
+
return self.fold(node)
|
|
152
|
+
|
|
122
153
|
def visit_UnaryOp(self, node):
|
|
123
154
|
|
|
124
155
|
node.operand = self.visit(node.operand)
|