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.
Metadata
Release files for pycodelift 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pycodelift-0.0.1.tar.gz | 61.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pycodelift-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 114.6 kB
Release files / pycodelift-0.0.1.tar.gz
| Download URL | pycodelift-0.0.1.tar.gz |
|---|---|
| Size | 61.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
075936374a1fcd5018609ebeea03724120679bc71c234d0ff6997f34ae431d8a
|
|
BLAKE2b-256 checksum How to use checksums |
b6dcb8046b9861f774d9c84eb018e3b3dfb22dcc332daf1ddbb7f6d2a643d1af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Release files / pycodelift-0.0.1-py3-none-any.whl
| Download URL | pycodelift-0.0.1-py3-none-any.whl |
|---|---|
| Size | 53.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9a9e763aff188de2e869bb9b537190a926ae183ea34ef91eae48eb3d3d7b7d23
|
|
BLAKE2b-256 checksum How to use checksums |
9bf402ad27178bb806697648b5a174cc619a2658fcb0e18348963ec07b761182
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|