Skip to main content

provides an intuitive API for building and manipulating Abstract Syntax Trees (ASTs) to generate Python code.

Project description

astlab

Latest Version Python Supported Versions MyPy Strict Test Coverage Downloads GitHub stars

astlab is a Python library that provides an intuitive API for building and manipulating Abstract Syntax Trees (ASTs) to generate Python code. With astlab, you can easily construct Python modules, classes, functions, type aliases, and generics using a fluent API — then render them into valid, executable Python code.

Features

  • Easy AST construction: Build Python code using a fluent, structured API.
  • Code generation: Generate fully valid, formatted Python source without templates.
  • Supports nested scopes & auto imports: Create classes, methods, and nested modules with automatic import resolution.
  • Type system support: Define and use type variables, generic classes, and type aliases compatible with Python 3.9–3.14 syntax.
  • Highly customizable: Extend the builder model for any Python AST use case.

Installation

pip install astlab

Usage

Simple Example

import ast
import astlab

with astlab.module("foo") as foo:
    with foo.class_def("Bar").dataclass() as bar:
        bar.field_def("spam", int)

print(foo.render())
print(ast.dump(foo.build(), indent=4))

Output

import builtins
import dataclasses

@dataclasses.dataclass()
class Bar:
    spam: builtins.int

Function Definition & Call Example

import astlab

with astlab.module("foo") as foo:
    with foo.class_def("Bar") as bar:
        with bar.method_def("do_stuff").arg("spam", int).returns(str) as stuff:
            stuff.assign_stmt("result", stuff.call(str).arg(stuff.attr("spam")))
            stuff.return_stmt(stuff.attr("result"))

print(foo.render())

Output

import builtins

class Bar:

    def do_stuff(self, spam: builtins.int) -> builtins.str:
        result = builtins.str(spam)
        return result

Type Reference Example

import astlab

with astlab.package("main") as main:
    with main.module("foo") as foo:
        with foo.class_def("Bar") as bar:
            pass

    with main.module("spam") as spam:
        with spam.class_def("Eggs").inherits(bar) as eggs:
            with eggs.method_def("do_stuff").returns(bar.ref().optional()) as stuff:
                pass

print(spam.render())

Output

import main.foo
import typing

class Eggs(main.foo.Bar):

    def do_stuff(self) -> typing.Optional[main.foo.Bar]:
        pass

Generics and Type Variables

astlab supports defining type variables and generic classes. Both the legacy (typing.TypeVar) and modern (class Node[T: int]) syntaxes are supported depending on Python version.

Example

import astlab

with astlab.module("generic") as mod:
    with mod.class_def("Node") as node, node.type_var("T").lower(int) as T:
        node.field_def("value", T)
        node.field_def("parent", node.ref().type_params(type_var).optional(), mod.none())

print(mod.render())

Output (python < 3.12)

import builtins
import typing

T = typing.TypeVar('T', bound=builtins.int)

class Node(typing.Generic[T]):
    value: T
    parent: typing.Optional['Node[T]'] = None

Output (python 3.12, 3.13)

import builtins
import typing

class Node[T: builtins.int]:
    value: T
    parent: typing.Optional['Node[T]'] = None

Output (python ≥ 3.14)

import builtins
import typing

class Node[T: builtins.int]:
    value: T
    parent: typing.Optional[Node[T]] = None

Type Aliases

astlab allows declarative creation of type aliases, including recursive and generic aliases. It automatically emits valid syntax for both typing.TypeAlias (pre-3.12) and type X = Y (3.12+).

Example

import astlab
from astlab.types import predef

with astlab.module("alias") as mod:
    mod.type_alias("MyInt").assign(int)

    with mod.type_alias("Json") as json_alias:
        json_alias.assign(
            json_alias.union_type(
                None,
                bool,
                int,
                float,
                str,
                mod.list_type(json_alias),
                mod.dict_type(str, json_alias),
            )
        )

    with (
        mod.type_alias("Nested") as nested_alias,
        nested_alias.type_var("T") as T,
    ):
        nested_alias.assign(
            nested_alias.union_type(
                T
                nested_alias.sequence_type(nested_alias.type_params(T)),
            )
        )

Output (python < 3.12)

import builtins
import typing

MyInt: typing.TypeAlias = builtins.int
Json: typing.TypeAlias = typing.Union[
    None,
    builtins.bool,
    builtins.int,
    builtins.float,
    builtins.str,
    builtins.list['Json'],
    builtins.dict[builtins.str, 'Json'],
]
T = typing.TypeVar("T")
Nested: typing.TypeAlias = typing.Union[T, typing.Sequence['Nested[T]']]

Output (python 3.12, 3.13)

import builtins
import typing

type MyInt = builtins.int
type Json = typing.Union[
    None,
    builtins.bool,
    builtins.int,
    builtins.float,
    builtins.str,
    builtins.list['Json'],
    builtins.dict[builtins.str, 'Json'],
]
type Nested[T] = typing.Union[T, typing.Sequence['Nested[T]']]

Output (python ≥ 3.14)

import builtins
import typing

type MyInt = builtins.int
type Json = typing.Union[
    None,
    builtins.bool,
    builtins.int,
    builtins.float,
    builtins.str,
    builtins.list[Json],
    builtins.dict[builtins.str, Json],
]
type Nested[T] = typing.Union[T, typing.Sequence[Nested[T]]]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

astlab-0.5.0.tar.gz (25.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

astlab-0.5.0-py3-none-any.whl (29.3 kB view details)

Uploaded Python 3

File details

Details for the file astlab-0.5.0.tar.gz.

File metadata

  • Download URL: astlab-0.5.0.tar.gz
  • Upload date:
  • Size: 25.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for astlab-0.5.0.tar.gz
Algorithm Hash digest
SHA256 04d23d5a392fc622caf7ecf15fb5530ed54a78f005de15a5cba85680a660d06c
MD5 c1e812aae2a78106a3c81c2b0aa5e536
BLAKE2b-256 08176d870dece105d81679a2404fa90b58c1bc66515ccb18933c11581d798ab9

See more details on using hashes here.

Provenance

The following attestation bundles were made for astlab-0.5.0.tar.gz:

Publisher: publish.yaml on zerlok/astlab

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file astlab-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: astlab-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 29.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for astlab-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9c7d763639fb62bf268ddeedbea543de8bd67b5ecf40b14f216894babc88703a
MD5 faccba35440e9068d37c1ee40b37a19c
BLAKE2b-256 51357899934031f8a9b76094230202262853c315ce8db24d94f400ce218292b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for astlab-0.5.0-py3-none-any.whl:

Publisher: publish.yaml on zerlok/astlab

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page