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 (python >= 3.10)

import main.foo

class Eggs(main.foo.Bar):

    def do_stuff(self) -> main.foo.Bar | None:
        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(T).optional(), mod.none())

print(mod.render())

Output (python 3.10, 3.11)

import builtins
import typing

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

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

Output (python 3.12, 3.13)

import builtins
import typing

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

Output (python ≥ 3.14)

import builtins
import typing

class Node[T: builtins.int]:
    value: T
    parent: Node[T] | None = 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.10, 3.11)

import builtins
import typing

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

Output (python 3.12, 3.13)

import builtins
import typing

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

Output (python ≥ 3.14)

import builtins
import typing

type MyInt = builtins.int
type Json =  None | builtins.bool | builtins.int | builtins.float | builtins.str | builtins.list[Json] | builtins.dict[builtins.str, Json]
type Nested[T] = 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.6.0.tar.gz (28.4 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.6.0-py3-none-any.whl (32.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for astlab-0.6.0.tar.gz
Algorithm Hash digest
SHA256 2061efcbe4af5ee23771db4d3ace10fb3aecab592e49181a7d9dbb05f497b22a
MD5 80bc0b67f40ae748f091b39e1c1bccb4
BLAKE2b-256 2a817956dcacf8d9378d223f6bfab06c4bace01f46596f5638586392e719ba84

See more details on using hashes here.

Provenance

The following attestation bundles were made for astlab-0.6.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.6.0-py3-none-any.whl.

File metadata

  • Download URL: astlab-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 32.7 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.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d9795fe5b10734f29a7020fc69034bf2a6627f28ac5d6ad0beb13b67da1953bd
MD5 de4dc6acc4a9455ab8ec68841ff7c829
BLAKE2b-256 3bdeec11944541ae4306af5c0eaa9455b3184d9080cec748d1e7d4a43fd947df

See more details on using hashes here.

Provenance

The following attestation bundles were made for astlab-0.6.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