Skip to content

Commit 54ebab7

Browse files
committed
Add module-level remove_unused_platforms option
Signed-off-by: Gary Thompson <[email protected]>
1 parent eb46ee6 commit 54ebab7

File tree

8 files changed

+668
-4
lines changed

8 files changed

+668
-4
lines changed

docs/source/transforms/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ They can be enabled or disabled through the minify function, or passing options
2929
rename_globals
3030
remove_asserts
3131
remove_debug
32+
remove_unused_platforms
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
value = 10
2+
_PLATFORM = "linux" # Normally this is derived from sys.uname or platform.
3+
4+
# Supported Statements that will be kept in this example
5+
if _PLATFORM == "linux":
6+
value += 1
7+
8+
9+
# Supported Statements that will be removed in this example
10+
if _PLATFORM == "armchair":
11+
value += 1
12+
13+
# Basic if/elif can be used
14+
15+
if _PLATFORM == "linux":
16+
value += 1
17+
elif _PLATFORM == "armchair":
18+
value += 1
19+
20+
# So can else
21+
if _PLATFORM == "armchair":
22+
value += 1
23+
else:
24+
value += 1
25+
26+
# Statements that are not supported by PyMinify
27+
if _PLATFORM:
28+
value += 1
29+
30+
if _PLATFORM in ["linux", "windows"]:
31+
value += 1
32+
33+
34+
print(value)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
Remove Unused Platforms
2+
=======================
3+
4+
This transform removes ``if`` blocks that do not match a platform value. This only supports
5+
module level if blocks and is configured to keep a single explicit match.
6+
7+
The transform is disabled by default.
8+
9+
When using the API, enable it by either passing ``remove_unused_platforms=True``
10+
argument to the :func:`python_minifier.minify`, or by passing ``remove_unused_platforms=unused_option``
11+
to the function where unused_option is an instance of :class:`RemoveUnusedPlatformOptions`.
12+
13+
When using the pyminify command, enable it with ``--remove-unused-platforms`` and set the options
14+
as required.
15+
16+
Options
17+
-------
18+
19+
These arguments can be used with the pyminify command as shown by the following examples:
20+
21+
``--platform-test-key=_PLATFORM`` The variable name that is testing the platform
22+
23+
``--platform-preserve-value=linux`` The value that matches the target platform
24+
25+
26+
Example
27+
-------
28+
29+
Input
30+
~~~~~
31+
32+
.. literalinclude:: remove_unused_platforms.py
33+
34+
Output
35+
~~~~~~
36+
37+
.. literalinclude:: remove_unused_platforms.min.py
38+
:language: python

src/python_minifier/__init__.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
from python_minifier.transforms.remove_object_base import RemoveObject
3333
from python_minifier.transforms.remove_pass import RemovePass
3434
from python_minifier.transforms.remove_posargs import remove_posargs
35+
from python_minifier.transforms.remove_unused_platform_options import RemoveUnusedPlatformOptions
36+
from python_minifier.transforms.remove_unused_platforms import RemoveUnusedPlatforms
3537

3638

3739
class UnstableMinification(RuntimeError):
@@ -72,12 +74,13 @@ def minify(
7274
remove_debug=False,
7375
remove_explicit_return_none=True,
7476
remove_builtin_exception_brackets=True,
75-
constant_folding=True
77+
constant_folding=True,
78+
remove_unused_platforms=RemoveUnusedPlatformOptions(),
7679
):
7780
"""
7881
Minify a python module
7982
80-
The module is transformed according the the arguments.
83+
The module is transformed according the arguments.
8184
If all transformation arguments are False, no transformations are made to the AST, the returned string will
8285
parse into exactly the same module.
8386
@@ -106,7 +109,8 @@ def minify(
106109
:param bool remove_explicit_return_none: If explicit return None statements should be replaced with a bare return
107110
:param bool remove_builtin_exception_brackets: If brackets should be removed when raising exceptions with no arguments
108111
:param bool constant_folding: If literal expressions should be evaluated
109-
112+
:param remove_unused_platforms: If top level platform masking blocks can be removed.
113+
:type remove_unused_platforms: bool or RemoveUnusedPlatformOptions
110114
:rtype: str
111115
112116
"""
@@ -157,6 +161,20 @@ def minify(
157161
if constant_folding:
158162
module = FoldConstants()(module)
159163

164+
if isinstance(remove_unused_platforms, bool):
165+
remove_unused_platforms_options = RemoveUnusedPlatformOptions(
166+
platform_test_key=RemoveUnusedPlatformOptions.platform_test_key,
167+
platform_preserve_value=RemoveUnusedPlatformOptions.platform_preserve_value,
168+
)
169+
elif isinstance(remove_unused_platforms, RemoveUnusedPlatformOptions):
170+
remove_unused_platforms_options = remove_unused_platforms
171+
else:
172+
raise TypeError('remove_unused_platforms must be a bool or RemoveUnusedPlatformOptions')
173+
174+
if remove_unused_platforms_options:
175+
module = RemoveUnusedPlatforms(remove_unused_platforms_options)(module)
176+
177+
160178
bind_names(module)
161179
resolve_names(module)
162180

src/python_minifier/__main__.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from python_minifier import minify
1010
from python_minifier.transforms.remove_annotations_options import RemoveAnnotationsOptions
11+
from python_minifier.transforms.remove_unused_platform_options import RemoveUnusedPlatformOptions
1112

1213
try:
1314
version = get_distribution('python_minifier').version
@@ -229,6 +230,30 @@ def parse_args():
229230
dest='remove_class_attribute_annotations',
230231
)
231232

233+
234+
platform_options = parser.add_argument_group('remove unused platform options', 'Options that affect platform removal')
235+
platform_options.add_argument(
236+
'--remove-unused-platforms',
237+
action='store_true',
238+
help='Remove code blocks that are masked out for a specific platform',
239+
dest='remove_unused_platforms',
240+
)
241+
platform_options.add_argument(
242+
'--platform-test-key',
243+
type=str,
244+
default="_PLATFORM",
245+
help='The variable name that is testing for a platform',
246+
dest='platform_test_key',
247+
)
248+
platform_options.add_argument(
249+
'--platform-preserve-value',
250+
type=str,
251+
default="linux",
252+
help='The value that matches the target platform',
253+
dest='platform_preserve_value',
254+
)
255+
256+
232257
parser.add_argument('--version', '-v', action='version', version=version)
233258

234259
args = parser.parse_args()
@@ -296,6 +321,17 @@ def do_minify(source, filename, minification_args):
296321
remove_class_attribute_annotations=minification_args.remove_class_attribute_annotations,
297322
)
298323

324+
if minification_args.remove_unused_platforms is False:
325+
remove_unused_platforms = RemoveUnusedPlatformOptions(
326+
platform_test_key="",
327+
platform_preserve_value=""
328+
)
329+
else:
330+
remove_unused_platforms = RemoveUnusedPlatformOptions(
331+
platform_test_key=minification_args.platform_test_key,
332+
platform_preserve_value=minification_args.platform_preserve_value
333+
)
334+
299335
return minify(
300336
source,
301337
filename=filename,
@@ -315,7 +351,8 @@ def do_minify(source, filename, minification_args):
315351
remove_debug=minification_args.remove_debug,
316352
remove_explicit_return_none=minification_args.remove_explicit_return_none,
317353
remove_builtin_exception_brackets=minification_args.remove_exception_brackets,
318-
constant_folding=minification_args.constant_folding
354+
constant_folding=minification_args.constant_folding,
355+
remove_unused_platforms=remove_unused_platforms
319356
)
320357

321358

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class RemoveUnusedPlatformOptions(object):
2+
"""
3+
Options for the RemoveUnusedPlatform transform
4+
5+
This can be passed to the minify function as the remove_unused_platforms argument
6+
7+
:param platform_test_key: The key used to indicate a platform check statement
8+
:type platform_test_key: str
9+
:param platform_preserve_value: The value of the test to keep
10+
:type platform_preserve_value: str
11+
"""
12+
13+
platform_test_key = "_PLATFORM"
14+
platform_preserve_value = "linux"
15+
16+
def __init__(self, platform_test_key="", platform_preserve_value=""):
17+
self.platform_test_key = platform_test_key
18+
self.platform_preserve_value = platform_preserve_value
19+
20+
def __repr__(self):
21+
return 'RemoveUnusedPlatformOptions(platform_test_key=%s, platform_preserve_value=%s)' % (self.platform_test_key, self.platform_preserve_value)
22+
23+
def __nonzero__(self):
24+
return any((self.platform_test_key, self.platform_preserve_value))
25+
26+
def __bool__(self):
27+
return self.__nonzero__()

0 commit comments

Comments
 (0)