Skip to content

Generator Plugin

To register a generator plugin, register the pydjinni.generator entry-point in the plugins pyproject.toml:

[project.entry-points.'pydjinni.generator']
foo = 'myplugin.foo:FooTarget'

Pydjinni will now automatically load the plugin, once it is installed.

Target

Bases: ABC

Abstract class for defining generation targets. A target combines multiple generators to one entity. E.g. to allow Java interop, both a Java and JNI generator are required.

generators abstractmethod property

A list of generators related to the target. Typically, targets will have two generators:

  1. For the target (host) language
  2. For the glue-code required in C++ to interact with the host language

internal property

Whether a generator is an internal component that does not produce code. This is used to flag the yaml generator as not being a language target.

key abstractmethod property

The name of the target. Will be used by the API/CLI for selecting the target.

supported_deriving property

Record derivings that are supported by the target language. For documentation purposes only.

Generator

Bases: ABC

Abstract class for defining generators. Each generator can utilize one or more Marshal classes, specified as generic arguments.

config_model abstractmethod property

The Pydantic model that defines the configuration options for the generator.

The model will automatically be registered in the system and is then available in the documentation and as part of the JSON-Schema for the configuration file.

external_type_model property

The Pydantic model of the external type specification for the generator. The model should contain all information that is required to reference and use an external type in the generated code.

The model will automatically be registered in the system and is then available in the documentation and as part of the JSON-Schema for external types.

external_types property

A dictionary of all builtin types that are supported by the generator. If the list is incomplete, an error is thrown when the user tries to use an unsupported type in a project that uses the generator.

A complete list of all builtin types can be found in pydjinni/generator/external_types.py

filters property

Jinja2 filter functions that are required in the generators Jinja templates

header_path property

The path where generated header files should be written.

The default implementation expects the generators config model to contain a field out that is either a Path or of type OutPaths.

Override this if the generators config doesn't match with those expectations.

key abstractmethod property

The name of the generator. Will be used as configuration key and for importing/exporting external types.

Typically, a target will have one generator with the same name (key) as the target. If additional glue code in C++ is provided, this will usually require a separate generator with a distinct name.

marshal_models property

A mapping of AST types to the marshalling model required by the generator. For each type in the AST, the generator searches for a matching marshalling model in this dictionary. If no marshalling model is found, an error will be thrown suggesting that the given AST type is not supported by the generator.

The generator will search for a matching marshalling model by traversing the type hierarchy of the AST type until a matching marshalling model is found.

A marshalling model must be a Pydantic model with two fields: - decl for the type of field declaration and - config for the generator configuration

All marshalling must happen in methods decorated as @cached_property, where the declaration and the configuration is used to derive information needed by the generator. Type marshalling properties must at least contain a property for each field in the given external type model. Every property that should be exported as part of the external type YAML definition must be decorated with @computed_field.

source_path property

The path where generated source files should be written.

The default implementation expects the generators config model to contain a field out that is either a Path or of type OutPaths.

Override this if the generators config doesn't match with those expectations.

support_lib_commons property

Whether the code generated by this generator depends on the common support lib code provided by pydjinni.

tests property

Jinja2 test functions that are required in the generators Jinja templates

writes_header property

Whether the generator will generate header files. This information is required for documentation purposes and for providing a valid JSON-Schema for the processed files report.

writes_source property

Whether the generator will generate source files. This information is required for documentation purposes and for providing a valid JSON-Schema for the processed files report.

GenerationException

Bases: ApplicationException

Generation error

clean()

purge all content from source and header output directories

generate(ast, copy_support_lib_sources=True)

This method is initiated by the system to start code generation.

Iterates over all given type definitions and dynamically searches for a matching generator function. A valid generator function must have the following signature, where <type> is a lowercase representation of the full type name, separated by _ instead of . if the given type is a subclass:

def generate_<type>(self, type_def: BaseType):
    ...

If no direct match for the types class name can be found, the inheritance hierarchy is traversed until a match was found.

Examples:

  • def generate_interface(self, type_def: Interface) will match for the Interface type.
  • def generate_base_type(self, type_def: BaseType) will match for all types deriving from BaseType if no better match can be found.

This method may be overridden if the default dynamic detection behaviour doesn't fit the requirements.

generate_support_lib()

Copies support lib files if they exist. Fails silently if no files can be found in the expected directories.

marshal(type_decls, field_decls)

Attaches marshalling models to the provided type and field definitions.

Searches the provided marshalling model mappings for a matching marshalling model for each given type or field. If no direct match can be found, the inheritance hierarchy is traversed until a matching model is found.

Once a matching marshalling model was found, it is initialized and attached to the given type/field definition.

Note

During attachment of the marshalling models, no actual marshalling is happening. Only during rendering of the Jinja templates the marshalling model properties are evaluated.

The method may be overridden with custom marshalling logic if the default behaviour doesn't fit the requirements. But the outcome must always be a Pydantic model being attached to each given type and field declaration passed to the method!

write_header(template, filename=None, **kwargs)

Method that must be used for any header file that is written by the generator.

Providing a filename is optional if a type definition is provided in the type_def parameter. In this case the filename can be derived from the marshalling model, given that a header field is provided.

write_source(template, filename=None, **kwargs)

Method that must be used for any source file that is written by the generator.

Providing a filename is optional if a type definition is provided in the type_def parameter. In this case the filename can be derived from the marshalling model, given that a source field is provided.