Code generation¶
Emitter framework¶
didactic.codegen.Emitter ¶
Bases: Protocol
The protocol every custom emitter implements.
Attributes:
| Name | Type | Description |
|---|---|---|
file_extension |
str
|
A class-level attribute naming the canonical filename
extension for this emitter ( |
Notes
Implement either or both of emit_class
(Model class -> bytes) and emit_instance
(Model instance -> bytes). Calls to the missing direction raise
NotImplementedError.
didactic.codegen.IndentWriter ¶
A small buffer with managed indentation for emitter authors.
Mirrors panproto_protocols::emit::IndentWriter from the
panproto Rust crate. Use as the standard helper for emitting
nested format text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
indent_str
|
str
|
The string used for each indent level. Defaults to four spaces. |
' '
|
Examples:
>>> w = IndentWriter()
>>> w.line("class Foo:")
>>> with w.indent():
... w.line("x: int")
>>> w.text_str()
'class Foo:\\n x: int\\n'
didactic.codegen.emitter ¶
Register a class as the emitter for name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The target name (e.g. |
required |
Returns:
| Type | Description |
|---|---|
decorator
|
A class decorator that calls register_emitter with an instance of the decorated class. |
Examples:
JSON Schema¶
didactic.codegen.json_schema_of ¶
json_schema_of(cls: type[Model]) -> JsonSchemaDoc
Build a JSON Schema (Draft 2020-12) document for cls.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type[Model]
|
A Model subclass. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
A JSON Schema object with |
Examples:
Bulk export¶
didactic.codegen.write ¶
write(
models: Iterable[type[Model]],
targets: Mapping[str, str],
*,
filename: str = "{model_name}.{ext}",
) -> dict[str, Path]
Emit each model under each target, writing files to disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
models
|
Iterable[type[Model]]
|
The Model classes to emit. |
required |
targets
|
Mapping[str, str]
|
Mapping of |
required |
filename
|
str
|
A format string for filenames. Available placeholders:
|
'{model_name}.{ext}'
|
Returns:
| Type | Description |
|---|---|
dict
|
Map of |
Raises:
| Type | Description |
|---|---|
LookupError
|
If |
Instance-level emit¶
didactic.codegen.io.emit ¶
emit(protocol: str, instance: Model) -> bytes
Encode instance as bytes in the named protocol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
protocol
|
str
|
A panproto protocol name (e.g. |
required |
instance
|
Model
|
A Model instance. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The encoded bytes. |
Raises:
| Type | Description |
|---|---|
IoError
|
If the codec rejects the instance (mismatch with the Model's Theory, value out of range, etc.). |
didactic.codegen.io.parse ¶
Decode data from protocol back to a Model instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
protocol
|
str
|
A panproto protocol name. |
required |
data
|
bytes
|
The encoded bytes. |
required |
schema
|
type[M]
|
The expected Model class. The decoded payload is validated against this class. |
required |
Returns:
| Type | Description |
|---|---|
Model
|
A new |
Raises:
| Type | Description |
|---|---|
IoError
|
If the codec cannot decode |
didactic.codegen.io.list_protocols ¶
List the supported instance-protocol names.
Returns:
| Type | Description |
|---|---|
list of str
|
Every codec the running panproto build registers, sorted. |
didactic.codegen.io.check_round_trip ¶
check_round_trip(protocol: str, instance: Model) -> None
Assert that parse(emit(instance)) == instance for protocol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
protocol
|
str
|
A panproto protocol name. |
required |
instance
|
Model
|
A Model instance. The check round-trips it through the codec and asserts equality. |
required |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If the round trip does not produce an equal Model. |
IoError
|
If the codec rejects either direction. |
Source-level emit¶
didactic.codegen.source.emit_pretty ¶
emit_pretty(model: type[Model], *, target: str) -> bytes
Render model as fresh source in the named target language.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
type[Model]
|
A Model subclass. |
required |
target
|
str
|
A panproto grammar name (e.g. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
Source code that the target grammar accepts as syntactically valid. |
Raises:
| Type | Description |
|---|---|
PanprotoError
|
If the grammar rejects the schema (typically because the
grammar lacks a |
Notes
The output is syntactically valid; idiomatic formatting (rustfmt
spacing rules, gofmt conventions) is left to a post-processor.
Configure one in pyproject.toml under
[tool.didactic.emit.targets.{target}.post_process].
didactic.codegen.source.emit ¶
Re-emit a parse-recovered schema as source bytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
schema
|
object
|
A |
required |
protocol
|
str
|
The grammar name to emit under (typically the same as the parse step). |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The reconstructed source. |
Notes
Use this for edit pipelines (parse, transform, emit). For fresh emission from a Model class, use emit_pretty.
didactic.codegen.source.parse ¶
Parse source bytes into a panproto.Schema.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
bytes
|
The source bytes to parse. |
required |
protocol
|
str
|
The grammar name (e.g. |
required |
file_path
|
str
|
A filename for error messages. Does not need to exist. |
'<source>'
|
Returns:
| Type | Description |
|---|---|
Schema
|
The parsed schema with byte-position fragments. Pass to emit to re-emit, or to didactic.codegen.source.for_protocol for lens-style round-trip checks. |
didactic.codegen.source.available_targets ¶
List every grammar the running panproto build supports.
Returns:
| Type | Description |
|---|---|
list of str
|
Grammar names, sorted. |
didactic.codegen.source.detect_language ¶
Return the grammar name that handles path's extension, if any.
didactic.codegen.source.for_protocol ¶
Build a parse function bound to protocol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
protocol
|
str
|
The grammar name. |
required |
Returns:
| Type | Description |
|---|---|
Callable
|
A function that takes source bytes and returns a Schema. Use in lens compositions or as a partial-application helper. |