trolskgen
pip install trolskgen
Easily compose types/values/string-templates/AST-nodes, then convert to source.
| Codgen | .to_source() |
|---|---|
|
|
|
|
|
|
If you want formatting, run ruff format over the output. If you want comments, sorry, instead use a docstring, some Annotated[] wizardry, or fork this library to use LibCST.
Blog post with a motivating example.
API
| Building templates |
|---|
trolskgen.t(s: str, **kwargs: object) -> trolskgen.templates.Template |
trolskgen.e(s: str, **kwargs: object) -> trolskgen.ASTModule |
trolskgen.t creates source templates. If you use the format string :*, it will splat in place - see above: {bases:*}, {fields:*}, {args,kwargs:*}
Note on Python 3.14 template strings.
From Python 3.14 upwards, there are template strings, these make trolskgen significantly more succinct.
Where previously you'd do:
name = trolskgen.t("f")
func = trolskgen.t(
"""
def {name}():
...
""",
name=name,
)
trolskgen.to_source(func)
As of Python 3.14, you can do:
name = t"f"
func = t"""
def {name}():
...
"""
trolskgen.to_source(func)
There are some if sys.version_info >= (3, 14) flags around, but it should just work come release date.
e is for "eager" - this might be preferable to use, otherwise error messages can become pretty inscrutable.
| Converting to AST/source |
|---|
trolskgen.to_ast(o: object, *, config: Config) -> trolskgen.ASTModule |
trolskgen.to_source(o: object, *, config: Config, ruff_format: bool, ruff_line_length: int) -> str |
Lower level functions to convert o into an ast.AST/str representation.
The following are special cases for the value of o:
ast.Module | ast.exprnodes - these just get passed straight back out.trolskgen.templates.Templateorstring.templatelib.Template- these get parsed as Python code.
trolskgen will generate sensible ASTs, for the following types:
Noneintfloatstrboollisttupledictsetclassesfunctionsdt.datetimedt.dateenum.Enumdecimal.DecimaldataclassAnnotated,T | U, etc.pydantic.BaseModel
If you have ruff installed, you can call with ruff_format=True.
| Configuring/Overriding |
|---|
__trolskgen__ |
__trolskgen_cls__ |
trolskgen.Converter |
trolskgen.Config |
trolskgen.Config().prepend_converter(converter: Converter, *, before: Converter | None) -> Config |
trolskgen.GLOBAL_CONFIG |
If you own the class, you can just add a __trolskgen__ method:
For example:
class MyInterfaceClass:
def __trolskgen__(self, f: trolskgen.F) -> ast.Module:
return f(trolskgen.t("MyInterfaceClass({values:*})", values=[1, 2, 3]))
trolskgen.to_source(MyInterfaceClass()) == "MyInterfaceClass(1, 2, 3)"
You can also add a __trolskgen_cls__ @classmethod:
@dataclass
class MyJustName:
a: str
@classmethod
def __trolskgen_cls__(cls, f: trolskgen.F) -> ast.Module:
return f(trolskgen.t("Foo"))
trolskgen.to_source(MyJustName("bar")) == "Foo(a='bar')"
Note that we use f to recursively call trolskgen.to_ast(...) while preserving the current Config.
You can do simple overrides with a dict in Annotated, for example:
MySpecialInt = Annotated[int, {"__trolskgen__": "my_module.MySpecialInt"}]
If you don't own the class, you can build a trolskgen.Config with a custom Converter function.
For example, if you for some reason wanted to render all ints in the form x + 1, you could:
def custom_int_converter(o: object, f: trolskgen.F) -> ast.Module | None:
if not isinstance(o, int):
return None
return f(trolskgen.t(f"{o - 1} + 1"))
config = trolskgen.Config().prepend_converter(custom_int_converter)
trolskgen.to_source([6, 9], config=config) == "[5 + 1, 8 + 1]"
You can also set a global trolskgen.GLOBAL_CONFIG ContextVar.
with trolskgen.GLOBAL_CONFIG.set(config):
trolskgen.to_source([6, 9]) == "[5 + 1, 8 + 1]"
Metadata
Release files for trolskgen 0.0.26
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| trolskgen-0.0.26.tar.gz | 16.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| trolskgen-0.0.26-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.8 kB
Release files / trolskgen-0.0.26.tar.gz
| Download URL | trolskgen-0.0.26.tar.gz |
|---|---|
| Size | 16.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bc198a2d0ab114dfda6e0598b2571cc38ac9f93e7689552158622bcce1e6b43c
|
|
BLAKE2b-256 checksum How to use checksums |
f740946df6ba1fd6b7beab55e4cc8139b2aab28e0981912065546150b636a2ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / trolskgen-0.0.26-py3-none-any.whl
| Download URL | trolskgen-0.0.26-py3-none-any.whl |
|---|---|
| Size | 12.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4359b23d150d4bc76dbc1f96223a890f586ca4f6313b821390b8911aa67e2b8e
|
|
BLAKE2b-256 checksum How to use checksums |
bb9800c102c7ccab1f7196df3d7f16990ec1a333c79c47fb9ad113a6b1c5f22b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for trolskgen 0.0.26
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.