Build-time class-inheritance flattener — generalize HuggingFace transformers' modular code-gen to any Python project.
Project description
pycodelift
Build-time class-inheritance flattener. Write thin diff-only child classes against a base file; get back a single self-contained module with the inheritance inlined.
Generalizes HuggingFace transformers'
modular
codegen into a framework-agnostic library. Status: alpha.
When this is worth using
When all three apply:
- Many sibling files share a base (10+).
- They are read and forked, not just called.
- Edits to the base must not silently ripple into already-released siblings.
For five subclasses in a normal app, plain Python inheritance is the right answer.
Install
pip install pycodelift # or: uv add pycodelift
Quickstart
mypkg/
├── base/modeling_base.py # parent
└── child/modular_child.py # diff
mypkg/child/modular_child.py:
from ..base.modeling_base import BaseModel
class ChildModel(BaseModel):
def __init__(self, config):
super().__init__(config)
self.y = 2
__all__ = ["ChildModel"]
Convert:
pycodelift convert mypkg/child/modular_child.py --package mypkg
Or:
from pycodelift import Flattener
files = Flattener(package_name="mypkg").convert("mypkg/child/modular_child.py")
print(files["modeling"])
The output modeling_child.py has BaseModel's body inlined and no
inheritance edge.
How it works
Eight CST passes: parse → walk → resolve parent classes →
inline-flatten one level → case-preserving rename → pull in
transitive helpers → split outputs by class-suffix → render. Each pass
with code examples in docs/how-it-works.md.
Policies
Flattener(...) keyword args (all optional):
| Argument | Purpose | Default |
|---|---|---|
rename |
irregular casing overrides | snake↔Pascal derivation |
file_types |
suffix → output stem (Config → configuration_<x>.py) |
everything → modeling_<x>.py |
pre_body_vars |
top-level vars that come first | ("logger",) |
skip_imports |
imports to drop | () |
post_class_hooks |
e.g. TrailingCallHook("post_init") for trailing-call rules |
() |
header_template |
banner with {relative_path} / {short_name} slots |
default banner |
excluded_external_files |
per-package files to skip when walking imports | None |
prepend_namespace_parent |
transformers' optimum.habana-style prefix |
False |
flatten_levels=2 and non-empty special_bases raise
NotImplementedError in v0.1.
transformers compatibility
from pycodelift.adapters.transformers import make_transformers_flattener
flattener = make_transformers_flattener()
files = flattener.convert("src/transformers/models/olmo2/modular_olmo2.py")
The adapter pins every transformers convention so output matches
upstream utils/modular_model_converter.py. CLI: --transformers.
Combine with --package optimum for transformers forks.
CLI
pycodelift convert <file>... # one or many
pycodelift convert-tree <root> # recursive
pycodelift describe # dump effective config as JSON
Flags: --package, --transformers, --write, --target-dir.
Caveats
- One-level flatten only.
Foo2(Foo)works;Foo's own parent is not inlined. - Not thread-safe (v0.1 mutates module-level vendor state). Use a process pool for parallelism.
del self.xis line-level — removes the assignment, not later references.
Examples
Three runnable mini-projects under examples/:
01_minimal, 02_split_outputs, 03_transformers_compat.
Lineage
Derived from huggingface/transformers's
utils/modular_model_converter.py
(Apache-2.0). The CST passes are theirs (battle-tested across 200+
models); pycodelift extracts the policy slots they hard-coded.
See NOTICE.
License
Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pycodelift-0.0.1.tar.gz.
File metadata
- Download URL: pycodelift-0.0.1.tar.gz
- Upload date:
- Size: 61.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
075936374a1fcd5018609ebeea03724120679bc71c234d0ff6997f34ae431d8a
|
|
| MD5 |
99ef524ad3d9dd6b803272f5781d4af2
|
|
| BLAKE2b-256 |
b6dcb8046b9861f774d9c84eb018e3b3dfb22dcc332daf1ddbb7f6d2a643d1af
|
File details
Details for the file pycodelift-0.0.1-py3-none-any.whl.
File metadata
- Download URL: pycodelift-0.0.1-py3-none-any.whl
- Upload date:
- Size: 53.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a9e763aff188de2e869bb9b537190a926ae183ea34ef91eae48eb3d3d7b7d23
|
|
| MD5 |
de0f37a252c4edbce8b6a0c78959d1ac
|
|
| BLAKE2b-256 |
9bf402ad27178bb806697648b5a174cc619a2658fcb0e18348963ec07b761182
|