From d5cc78d32fda7e528951ec42715946981d87778b Mon Sep 17 00:00:00 2001 From: Daniel Flook Date: Sun, 1 Sep 2024 12:04:43 +0100 Subject: [PATCH 1/3] Enable renaming of type parameters --- src/python_minifier/rename/bind_names.py | 12 ++++++++++++ src/python_minifier/rename/binding.py | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/python_minifier/rename/bind_names.py b/src/python_minifier/rename/bind_names.py index 1a2f586a..148bf68e 100644 --- a/src/python_minifier/rename/bind_names.py +++ b/src/python_minifier/rename/bind_names.py @@ -161,6 +161,18 @@ def visit_MatchMapping(self, node): self.generic_visit(node) + def visit_TypeVar(self, node): + if node.name not in node.namespace.nonlocal_names: + self.get_binding(node.name, node.namespace).add_reference(node) + + def visit_TypeVarTuple(self, node): + if node.name not in node.namespace.nonlocal_names: + self.get_binding(node.name, node.namespace).add_reference(node) + + def visit_ParamSpec(self, node): + if node.name not in node.namespace.nonlocal_names: + self.get_binding(node.name, node.namespace).add_reference(node) + def bind_names(module): """ Bind names to their local namespace diff --git a/src/python_minifier/rename/binding.py b/src/python_minifier/rename/binding.py index d18f1703..9f58058b 100644 --- a/src/python_minifier/rename/binding.py +++ b/src/python_minifier/rename/binding.py @@ -130,6 +130,12 @@ def additional_byte_cost(self): pass elif is_ast_node(node, 'MatchMapping'): pass + elif is_ast_node(node, 'TypeVar'): + pass + elif is_ast_node(node, 'TypeVarTuple'): + pass + elif is_ast_node(node, 'ParamSpec'): + pass else: raise AssertionError('Unknown reference node') @@ -177,6 +183,12 @@ def old_mention_count(self): pass elif is_ast_node(node, 'MatchMapping'): pass + elif is_ast_node(node, 'TypeVar'): + pass + elif is_ast_node(node, 'TypeVarTuple'): + pass + elif is_ast_node(node, 'ParamSpec'): + pass else: raise AssertionError('Unknown reference node') @@ -220,6 +232,12 @@ def new_mention_count(self): mentions += 1 elif is_ast_node(node, 'MatchMapping'): mentions += 1 + elif is_ast_node(node, 'TypeVar'): + mentions += 1 + elif is_ast_node(node, 'TypeVarTuple'): + mentions += 1 + elif is_ast_node(node, 'ParamSpec'): + mentions += 1 else: raise AssertionError('Unknown reference node') @@ -386,6 +404,12 @@ def rename(self, new_name): node.name = new_name elif is_ast_node(node, 'MatchMapping'): node.rest = new_name + elif is_ast_node(node, 'TypeVar'): + node.name = new_name + elif is_ast_node(node, 'TypeVarTuple'): + node.name = new_name + elif is_ast_node(node, 'ParamSpec'): + node.name = new_name if func_namespace_binding is not None: func_namespace_binding.body = list( From e1286443bfa65d58786db749d985b78ecc4c88d2 Mon Sep 17 00:00:00 2001 From: Daniel Flook Date: Thu, 5 Sep 2024 16:46:02 +0100 Subject: [PATCH 2/3] Disable renaming of type parameters It's not practical to rename type parameters safely until we can properly model annotation namespaces. --- src/python_minifier/__init__.py | 8 ++++++++ src/python_minifier/rename/bind_names.py | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/src/python_minifier/__init__.py b/src/python_minifier/__init__.py index 9863b791..15122694 100644 --- a/src/python_minifier/__init__.py +++ b/src/python_minifier/__init__.py @@ -166,6 +166,14 @@ def minify( rename_globals = False rename_locals = False + if preserve_locals is None: + preserve_locals = [] + if preserve_globals is None: + preserve_globals = [] + + preserve_locals.extend(module.preserved) + preserve_globals.extend(module.preserved) + allow_rename_locals(module, rename_locals, preserve_locals) allow_rename_globals(module, rename_globals, preserve_globals) diff --git a/src/python_minifier/rename/bind_names.py b/src/python_minifier/rename/bind_names.py index 148bf68e..57597674 100644 --- a/src/python_minifier/rename/bind_names.py +++ b/src/python_minifier/rename/bind_names.py @@ -15,6 +15,7 @@ class NameBinder(NodeVisitor): def __call__(self, module): assert isinstance(module, ast.Module) module.tainted = False + module.preserved = set() return self.visit(module) def get_binding(self, name, namespace): @@ -165,14 +166,20 @@ def visit_TypeVar(self, node): if node.name not in node.namespace.nonlocal_names: self.get_binding(node.name, node.namespace).add_reference(node) + get_global_namespace(node.namespace).preserved.add(node.name) + def visit_TypeVarTuple(self, node): if node.name not in node.namespace.nonlocal_names: self.get_binding(node.name, node.namespace).add_reference(node) + get_global_namespace(node.namespace).preserved.add(node.name) + def visit_ParamSpec(self, node): if node.name not in node.namespace.nonlocal_names: self.get_binding(node.name, node.namespace).add_reference(node) + get_global_namespace(node.namespace).preserved.add(node.name) + def bind_names(module): """ Bind names to their local namespace From 03ec99ab1eee1b12d65ff000fe113cf566f30631 Mon Sep 17 00:00:00 2001 From: Daniel Flook Date: Thu, 5 Sep 2024 17:27:06 +0100 Subject: [PATCH 3/3] Fix errors in manifests preserve_locals/globals should be a list. Cast it to a list if it looks like it has mistaken been passed as a string. --- src/python_minifier/__init__.py | 4 ++++ xtest/manifests/python3.10_test_manifest.yaml | 12 ++++++---- xtest/manifests/python3.11_test_manifest.yaml | 24 ++++++++++++------- xtest/manifests/python3.12_test_manifest.yaml | 12 ++++++---- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/python_minifier/__init__.py b/src/python_minifier/__init__.py index 15122694..a7ab2b67 100644 --- a/src/python_minifier/__init__.py +++ b/src/python_minifier/__init__.py @@ -168,8 +168,12 @@ def minify( if preserve_locals is None: preserve_locals = [] + elif isinstance(preserve_locals, str): + preserve_locals = [preserve_locals] if preserve_globals is None: preserve_globals = [] + elif isinstance(preserve_globals, str): + preserve_globals = [preserve_globals] preserve_locals.extend(module.preserved) preserve_globals.extend(module.preserved) diff --git a/xtest/manifests/python3.10_test_manifest.yaml b/xtest/manifests/python3.10_test_manifest.yaml index e958d54d..5603f85c 100644 --- a/xtest/manifests/python3.10_test_manifest.yaml +++ b/xtest/manifests/python3.10_test_manifest.yaml @@ -865,17 +865,21 @@ rename_globals: true /usr/local/lib/python3.10/test/test_contextlib_async.py: - options: - preserve_locals: baz + preserve_locals: + - baz - options: rename_globals: true - preserve_locals: baz + preserve_locals: + - baz - options: remove_literal_statements: true - preserve_locals: baz + preserve_locals: + - baz - options: remove_literal_statements: true rename_globals: true - preserve_locals: baz + preserve_locals: + - baz /usr/local/lib/python3.10/test/test_copy.py: - options: {} - options: diff --git a/xtest/manifests/python3.11_test_manifest.yaml b/xtest/manifests/python3.11_test_manifest.yaml index 74384540..b8158cc2 100644 --- a/xtest/manifests/python3.11_test_manifest.yaml +++ b/xtest/manifests/python3.11_test_manifest.yaml @@ -188,17 +188,21 @@ /usr/local/lib/python3.11/test/test_asyncio/test_futures.py: [] /usr/local/lib/python3.11/test/test_asyncio/test_futures2.py: - options: - preserve_locals: future + preserve_locals: + - future - options: rename_globals: true - preserve_locals: future + preserve_locals: + - future - options: remove_literal_statements: true - preserve_locals: future + preserve_locals: + - future - options: remove_literal_statements: true rename_globals: true - preserve_locals: future + preserve_locals: + - future /usr/local/lib/python3.11/test/test_asyncio/test_locks.py: - options: {} - options: @@ -2904,17 +2908,21 @@ rename_globals: true /usr/local/lib/python3.11/test/test_opcache.py: - options: - preserve_locals: Class + preserve_locals: + - Class - options: rename_globals: true - preserve_locals: Class + preserve_locals: + - Class - options: remove_literal_statements: true - preserve_locals: Class + preserve_locals: + - Class - options: remove_literal_statements: true rename_globals: true - preserve_locals: Class + preserve_locals: + - Class /usr/local/lib/python3.11/test/test_opcodes.py: - options: {} - options: diff --git a/xtest/manifests/python3.12_test_manifest.yaml b/xtest/manifests/python3.12_test_manifest.yaml index 4c143483..c1a6a4a4 100644 --- a/xtest/manifests/python3.12_test_manifest.yaml +++ b/xtest/manifests/python3.12_test_manifest.yaml @@ -4740,20 +4740,24 @@ status: passing /usr/local/lib/python3.12/test/test_opcache.py: - options: - preserve_locals: Class + preserve_locals: + - Class remove_literal_statements: true rename_globals: true status: passing - options: - preserve_locals: Class + preserve_locals: + - Class rename_globals: true status: passing - options: - preserve_locals: Class + preserve_locals: + - Class remove_literal_statements: true status: passing - options: - preserve_locals: Class + preserve_locals: + - Class status: passing /usr/local/lib/python3.12/test/test_opcodes.py: - options: