Skip to content

[codex] restore remaining optimizations#9

Merged
alvinwan merged 2 commits intomainfrom
dev/alvin/restore-remaining-optimizations
Apr 4, 2026
Merged

[codex] restore remaining optimizations#9
alvinwan merged 2 commits intomainfrom
dev/alvin/restore-remaining-optimizations

Conversation

@alvinwan
Copy link
Copy Markdown
Owner

@alvinwan alvinwan commented Apr 4, 2026

What changed

This restores the remaining optimization passes in pymini with size-aware guardrails instead of all-or-nothing behavior.

  • reintroduced statement-local repeated-name aliasing with cleanup deletes
  • extended repeated-string hoisting to function, module, and class scopes with profitability checks
  • reintroduced preserve-mode class, method, and class-attribute renaming when the alias overhead is worth it
  • kept attribute rewriting limited to owners we can prove from the AST
  • refreshed the checked-in pyminify example output and benchmark numbers in the README

Why

The remaining deferred optimizations were worth restoring, but the naive versions regressed small public APIs and package-shaped inputs. The new heuristics keep the wins for larger code while skipping unprofitable rewrites on small fixtures.

Impact

  • tests/examples/pyminifier.py returns to 511 bytes (62.3% reduction)
  • tests/examples/pyminify.py is 981 bytes (50.7% reduction)
  • minified TexSoup still passes its upstream test suite
  • TexSoup raw source is 66.3% smaller and the package .tar.gz snapshot is 83.2% smaller

Validation

  • .venv/bin/python -m pytest
  • .venv/bin/python scripts/regenerate_examples.py --check
  • PYTHONPATH=/tmp/texsoup-restore2.L4TojF .venv/bin/python -m pytest /tmp/pymini-texsoup-repo/tests -o addopts=''

@alvinwan alvinwan marked this pull request as ready for review April 4, 2026 21:32
@alvinwan alvinwan merged commit ea1bb77 into main Apr 4, 2026
10 checks passed
@alvinwan alvinwan deleted the dev/alvin/restore-remaining-optimizations branch April 4, 2026 21:32
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f6d003c8a7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pymini/pymini.py
Comment on lines +1011 to +1012
insert_at = 1 if body and ast.get_docstring(ast.Module(body=body, type_ignores=[])) is not None else 0
return body[:insert_at] + assignments + body[insert_at:]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve future imports at file start when hoisting

The module/class string-hoisting insertion point only checks for a docstring, so generated assignments can be placed before from __future__ import .... In modules that use future imports and have a repeated hoisted string, the minified output becomes syntactically invalid (SyntaxError: from __future__ imports must occur at the beginning of the file). This is a runtime-breaking regression introduced by module-scope hoisting.

Useful? React with 👍 / 👎.

Comment thread pymini/pymini.py
rewritten.append(statement)
continue
rewritten_statement = RepeatedNameRewriter(mapping).visit(statement)
rewritten.append(self._alias_assignment(mapping))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid eager name evaluation in repeated-name aliasing

This pass prepends an alias assignment before the original statement, which eagerly loads every repeated name up front. That changes semantics for guarded/short-circuited expressions (for example, condition and missing_name), where a name may never be evaluated in the original code but now raises NameError during alias setup. The optimization should not force earlier evaluation of names used inside the statement.

Useful? React with 👍 / 👎.

Comment thread pymini/pymini.py
Comment on lines +701 to +702
elif base_name in self.class_member_mappings:
attribute_mapping = self.class_member_mappings[base_name]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict class-member rewrites after class-name rebinding

Attribute rewriting keys off bare identifier text in class_member_mappings, so any later Name.attr with the same identifier is rewritten even if that name has been rebound to a different object. A common case is rebinding a class symbol (Foo = type(...)) and then accessing Foo.some_method; this can be rewritten to the shortened attribute and fail with AttributeError on the new object.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant