nunavut

Code generator built on top of pydsdl.

Nunavut uses pydsdl to generate text files using templates. While these text files are often source code this module could also be used to generate documentation or data interchange formats like JSON or XML.

The input to the nunavut library is a list of templates and a list of pydsdl.CompositeType objects. Typical use of this library is simply invoking the nunavut.generate_all method.

class nunavut.AbstractGenerator(namespace: Namespace, resource_types: int, generate_namespace_types: YesNoDefault = YesNoDefault.DEFAULT, index_file: Iterable[Path] | None = None, **kwargs: Any)[source]

Bases: object

Abstract base class for classes that generate source file output from a given pydsdl parser result.

Parameters:
  • namespace (nunavut.Namespace) – The top-level namespace to generates types at and from.

  • resource_types (int) – A bitmask of resources to generate. This can be a combination of ResourceType values.

  • generate_namespace_types (YesNoDefault) – Set to YES to force generation files for namespaces and NO to suppress. DEFAULT will generate namespace files based on the language preference.

  • index_file (Iterable[Path]) – A list of paths to files that should be generated, relative to the output directory, which are given access to the full namespace context rather than per-type context.

  • kwargs (Any) – Additional arguments to pass into generators.

abstractmethod generate_all(is_dryrun: bool = False, allow_overwrite: bool = True) Iterable[Path][source]

Generates all output for a given nunavut.Namespace and using the templates found by this object.

Parameters:
  • is_dryrun (bool) – If True then no output files will actually be written but all other operations will be performed.

  • allow_overwrite (bool) – If True then the generator will attempt to overwrite any existing files it encounters. If False then the generator will raise an error if the output file exists and the generation is not a dry-run.

Returns:

Iterator over the files generated.

Raises:

PermissionError if allow_overwrite is False and the file exists.

property generate_namespace_types: bool

If true then the generator is set to emit files for nunavut.Namespace in addition to the pydsdl datatypes. If false then only files for pydsdl datatypes will be generated.

classmethod generate_namespace_types_from_trinary(target_language: Language, generate_namespace_types: YesNoDefault) bool[source]

Given the target language and a trinary value, returns a binary result for “should namespace types be generated” as a parameter.

abstractmethod get_templates() Iterable[Path][source]

Enumerate all templates found in the templates path. :return: A list of paths to all templates found by this Generator object.

property index_files: List[Path]

A list of paths to files that should be generated, relative to the output directory, which are given access to the full namespace context rather than per-type context.

property namespace: Namespace

The root nunavut.Namespace for this generator.

property resource_types: int

The bitmask of resources to generate. This can be a combination of ResourceType values.

class nunavut.CodeGenerator(namespace: Namespace, resource_types: int = 3, generate_namespace_types: YesNoDefault = YesNoDefault.DEFAULT, templates_dir: Path | List[Path] | None = None, template_loader: Type[DSDLTemplateLoader] | None = None, followlinks: bool = False, trim_blocks: bool = False, lstrip_blocks: bool = False, additional_filters: Dict[str, Callable] | None = None, additional_tests: Dict[str, Callable] | None = None, additional_globals: Dict[str, Any] | None = None, post_processors: List[PostProcessor] | None = None, builtin_template_path: str = 'templates', search_policy: ResourceSearchPolicy = ResourceSearchPolicy.FIND_ALL, embed_auditing_info: bool = False, **kwargs: Any)[source]

Bases: AbstractGenerator

Abstract base class for all Generators that build source code using Jinja templates.

Parameters:
  • resource_types (int) – A bitfield of nunavut._utilities.ResourceType for filtering the types of resources this generator will emit.

  • namespace (nunavut.Namespace) – The top-level namespace to generates code at and from.

  • generate_namespace_types (YesNoDefault) – Set to YES to emit files for namespaces. NO will suppress namespace file generation and DEFAULT will use the language’s preference.

  • templates_dir (Optional[Union[Path,List[Path]]]) – Directories containing jinja templates. These will be available along with any built-in templates provided by the target language. The templates at these paths will take precedence masking any built-in templates where the names are the same. See jinja2.ChoiceLoader for rules on the lookup hierarchy.

  • template_loader (Optional[Type[DSDLTemplateLoader]]) – If None uses an internal default implementation of DSDLTemplateLoader otherwise instantiates the given class with the arguments specified by the DSDLTemplateLoader constructor.

  • followlinks (bool) – If True then symbolic links will be followed when searching for templates.

  • trim_blocks (bool) – If this is set to True the first newline after a block is removed (block, not variable tag!).

  • lstrip_blocks (bool) – If this is set to True leading spaces and tabs are stripped from the start of a line to a block. Defaults to False.

  • additional_filters (Dict[str, Callable]) – Optional jinja filters to add to the global environment using the key as the filter name and the callable as the filter.

  • additional_tests (Dict[str, Callable]) – Optional jinja tests to add to the global environment using the key as the test name and the callable as the test.

  • additional_globals (Dict[str, Any]) – Optional objects to add to the template environment globals collection.

  • post_processors (Optional[List[nunavut.postprocessors.PostProcessor]]) – A list of nunavut.postprocessors.PostProcessor

  • builtin_template_path (str) – If provided overrides the folder name under which built-in templates are loaded from within a target language’s package (i.e. ignored if no target language is specified). For example, if the target language is c and this parameter was set to foo then built-in templates would be loaded from nunavut.lang.c.foo.

  • search_policy (ResourceSearchPolicy) – The policy to use when searching for templates.

  • embed_auditing_info (bool) – If True then the generator will embed auditing information in the generated code.

Raises:

RuntimeError – If any additional filter or test attempts to replace a built-in or otherwise already defined filter or test.

property dsdl_loader: DSDLTemplateLoader

The template loader used by this generator.

property environment: CodeGenEnvironment

The generator environment.

abstractmethod generate_all(is_dryrun: bool = False, allow_overwrite: bool = True) Iterable[Path][source]

Generates all output for a given nunavut.Namespace and using the templates found by this object.

Parameters:
  • is_dryrun (bool) – If True then no output files will actually be written but all other operations will be performed.

  • allow_overwrite (bool) – If True then the generator will attempt to overwrite any existing files it encounters. If False then the generator will raise an error if the output file exists and the generation is not a dry-run.

Returns:

Iterator over the files generated.

Raises:

PermissionError if allow_overwrite is False and the file exists.

get_templates() Iterable[Path][source]

Enumerate all templates found in the templates path. TEMPLATE_SUFFIX as the suffix for the filename.

Returns:

A list of paths to all templates found by this Generator object.

property language_context: LanguageContext

The language context used by this generator.

class nunavut.DefaultValue(value: Any)[source]

Bases: object

Represents a default value in the language configuration. Use this to differentiate between explicit values and default values when merging configuration. For example, given the following configuration:

collection = {
    'a': DefaultValue(1),
    'b': 2
}

overrides = [
    {
        'a': 3,
        'b': DefaultValue(4)
    },
    {
        'a': DefaultValue(5),
        'b': 6
    }
]

Then the merged configuration should be:

merged = {
    'a': 3,
    'b': 6
}

Other properties of DefaultValue:

assert DefaultValue(1) == 1
assert DefaultValue(1) != 2
assert DefaultValue(1) == DefaultValue(1)
assert DefaultValue(1) != DefaultValue(2)
assert eval(repr(DefaultValue(1))) == DefaultValue(1)
assert hash(DefaultValue(1)) == hash(1)
assert bool(DefaultValue(1))
assert not bool(DefaultValue(None))
repred = eval(repr(DefaultValue(8)))
assert repred.value == 8
classmethod assign_to_if_not_default(target: MutableMapping[str, Any], key: str, value: Any) Any[source]

Assigns a value to a key in a dictionary unless the key already has a value and the value is not a DefaultValue. The one exception to this is if the value is a DefaultValue and the value for the key is already a DefaultValue. In this case the new DefaultValue value will be assigned to the key.

Parameters:
  • target – The dictionary to assign to.

  • key – The key to assign to.

  • value – The value to test and assign.

Returns:

The value assigned to the key. This is the value of the value parameter if it was assigned or the value of the key in the target dictionary if it was not assigned.

property value: Any

The default value.

class nunavut.DSDLCodeGenerator(namespace: Namespace, resource_types: int = 3, **kwargs: Any)[source]

Bases: CodeGenerator

CodeGenerator implementation that generates code for a given set of DSDL types.

static filter_alignment_prefix(offset: BitLengthSet) str[source]

Provides a string prefix based on a given pydsdl.BitLengthSet.

# Given
B = pydsdl.BitLengthSet(32)

# and
template = '{{ B | alignment_prefix }}'

# outputs
rendered = 'aligned'
# Given
B = pydsdl.BitLengthSet(32)
B += 1

# and
template = '{{ B | alignment_prefix }}'

# outputs
rendered = 'unaligned'
Parameters:

offset (pydsdl.BitLengthSet) – A bit length set to test for alignment.

Returns:

‘aligned’ or ‘unaligned’ based on the state of the offset argument.

static filter_bit_length_set(values: Iterable[int] | int | None) BitLengthSet[source]

Convert an integer or a list of integers into a pydsdl.BitLengthSet.

static filter_bits2bytes_ceil(n_bits: int) int[source]

Implements int(ceil(x/8)) | x >= 0.

static filter_remove_blank_lines(text: str) str[source]

Remove blank lines from the supplied string. Lines that contain only whitespace characters are also considered blank.

# Given
text = '''123

456




789'''

# and
template = '{{ text | remove_blank_lines }}'

# then the black lines will be removed leaving...
rendered = '''123
456
789'''
static filter_text_table(data: Dict, start_each_line: str, column_sep: str = ' : ', line_end: str = '\n') str[source]

Create a text table from a dictionary of data.

# Given
table = {
    "banana": "yellow",
    "apple": "red",
    "grape": "purple"
}

# and
template = '''
{{ table | text_table("//  ", " | ", "\n") }}'''

# then
rendered = '''
//  banana | yellow
//  apple  | red
//  grape  | purple'''
filter_type_to_include_path(value: Any, resolve: bool = False) str[source]

Emits an include path to the output target for a given type.

Example:

# include "{{ T.my_type | type_to_include_path }}"

Result Example:

# include “foo/bar/my_type.h”

Parameters:
  • value (Any) – The type to emit an include for.

  • resolve (bool) – If True the path returned will be absolute else the path will be relative to the folder of the root namespace.

Returns:

A string path to output file for the type.

filter_type_to_template(value: Any) str[source]

Template for type resolution as a filter. Available as type_to_template in all template environments.

Example:

{%- for attribute in T.attributes %}
    {%* include attribute.data_type | type_to_template %}
    {%- if not loop.last %},{% endif %}
{%- endfor %}
Parameters:

value – The input value to change into a template include path.

Returns:

A path to a template named for the type with TEMPLATE_SUFFIX

static filter_typename(value: Any) str[source]

Filters a given token as its type name. Available as typename in all template environments.

This example supposes that T.some_value == "some string"

Example:

{{ T.some_value | typename }}

Result Example:

str
Parameters:

value – The input value to filter into a type name.

Returns:

The __name__ of the python type.

static filter_yamlfy(value: Any) str[source]

Filter to, optionally, emit a dump of the dsdl input as a yaml document. Available as yamlfy in all template environments.

Example:

/*
{{ T | yamlfy }}
*/

Result Example (truncated for brevity):

/*
!!python/object:pydsdl.StructureType
_attributes:
- !!python/object:pydsdl.Field
_serializable: !!python/object:pydsdl.UnsignedIntegerType
    _bit_length: 16
    _cast_mode: &id001 !!python/object/apply:pydsdl.CastMode
    - 0
_name: value
*/
Parameters:

value – The input value to parse as yaml.

Returns:

If a yaml parser is available, a pretty dump of the given value as yaml. If a yaml parser is not available then an empty string is returned.

generate_all(is_dryrun: bool = False, allow_overwrite: bool = True) Iterable[Path][source]

Generates all output for a given nunavut.Namespace and using the templates found by this object.

Parameters:
  • is_dryrun (bool) – If True then no output files will actually be written but all other operations will be performed.

  • allow_overwrite (bool) – If True then the generator will attempt to overwrite any existing files it encounters. If False then the generator will raise an error if the output file exists and the generation is not a dry-run.

Returns:

Iterator over the files generated.

Raises:

PermissionError if allow_overwrite is False and the file exists.

get_templates() Iterable[Path][source]

Enumerate all templates found in the templates path. TEMPLATE_SUFFIX as the suffix for the filename.

Returns:

A list of paths to all templates found by this Generator object.

static is_None(value: Any) bool[source]

Tests if a value is None

static is_deprecated(instance: Any) bool[source]

Tests if a type is marked as deprecated

static is_saturated(t: PrimitiveType) bool[source]

Tests if a type is a saturated type or not.

static is_service_request(instance: Any) bool[source]

Tests if a type is request type of a service type.

static is_service_response(instance: Any) bool[source]

Tests if a type is response type of a service type.

nunavut.generate_all(target_language: str, target_files: Iterable[Path | str], root_namespace_directories_or_names: Iterable[Path | str], outdir: Path, language_options: Mapping[str, Any] | None = None, include_experimental_languages: bool = False, resource_types: int = 3, embed_auditing_info: bool = False, dry_run: bool = False, jobs: int = 0, no_overwrite: bool = False, allow_unregulated_fixed_port_id: bool = False, omit_dependencies: bool = False, code_generator_type: Type[AbstractGenerator] | None = None, support_generator_type: Type[AbstractGenerator] | None = None, **kwargs: Any) GenerationResult[source]

Helper method that uses default settings and built-in templates to generate types for a given language. This method is the most direct way to generate code using Nunavut.

Generation takes place four steps with a function provided for each step:

┌───────────────────────────────────────────────────┐ 1. generate_all
│           Language context construction           │
│                                                   │
│  ┌─────────────────────────────────────────────┐  │ 2. generate_all_for_language
│  │ Parsing (pydsdl) and constructing Namespace │  │
│  │             trees from results              │  │
│  │                                             │  │
│  │  ┌───────────────────────────────────────┐  │  │ 3. generate_all_from_namespace
│  │  │        Generator construction         │  │  │
│  │  │                                       │  │  │
│  │  │  ┌─────────────────────────────────┐  │  │  │ 4. generate_all_from_namespace_with_generators
│  │  │  │        code generation          │  │  │  │
│  │  │  │                                 │  │  │  │
│  │  │  │                                 │  │  │  │
│  │  │  └─────────────────────────────────┘  │  │  │
│  │  └───────────────────────────────────────┘  │  │
│  └─────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────┘

At each stage the number of options are reduced as objects are constructed based on their values.

  • generate_all: Requires no Nunavut objects and can be driven from a command-line.

  • generate_all_for_language: This is the best entry point for programmatic use of Nunavut. Simply construct a

    LanguageContext object using a LanguageContextBuilder and pass it to this function.

  • generate_all_from_namespace: This function can be used if you have already constructed a Namespace object.

  • generate_all_from_namespace_with_generators: This function is used if you have already constructed the

    generators you want to use.

Parameters:
  • target_language (str) – The name of the language to generate source for. See the Template Language Guide for details on available language support.

  • target_files – A list of paths to dsdl files. This method will generate code for these files and their dependant types.

  • root_namespace_directories_or_names

    This can be a set of names of root namespaces or relative paths to root namespaces. All dsdl_files provided must be under one of these roots. For example, given:

    target_dsdl_files = [
                    Path("workspace/project/types/animals/felines/Tabby.1.0.dsdl"),
                    Path("workspace/project/types/animals/canines/Boxer.1.0.dsdl"),
                    Path("workspace/project/types/plants/trees/DouglasFir.1.0.dsdl")
                ]
    

    then this argument must be one of:

    root_namespace_directories_or_names = ["animals", "plants"]
    
    # or
    
    root_namespace_directories_or_names = [
                    Path("workspace/project/types/animals"),
                    Path("workspace/project/types/plants")
                ]
    

  • outdir (Path) – The path to generate code at and under.

  • language_options (Optional[Mapping[str, Any]]) – Opaque arguments passed through to the language objects. The supported arguments and valid values are different depending on the language specified by the language_key parameter.

  • resource_types (int) – Bitmask of resources to generate. This can be a combination of ResourceType values. For example, to generate only serialization support code, set this to ResourceType.SERIALIZATION_SUPPORT.value. To generate all resources set this to ResourceType.ANY.value. To only generate resource files (i.e. to omit source code generation) set the ResourceType.ONLY.value bit and the resource type bytes you do want to generate.

  • embed_auditing_info – If True then additional information about the inputs and environment used to generate source will be embedded in the generated files at the cost of build reproducibility.

  • include_experimental_languages (bool) – If true then experimental languages will also be available.

  • dry_run (bool) – If True then no files will be generated/written but all logic will be exercised with commensurate logging and errors.

  • jobs (int) –

    The number of parallel jobs to use when generating code. If 1 then no parallelism is used. If 0 then the number of jobs is determined by the number of CPUs available.

    Note

    By default, any multiprocessing jobs used will not have a timeout set. To set a timeout for any jobs set the environment variable NUNAVUT_JOB_TIMEOUT_SECONDS to the desired timeout in fractional seconds. this is normally not useful as a correct timeout value is highly dependent on the system and the number of types being generated.

  • no_overwrite (bool) – If True then generated files will not be allowed to overwrite existing files under the outdir path causing errors.

  • allow_unregulated_fixed_port_id (bool) – If True then errors will become warning when using fixed port identifiers for unregulated datatypes.

  • omit_dependencies (bool) – If True then only the types explicitly provided in target_files will be generated. If False then all dependant types will also be generated.

  • code_generator_type – The type of code generator to use. If None then the default code generator is used.

  • support_generator_type – The type of support generator to use. If None then the default support generator is used.

  • kwargs – Additional arguments passed into the language context builder and generator constructors. See the documentation for basic_language_context_builder_from_args() and for specific generator types for details on supported arguments.

Returns GenerationResult:

A dataclass containing explicit inputs, discovered inputs, and determined outputs.

Raises:

pydsdl.FrontendError – Exceptions thrown from the pydsdl frontend. For example, parsing malformed DSDL will raise this exception.

nunavut.generate_all_for_language(language_context: LanguageContext, target_files: Iterable[Path | str], root_namespace_directories_or_names: Iterable[Path | str], outdir: Path, resource_types: int = 3, embed_auditing_info: bool = False, dry_run: bool = False, jobs: int = 0, no_overwrite: bool = False, allow_unregulated_fixed_port_id: bool = False, omit_dependencies: bool = False, code_generator_type: Type[AbstractGenerator] | None = None, support_generator_type: Type[AbstractGenerator] | None = None, **generator_args: Any) GenerationResult[source]

Generate code for a set of target_files using a configured language context. This is the second step in the generation process and is the best entry point for programmatic use of Nunavut. See the documentation for generate_all() for more details.

Parameters:
  • language_context – The language context to generate code for.

  • target_files – A list of paths to dsdl files. This method will generate code for these files and their dependant types.

  • root_namespace_directories_or_names – This can be a set of names of root namespaces or relative paths to root namespaces. All dsdl_files provided must be under one of these roots. See the documentation for generate_all() for more details.

  • outdir – The path to generate code at and under.

  • resource_types – A bitmask of resources to generate. This can be a combination of ResourceType values.

  • embed_auditing_info – If True then additional information about the inputs and environment used to generate source will be embedded in the generated files at the cost of build reproducibility.

  • dry_run – If True then no files will be generated/written but all logic will be exercised with commensurate logging and errors.

  • jobs (int) –

    The number of parallel jobs to use when generating code. If 1 then no parallelism is used. If 0 then the number of jobs is determined by the number of CPUs available.

    Note

    By default, any multiprocessing jobs used will not have a timeout set. To set a timeout for any jobs set the environment variable NUNAVUT_JOB_TIMEOUT_SECONDS to the desired timeout in fractional seconds. this is normally not useful as a correct timeout value is highly dependent on the system and the number of types being generated.

  • no_overwrite – If True then generated files will not be allowed to overwrite existing files under the outdir path causing errors.

  • allow_unregulated_fixed_port_id – If True then errors will become warning when using fixed port identifiers for unregulated datatypes.

  • omit_dependencies – If True then only the types explicitly provided in target_files will be generated. If False then all dependant types will also be generated.

  • code_generator_type – The type of code generator to use. If None then the default code generator is used.

  • support_generator_type – The type of support generator to use. If None then the default support generator is used.

  • generator_args – Additional arguments to pass into the generator constructors. See the documentation for specific generator types for details on supported arguments.

Returns:

A dataclass containing explicit inputs, discovered inputs, and determined outputs.

Raises:

pydsdl.FrontendError – Exceptions thrown from the pydsdl frontend. For example, parsing malformed DSDL will raise this exception.

nunavut.generate_all_from_namespace(index: Namespace, resource_types: int = 3, embed_auditing_info: bool = False, dry_run: bool = False, no_overwrite: bool = False, code_generator_type: Type[AbstractGenerator] | None = None, support_generator_type: Type[AbstractGenerator] | None = None, **generator_args: Any) GenerationResult[source]

Given a populated namespace, generate code for the types found within it. This is the third step in the generation process and is used when you have already constructed a Namespace object. See the documentation for generate_all() for more details.

Parameters:
  • index – The namespace tree to generate code for.

  • resource_types – A bitmask of resources to generate. This can be a combination of ResourceType values.

  • embed_auditing_info – If True then additional information about the inputs and environment used to generate source will be embedded in the generated files at the cost of build reproducibility.

  • dry_run – If True then no files will be generated/written but all logic will be exercised with commensurate logging and errors.

  • no_overwrite – If True then generated files will not be allowed to overwrite existing files under the outdir path causing errors.

  • code_generator_type – The type of code generator to use. If None then the default code generator is used.

  • support_generator_type – The type of support generator to use. If None then the default support generator is used.

  • generator_args – Additional arguments to pass into the generator constructors. See the documentation for specific generator types for details on supported arguments.

Returns:

A dataclass containing explicit inputs, discovered inputs, and determined outputs.

Raises:

pydsdl.FrontendError – Exceptions thrown from the pydsdl frontend. For example, parsing malformed DSDL will raise this exception.

nunavut.generate_all_from_namespace_with_generators(index: Namespace, code_generator: AbstractGenerator, support_generator: AbstractGenerator, dry_run: bool = False, no_overwrite: bool = False) GenerationResult[source]

Given a populated namespace, generate code for the types found within it using the provided generators. This is the fourth and final step in the generation process and is used when you have already constructed the generators you want to use. See the documentation for generate_all() for more details.

Parameters:
  • index – The namespace tree to generate code for.

  • code_generator – The code generator to use.

  • support_generator – The support generator to use.

  • dry_run – If True then no files will be generated/written but all logic will be exercised with commensurate logging and errors.

  • no_overwrite – If True then generated files will not be allowed to overwrite existing files under the outdir path causing errors.

Returns:

A dataclass containing explicit inputs, discovered inputs, and determined outputs.

Raises:

pydsdl.FrontendError – Exceptions thrown from the pydsdl frontend. For example, parsing malformed DSDL will raise this exception.

nunavut.basic_language_context_builder_from_args(target_language: str, **kwargs: Any) LanguageContextBuilder[source]

Uses interpreted arguments to create a new LanguageContextBuilder object with support for the most common arguments. This method will always support arguments used in the CLI. For more advanced use cases, create a LanguageContextBuilder object directly or add additional arguments to the builder after creation.

Note

This is the same method used by generate_all() to create a LanguageContextBuilder object.

# target_language is the only required argument
builder = basic_language_context_builder_from_args(target_language="c")

assert builder.create().get_target_language().name == "c"
Parameters:
  • target_language (str) – The name of the language to generate source for.

  • kwargs

    A dictionary of arguments to pass to the LanguageContextBuilder. The following arguments are supported:

    • configuration: A list of additional configuration files to load.

    • option: Key value arguments to override individual language option values.

    • include_experimental_languages: If true then experimental languages will also be available.

    • language_options: Opaque arguments passed through to the language objects. The supported arguments and

      valid values are different depending on the language specified by the language_key parameter.

    • output_extension: The file extension to use for generated files.

    • namespace_output_stem: The stem to use for generated namespace files.

    • additional_config_files: A list of Path s to additional configuration files to load.

Returns:

A new LanguageContextBuilder object based on the command line arguments.

class nunavut.Language(language_module_name: str, config: LanguageConfig, **kwargs: Any)[source]

Bases: object

Facilities for generating source code for a specific language. Concrete Language classes must be implemented by the language support package below lang and should be instantiated using nunavut.lang.LanguageClassLoader.

Parameters:
  • module_name (str) – The name of the nunavut.lang module that contains the concrete language type and its resources.

  • config (LanguageConfig) – All configuration as defined by the properties.json schema.

  • kwargs

    Opaque arguments passed through to the target

    nunavut.lang.Language object. See all “WKLA” constants on this class for well-known keyword arguments.

classmethod default_filter_id_for_target(instance: Any) str[source]

The default transformation of any object into a string.

Parameters:

instance (any) – Any object or data that either has a name property or can be converted to a string.

Returns:

Either str(instance.name) if the instance has a name property or just str(instance)

property enable_stropping: bool

Whether or not to strop identifiers for this language.

property extension: str

The extension to use for files generated in this language.

filter_id(instance: Any, id_type: str = 'any') str[source]

Produces a valid identifier in the language for a given object. The encoding may not be reversible.

Parameters:
  • instance (any) – Any object or data that either has a name property or can be converted to a string.

  • id_type (str) – A type of identifier. This is different for each language. For example, for C this value can be ‘typedef’, ‘macro’, ‘function’, or ‘enum’. Use ‘any’ to apply stropping rules for all identifier types to the instance.

Returns:

A token that is a valid identifier in the language, is not a reserved keyword, and is transformed in a deterministic manner based on the provided instance.

filter_short_reference_name(t: CompositeType, stropping: YesNoDefault = YesNoDefault.DEFAULT, id_type: str = 'any') str[source]

Provides a string that is a shorted version of the full reference name omitting any namespace parts of the type.

Parameters:
  • t (pydsdl.CompositeType) – The DSDL type to get the reference name for.

  • stropping (YesNoDefault) – If DEFAULT then the stropping value configured for the target language is used else this overrides that value.

  • id_type (str) – A type of identifier. This is different for each language. For example, for C this value can be ‘typedef’, ‘macro’, ‘function’, or ‘enum’. Use ‘any’ to apply stropping rules for all identifier types to the instance.

get_config_value(key: str, default_value: str | None = None) str[source]

Get an optional language property from the language configuration.

Parameters:
  • key (str) – The config value to retrieve.

  • default_value (Optional[str]) – The value to return if the key was not in the configuration. If provided this method will not raise.

Returns:

Either the value from the config or the default_value if provided.

Return type:

str

Raises:

KeyError if the section or the key in the section does not exist and a default_value was not provided.

get_config_value_as_bool(key: str, default_value: bool = False) bool[source]

Get an optional language property from the language configuration returning a boolean.

Parameters:
  • key (str) – The config value to retrieve.

  • default_value (bool) – The value to use if no value existed.

Returns:

The config value as either True or False.

Return type:

bool

get_config_value_as_dict(key: str, default_value: Dict | None = None) Dict[str, Any][source]

Get a language property parsing it as a map with string keys.

Parameters:
  • key (str) – The config value to retrieve.

  • default_value (Optional[Mapping[str, Any]]) – The value to return if the key was not in the configuration. If provided this method will not raise a KeyError nor a TypeError.

Returns:

Either the value from the config or the default_value if provided.

Return type:

Mapping[str, Any]

Raises:

KeyError if the key does not exist and a default_value was not provided.

Raises:

TypeError if the value exists but is not a dict and a default_value was not provided.

get_config_value_as_list(key: str, default_value: List | None = None) List[Any][source]

Get a language property parsing it as a map with string keys.

Parameters:
  • key (str) – The config value to retrieve.

  • default_value (Optional[List[Any]]) – The value to return if the key was not in the configuration. If provided this method will not raise a KeyError nor a TypeError.

Returns:

Either the value from the config or the default_value if provided.

Return type:

List[Any]

Raises:

KeyError if the key does not exist and a default_value was not provided.

Raises:

TypeError if the value exists but is not a dict and a default_value was not provided.

get_dependency_builder(for_type: Any) DependencyBuilder[source]

Get a dependency builder for the given type.

get_globals() Mapping[str, Any][source]

Get all values for this language that should be available in a global context.

Returns:

A mapping of global names to global values.

abstractmethod get_includes(dep_types: Dependencies) List[str][source]

Get a list of include paths that are specific to this language and the options set for it. :param Dependencies dep_types: A description of the dependencies includes are needed for. :return: A list of include file paths. The list may be empty if no includes were needed.

get_option(option_key: str, default_value: Mapping[str, Any] | str | bool | None = None) Mapping[str, Any] | str | bool | None[source]

Get a language option for this language.

# Values can come from defaults...
assert lang_cpp.get_option('target_endianness') == 'little'

# ... or can come from a sane default.
assert lang_cpp.get_option('foobar', 'sane_default') == 'sane_default'
Returns:

Either the value provided to the nunavut.lang.Language instance, the value from properties.json or the default_value.

get_options() Mapping[str, Any][source]

Get all language options for this Language.

Returns:

A mapping of option names to option values.

get_support_files(resource_type: int = 3) Generator[Path, None, None][source]

Iterates over supporting files embedded within the Nunavut distribution.

Parameters:

resource_type – The type of support resources to enumerate.

get_support_module() Tuple[str, Tuple[int, int, int], ModuleType | None][source]

Returns the module object for the language support files. :return: A tuple of module name, x.y.z module version, and the module object itself.

get_templates_package_name() str[source]

The name of the nunavut python package containing filters, types, and configuration for this language.

property has_standard_namespace_files: bool

Whether or not the language defines special namespace files as part of its core standard (e.g. python’s __init__).

property name: str

The name of the language used by the nunavut.lang module.

property named_types: Mapping[str, str]

Get a map of named types to the type name to emit for this language.

property named_values: Mapping[str, str]

Get a map of named values to the token to emit for this language.

property namespace_output_stem: str | None

The name of a namespace file for this language.

property stable_support: bool

Whether support for this language is designated ‘stable’, and not experimental.

property support_namespace: List[str]

The hierarchical namespace used by the support software. The property is a dot separated string when specified in configuration. This property returns that value split into namespace components with the first identifier being the first index in the array, etc.

class nunavut.LanguageConfig[source]

Bases: object

Configuration storage encapsulating parsers and other configuration format details. For any configuration type used the concept of “sections” must be maintained which requires that the top-level configuration be structured as key/value pairs with the keys using the form “nunavut.lang.[language name]”. For example, json configuration must have a top-level structure like this:

example_json = '''
    {
      "nunavut.lang.a": {
        "key_one": "value_one",
        "key_two": "value_two"
      },
      "nunavut.lang.b": {
        "key_one": "value_one",
        "key_two": "value_two"
      },
      "nunavut.lang.c": {
        "key_one": "value_one",
        "key_two": "value_two"
      }
    }
'''

Note

The “language name” part of the section identifier must not start with a number and can contain only alphanumeric characters. That is, the section identifier must match this pattern:

nunavut.lang.[a-zA-Z]{1}w*

The values of the section data can be anything:

example_json = '''
    {
        "nunavut.lang.d": {
            "key_one": [
            "is",
            "a",
            {
                "list": {
                "where": "index2",
                "is": "a_dictionary"
                }
            }
            ]
        }
    }
'''
SECTION_NAME_PATTERN = re.compile('^nunavut\\.lang\\.([a-zA-Z]{1}\\w*)$')

Required pattern for section name identifiers.

add_section(section_name: str) None[source]

Add a section to the configuration.

Sections are top-level containers that contain key/value pairs of configuration of a single language type.

Parameters:

section_name – The name of the language section. This must adhere to the SECTION_NAME_PATTERN pattern.

get_config_value(section_name: str, key: str, default_value: str | None = None) str[source]

Get an optional language property from the language configuration.

:param section_name : The name of the section to get the value from. :param str key : The config value to retrieve. :param default_value: The value to return if the key was not in the configuration. If provided this method will not raise. :type default_value : typing.Optional[str] :return: Either the value from the config or the default_value if provided. :rtype: str :raises: KeyError if the section or the key in the section does not exist and a default_value was not provided.

get_config_value_as_bool(section_name: str, key: str, default_value: bool = False) bool[source]

Get an optional language property from the language configuration returning a boolean. The rules for boolean conversion are as follows:

# "Any string" = True
config.set('nunavut.lang.cpp', 'v', 'Any string')
assert config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# "true" = True
config.set('nunavut.lang.cpp', 'v', 'true')
assert config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# "TrUe" = True
config.set('nunavut.lang.cpp', 'v', 'TrUe')
assert config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# "1" = True
config.set('nunavut.lang.cpp', 'v', '1')
assert config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# "false" = False
config.set('nunavut.lang.cpp', 'v', 'false')
assert not config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# "FaLse" = False
config.set('nunavut.lang.cpp', 'v', 'FaLse')
assert not config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# "0" = False
config.set('nunavut.lang.cpp', 'v', '0')
assert not config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# "" = False
config.set('nunavut.lang.cpp', 'v', '')
assert not config.get_config_value_as_bool('nunavut.lang.cpp', 'v')

# False if not defined
assert not config.get_config_value_as_bool('nunavut.lang.cpp', 'not_a_key')

# True if not defined but default_value is True
assert not config.get_config_value_as_bool('nunavut.lang.cpp', 'not_a_key')

:param section_name : The name of the section to get the value from. :param str key : The config value to retrieve. :param bool default_value : The value to use if no value existed. :return : The config value as either True or False. :rtype : bool

get_config_value_as_dict(section_name: str, key: str, default_value: Dict | None = None) Dict[str, Any][source]

Get a language property parsing it as a map with string keys.

Example:

:param str section_name : The name of the section to get the key from. :param str key : The config value to retrieve. :param default_value : The value to return if the key was not in the configuration. If provided this method will not raise a KeyError nor a TypeError. :type default_value : typing.Optional[typing.Mapping[str, typing.Any]] :return : Either the value from the config or the default_value if provided. :rtype : typing.Mapping[str, typing.Any] :raises : KeyError if the key does not exist and a default_value was not provided. :raises : TypeError if the value exists but is not a dict and a default_value was not provided.

get_config_value_as_list(section_name: str, key: str, default_value: List | None = None) List[Any][source]

Get a language property parsing it as a map with string keys.

Example:

:param str section_name : The name of the section to get the key from. :param str key : The config value to retrieve. :param default_value : The value to return if the key was not in the configuration. If provided this method will not raise a KeyError nor a TypeError. :type default_value : typing.Optional[typing.List[typing.Any]] :return : Either the value from the config or the default_value if provided. :rtype : typing.List[typing.Any] :raises : KeyError if the key does not exist and a default_value was not provided. :raises : TypeError if the value exists but is not a dict and a default_value was not provided.

sections() Dict[str, Dict[str, Any]][source]

Get all sections of the configuration.

set(section: str, option: str, value: Any) None[source]

Set a configuration value.

Parameters:
  • section – The section to set the value in.

  • option – The option to set.

  • value – The value to set.

update(configuration: Any) None[source]

Add configuration data to this configuration from a string.

Unlike add_section, this method will update section data with existing keys.

For example, the first update is to an empty configuration so it will act as a simple insert operation:

…but updating this data is now possible where sections can be added and updated:

update_from_json_file(f: TextIO) None[source]

Update the configuration from a json file. Calls update() with the parsed json data and will raise the same exceptions.

update_from_json_string(string: str) None[source]

Update the configuration from a json string. Calls update() with the parsed json data and will raise the same exceptions.

update_from_yaml_file(f: TextIO) None[source]

Update the configuration from a yaml file. Calls update() with the parsed yaml data and will raise the same exceptions.

update_section(section_name: str, configuration: Any) None[source]

Update a section of the configuration.

class nunavut.LanguageContext(language_configuration: LanguageConfig, target_language: Language, supported_language_builder: Callable[[], Dict[str, Language]])[source]

Bases: object

Context object containing the current target language and all supported nunavut.lang.Language objects.

Parameters:
  • language_configuration – The configuration for all languages as defined by the properties.json schema.

  • target_language – The target language.

  • supported_language_builder – factory closure that will create nunavut.lang.Language objects for all supported languages when LanguageContext.get_target_languages() is first called.

property config: LanguageConfig

Returns the nunavut.lang.LanguageConfig object that contains the configuration for all supported languages. This is the same object that is used to instantiate the nunavut.lang.Language

filter_id_for_target(instance: Any, id_type: str = 'any') str[source]

A filter that will transform a given string or pydsdl identifier into a valid identifier in the target language.

Parameters:
  • instance (any) – Any object or data that either has a name property or can be converted to a string.

  • id_type (str) – A type of identifier. This is different for each language. Use ‘any’ to apply stropping rules for all identifier types to the instance.

Returns:

A token that is a valid identifier in the target language, is not a reserved keyword, and is transformed in a deterministic manner based on the provided instance.

get_language(key_or_module_name: str) Language[source]

Get a nunavut.lang.Language object for a given language identifier.

Parameters:

key_or_module_name (str) – Either one of the Nunavut mnemonics for a supported language or the __name__ of one of the nunavut.lang.[language] python modules.

Returns:

A nunavut.lang.Language object cached by this context.

Return type:

nunavut.lang.Language

get_supported_languages() Dict[str, Language][source]

Returns a collection of available language support objects.

get_target_language() Language[source]

Returns the target language for code generation.

class nunavut.LanguageContextBuilder(include_experimental_languages: bool = False)[source]

Bases: object

Used to instantiate new LanguageContext objects.

The simplest invocation will always work by using the LanguageContextBuilder.DEFAULT_TARGET_LANGUAGE constant:

from nunavut.lang import LanguageContextBuilder

default_language_context = LanguageContextBuilder().create()

assert LanguageContextBuilder.DEFAULT_TARGET_LANGUAGE == default_language_context.get_target_language().name

Typically a target language is specified at minimum. Also see constants on nunavut.lang.Language for well-known options that the builder can override:

from nunavut.lang import LanguageContextBuilder

customized_language_context = (
    LanguageContextBuilder()
        .set_target_language("c")
        .set_target_language_configuration_override(Language.WKCV_DEFINITION_FILE_EXTENSION, ".h")
        .create()
)

assert customized_language_context.get_target_language().extension == ".h"
Parameters:

include_experimental_languages – If set then languages that are not fully supported will be allowed otherwise any experimental languages will be missing and errors will be raised as if the language specified was unknown.

DEFAULT_TARGET_LANGUAGE = 'c'

The target language used for new contexts if none is specified.

add_config_files(*additional_config_files: Path) LanguageContextBuilder[source]

A list of paths to additional json files to load as configuration. These will override any values found in the nunavut.lang.properties.json file and files appearing later in this list will override value found in earlier entries.

target_language_w_overrides = (
    LanguageContextBuilder()
        .set_target_language("c")
        .add_config_files(overrides_file)
        .create()
        .get_target_language()
)

target_language_no_overrides = (
    LanguageContextBuilder()
        .set_target_language("c")
        .create()
        .get_target_language()
)

assert target_language_w_overrides.extension == ".foo"
assert target_language_no_overrides.extension == ".h"

Overrides are applied as unions. For example, given this override data:

overrides_data = '''
    {
        "nunavut.lang.c" :
            {
                "extension": ".foo",
                "non-standard": "bar"
            }
    }
'''

…the standard “extension” property will be overridden and the “non-standard” property will be added.

target_language_w_overrides = (
    LanguageContextBuilder()
        .set_target_language("c")
        .add_config_files(second_overrides_file)
        .create()
        .get_target_language()
)

assert ".foo" == target_language_w_overrides.extension
assert "bar" == target_language_w_overrides.get_config_value("non-standard")
add_target_language_option_override(key: str, value: Any) LanguageContextBuilder[source]

Adds a key and value to override in the language options section of the configuration for a language target when a LanguageContext is crated. These overrides are always set under the language section of the target language.

builder = LanguageContextBuilder().set_target_language("c")
c_section_name = LanguageClassLoader.to_language_module_name("c")

default_c_language_options = builder.config.get_config_value_as_dict(
                                c_section_name,
                                Language.WKCV_LANGUAGE_OPTIONS)

assert default_c_language_options["std"] == "c11"

We can now try to override the default standard for a future “C” target language object:

builder.add_target_language_option_override("std", "c17")

…but that value will not be overridden until you create the target language:

default_c_language_options = builder.config.get_config_value_as_dict(
                                c_section_name,
                                Language.WKCV_LANGUAGE_OPTIONS)

assert default_c_language_options["std"] == "c11"

_ = builder.create()

overridden_c_language_options = builder.config.get_config_value_as_dict(
                                c_section_name,
                                Language.WKCV_LANGUAGE_OPTIONS)

assert default_c_language_options["std"] == "c17"

Note that the config is scoped by the builder but is then inherited by the language objects created by the builder in the same way as the configuration overrides.

property config: LanguageConfig

The configuration object that will be used to create the language context.

create() LanguageContext[source]

Applies all pending configuration overrides to the internal LanguageConfig object and instantiates a LanguageContext object.

get_supported_language_names() Iterable[str][source]

Get a list of target languages supported by Nunavut.

Returns:

An iterable of strings which are languages with special support within Nunavut templates.

set_additional_config_files(additional_config_files: List[Path]) LanguageContextBuilder[source]

Deprecated. Use add_config_files() instead.

set_target_language(target_language: str | None) LanguageContextBuilder[source]

Set the language name to target. This can be either the name of the language, as defined by Nunavut, or it can be the language package name.

assert LanguageContextBuilder().set_target_language("c").create().get_target_language().name == "c"

assert (
    LanguageContextBuilder()
        .set_target_language(LanguageClassLoader.to_language_module_name("c"))
        .create()
        .get_target_language().name == "c"
)

Also note that, if the language name is None, the default name will be assigned internally:

target_language = LanguageContextBuilder().set_target_language(None).create().get_target_language()

assert target_language.name == LanguageContextBuilder.DEFAULT_TARGET_LANGUAGE
set_target_language_configuration_override(key: str, value: Any) LanguageContextBuilder[source]

Stores a key and value to override in the configuration for a language target when a LanguageContext is crated. These overrides are always set under the language section of the target language.

builder = LanguageContextBuilder().set_target_language("c")

default_c_file_extension = builder.config.get_config_value(
                                LanguageClassLoader.to_language_module_name("c"),
                                Language.WKCV_DEFINITION_FILE_EXTENSION)

assert default_c_file_extension == ".h"

We can now try to override the file extension for a future “C” target language object:

builder.set_target_language_configuration_override(Language.WKCV_DEFINITION_FILE_EXTENSION, ".foo")

…but that value will not be overridden until you create the target language:

default_c_file_extension = builder.config.get_config_value(
                                LanguageClassLoader.to_language_module_name("c"),
                                Language.WKCV_DEFINITION_FILE_EXTENSION)

assert default_c_file_extension == ".h"

_ = builder.create()

overridden_c_file_extension = builder.config.get_config_value(
                                LanguageClassLoader.to_language_module_name("c"),
                                Language.WKCV_DEFINITION_FILE_EXTENSION)

assert overridden_c_file_extension == ".foo"

Note that the config is scoped by the builder but is then inherited by the language objects created by the builder:

one = (
    LanguageContextBuilder()
        .set_target_language("c")
        .set_target_language_configuration_override("foo", 1)
    )
two = (
    LanguageContextBuilder()
        .set_target_language("c")
        .set_target_language_configuration_override("foo", 2)
    )

# Here we see that the second override of "foo" does not affect the first because they
# are in different builders.

assert (
        one.create().get_target_language().get_config_value("foo")
        !=
        two.create().get_target_language().get_config_value("foo")
    )
set_target_language_extension(target_language_extension: str | None) LanguageContextBuilder[source]

Helper method for setting the target language file extension (since this is a common override).

Calling this method is the same as doing:

LanguageContextBuilder().set_target_language_configuration_override(
    Language.WKCV_DEFINITION_FILE_EXTENSION,
    ".h")
class nunavut.Namespace(full_namespace: str, namespace_dir: Path, language_context: LanguageContext, parent: Namespace | None = None)[source]

Bases: Any

K-ary tree (where K is the largest set of data types in a single dsdl namespace) where the nodes represent dsdl namespaces and the children are the datatypes and other nested namespaces (with datatypes always being leaf nodes). This structure extends pydsdl.Any and is a pydsdl.CompositeType via duck typing.

Parameters:
  • full_namespace (str) – The full, dot-separated name of the namepace.

  • namespace_dir (Path) – If full_namespace is “” then this is interpreted as the directory under which all namespaces and datatypes should be generated. Otherwise, it is the directory that contains the namespace’s datatypes.

  • language_context (LanguageContext) – The generated software language context the namespace is within.

  • parent (Namespace) – The parent namespace of this namespace or None if this is an index namespace.

classmethod Identity(output_path: Path, lctx: LanguageContext) Namespace[source]

Create a namespace identity object. This is a namespace with no root directory and no parent. It can be used as a Namespace index object.

Parameters:
  • output_path (Path) – The base path under which all namespaces and datatypes should be generated.

  • lctx (LanguageContext) – The language context to use when building the namespace.

Returns:

A namespace identity object.

Return type:

Namespace

add_data_type(dsdl_type: CompositeType, input_types: List[CompositeType], extension: str | None) Generatable[source]

Add a datatype to this namespace.

Parameters:
  • dsdl_type (pydsdl.CompositeType) – The datatype to add.

  • extension (str) – The file extension to use for the generated file. If None, the extension will be determined by the target language.

Returns:

A path to the file this type will be generated in.

classmethod add_types(index: Namespace, types: Tuple[CompositeType, List[CompositeType]] | List[Tuple[CompositeType, List[CompositeType]]], extension: str | None = None) None[source]

Add a set of types to a namespace tree building new nodes as needed.

Parameters:
  • tree (Namespace) – A namespace tree to add types to. This can be any namespace in the tree as Namespace.get_index_namespace() will be used to find the meta-namespace.

  • types (list) – A list of pydsdl types to add.

  • extension (str) – Override the file extension to use for the generated files. If None, the extension will be determined by the target language.

property attributes: List[CompositeType]

See pydsdl.CompositeType.attributes

property base_output_path: Path

The folder under which artifacts are generated.

property data_types: KeysView[CompositeType]

See pydsdl.CompositeType.data_types

find_output_path_for_type(compound_type: Namespace | CompositeType) Path[source]

Searches the entire namespace tree to find a mapping of the type to an output file path.

Parameters:

compound_type (pydsdl.CompositeType) – A Namespace or pydsdl.CompositeType to find the output pathfor.

Returns:

The path where a file will be generated for a given type.

Raises:

KeyError – If the type was not found in this namespace tree.

property full_name: str

See pydsdl.CompositeType.full_name

property full_namespace: str

See pydsdl.CompositeType.full_namespace

get_all_datatypes() Generator[Tuple[CompositeType, Generatable], None, None][source]

Generates tuples relating datatypes at and below this namespace to the path for each type’s generated output.

get_all_namespaces() Generator[Tuple[Namespace, Path], None, None][source]

Generates tuples relating nested namespaces at and below this namespace to the path for each namespace’s generated output.

get_all_types() Generator[Tuple[Any, Generatable | Path], None, None][source]

Generates tuples relating datatypes and nested namespaces at and below this namespace to the path for each type’s generated output.

get_index_namespace() Namespace[source]

The index namespace is a meta-namespace that is empty and has no data types. It contains the root output folder, a common language context, and all the namespaces in a tree of DSDL types. It is used to generate index files that reference all the generated files in the tree at once. Logically, it is the root of the tree and is always the parent of each root namespace. The taxonomy of namespaces is therefore

                          ┌────────────────┐
                          │  CompoundType  │
                          │   «duck type»  │
                          └────────────────┘
                           ▲             ▲
        ┌──────────────────┘             │
        │                                │
        │              ┌──────┐          │
        │              │ Path │          │
        │              │      │          │
        │              └──────┘          │
        │               ▲    ▲           │
        │               │    │           │
  ┌─────┴─────┐ ┌───────┴┐  ┌┴───────┐   │
  │ Namespace │ │ Folder │  │  File  │   │
  │           │ │        │  │        │   │
  └───────────┘ └────────┘  └────────┘   │
   ▲    ▲   ▲     ^    ^           ^     │
   │    │   │     :    :.......    :     │
   │    │   │     :           :    :     │
   │    │   └──── : ─────┐    :    :     │
   │    │         :      │    :    :     │
   │    └─────┐   :      │    :    :     │
   │          │   :      │    :    :     │
┌──┴──────┐ ┌─┴───┴──┐ ┌─┴────┴─┐ ┌┴─────┴────┐
│  index  │ │  root  │ │ nested │ │ DSDL Type │
│         │ │        │ │        │ │           │
└─────────┘ └────────┘ └────────┘ └───────────┘
Returns:

The index namespace.

# This is the index namespace identity.
index_ns = Namespace.Identity(base_path, lctx)
ns = Namespace("uavcan", root_namespace_dir, lctx, index_ns)

# This is a root namespace identity.
assert ns.get_index_namespace() == index_ns
get_language_context() LanguageContext[source]

The generated software language context the namespace is within.

get_nested_namespace(namespace_name: str, create_if_missing: bool = False) Namespace[source]

Get a nested namespace by name. Note, this is not recursive.

Parameters:
  • namespace_name (str) – The name of the nested namespace to get.

  • create_if_missing (bool) – If True, the namespace will be created if it does not exist.

Returns:

The nested namespace.

Raises:

KeyError – If the namespace was not found and create_if_missing is False.

get_nested_namespaces() Iterator[Namespace][source]

Get an iterator over all the nested namespaces within this namespace. This is a shallow iterator that only provides directly nested namespaces.

get_nested_types() ItemsView[CompositeType, Generatable][source]

Get a view of a tuple relating datatypes in this namespace to the path for the type’s generated output. This is a shallow view including only the types directly within this namespace.

get_root_namespace(root_namespace_name: str, create_if_missing: bool = False) Namespace[source]

Retrieves or creates a root namespace object for a given name.

Parameters:
  • root_namespace_name (Path) – The root namespace name to get.

  • create_if_missing (bool) – If True, the namespace will be created if it does not exist.

Returns:

The root namespace object.

Raises:

KeyError – If the namespace was not found and create_if_missing is False.

property is_index: bool

True if this namespace is an index namespace.

property is_nested: bool

True if this namespace is a nested namespace.

property is_root: bool

True if this namespace is a root namespace.

property namespace_components: List[str]

See pydsdl.CompositeType.namespace_components

property output_folder: Path

The folder where this namespace’s output file and datatypes are generated.

property output_path: Path

Path to the namespace’s output file.

property parent: Namespace | None

The parent namespace of this namespace or None if this is a root namespace.

classmethod read_files(index: Namespace, dsdl_files: Path | str | Iterable[Path | str], root_namespace_directories_or_names: Path | str | Iterable[Path | str] | None, jobs: int = 0, job_timeout_seconds: float = 0, lookup_directories: Path | str | Iterable[Path | str] | None = None, print_output_handler: Callable[[Path, int, str], None] | None = None, allow_unregulated_fixed_port_id: bool = False, omit_dependencies: bool = False) Namespace[source]
classmethod read_files(output_path: Path, lctx: LanguageContext, dsdl_files: Path | str | Iterable[Path | str] | None, root_namespace_directories_or_names: Path | str | Iterable[Path | str] | None, jobs: int = 0, job_timeout_seconds: float = 0, lookup_directories: Path | str | Iterable[Path | str] | None = None, print_output_handler: Callable[[Path, int, str], None] | None = None, allow_unregulated_fixed_port_id: bool = False, omit_dependencies: bool = False) Any
classmethod read_files(output_path: str, lctx: LanguageContext, dsdl_files: Path | str | Iterable[Path | str] | None, root_namespace_directories_or_names: Path | str | Iterable[Path | str] | None, jobs: int = 0, job_timeout_seconds: float = 0, lookup_directories: Path | str | Iterable[Path | str] | None = None, print_output_handler: Callable[[Path, int, str], None] | None = None, allow_unregulated_fixed_port_id: bool = False, omit_dependencies: bool = False) Any

For a given set of dsdl_files, read the files and build a namespace tree.

Parameters:
  • index (Namespace) – The index namespace to add the new namespaces and types to.

  • dsdl_files (Path | str | Iterable[Path | str]) – The dsdl files to read.

  • root_namespace_directories_or_names (Path | str | Iterable[Path | str]) – See pydsdl.read_files().

  • jobs (int) – The number of parallel jobs to allow when reading multiple files. 0 Indicates no limit and 1 diasallows all parallelism.

  • job_timeout_seconds (float) – Maximum time in fractional seconds any one read file job is allowed to take before timing out. 0 disables timeouts.

  • lookup_directories (Path | str | Iterable[Path | str]) – See pydsdl.read_files().

  • print_output_handler (Callable[[Path, int, str], None]) – A callback to handle print output.

  • allow_unregulated_fixed_port_id (bool) – Allow unregulated fixed port ids.

Returns:

A new namespace index that contains trees of datatypes.

classmethod read_namespace(index: Namespace, root_namespace_directory: Path | str, lookup_directories: Path | str | Iterable[Path | str] | None = None, print_output_handler: Callable[[Path, int, str], None] | None = None, allow_unregulated_fixed_port_id: bool = False, allow_root_namespace_name_collision: bool = True) Namespace[source]
classmethod read_namespace(output_path: str, lctx: LanguageContext, root_namespace_directory: Path | str, lookup_directories: Path | str | Iterable[Path | str] | None = None, print_output_handler: Callable[[Path, int, str], None] | None = None, allow_unregulated_fixed_port_id: bool = False, allow_root_namespace_name_collision: bool = True) Any
classmethod read_namespace(output_path: Path, lctx: LanguageContext, root_namespace_directory: Path | str, lookup_directories: Path | str | Iterable[Path | str] | None = None, print_output_handler: Callable[[Path, int, str], None] | None = None, allow_unregulated_fixed_port_id: bool = False, allow_root_namespace_name_collision: bool = True) Any

Read a namespace from a root namespace directory.

Parameters:
  • index (Namespace) – The index namespace to add the new namespaces and types to.

  • root_namespace_directory (Path | str) – The root namespace directory.

  • lookup_directories (Path | str | Iterable[Path | str]) – The directories to search for dsdl files.

  • print_output_handler (Callable[[Path, int, str], None]) – A callback to handle print output.

  • allow_unregulated_fixed_port_id (bool) – Allow unregulated fixed port ids.

  • allow_root_namespace_name_collision (bool) – Allow root namespace name collisions.

Returns:

A new namespace index that contains trees of datatypes.

property root_namespace: Namespace

The root namespace of this namespace. :raises RuntimeError: If this is an index namespace.

property short_name: str

See pydsdl.CompositeType.short_name

property source_file_path: Path

See pydsdl.CompositeType.source_file_path Note that, for Namespace objects, this path is always relative since a single namespace may contain sources from files rooted in different directory trees. For example, a namespace may a type “/path/to/animals/mammals/Dog.1.0.dsdl” and another type “/a/different/path/to/animals/mammals/Cat.1.0.dsdl”.

property source_file_path_to_root: Path

See pydsdl.CompositeType.source_file_path_to_root Note that, for Namespace objects, this path is always relative. See source_file_path for more.

classmethod strop_namespace(full_namespace: str, language_context: LanguageContext) Tuple[List[str], List[str]][source]

Strop a namespace string for a given language context.

Parameters:
  • full_namespace (str) – The dot-separated namespace string to strop.

  • language_context (LanguageContext) – The language context to use when stroping the namespace.

Returns:

A tuple containing the original namespace components and the stropped namespace components.

full_namespace = "uavcan.node"
namespace_components, namespace_components_stropped = Namespace.strop_namespace(full_namespace, lctx)

assert namespace_components == ["uavcan", "node"]
assert namespace_components_stropped == ["uavcan", "node"]
class nunavut.ResourceType(*values)[source]

Bases: Enum

Standard Nunavut classifications for Python package resources.

NONE = 0

No resources specified.

SERIALIZATION_SUPPORT = 1

Serialization support files.

TYPE_SUPPORT = 2

Type support files.

ONLY = 2147483648

Only the specified resources.

ANY = 3

Any resources.

class nunavut.ResourceSearchPolicy(*values)[source]

Bases: Enum

Generic policy type for controlling the behaviour of things that search for resources.

class nunavut.SupportGenerator(namespace: Namespace, resource_types: int, generate_namespace_types: YesNoDefault = YesNoDefault.DEFAULT, templates_dir: Path | List[Path] | None = None, **kwargs: Any)[source]

Bases: CodeGenerator

Generates output files by copying them from within the Nunavut package itself for non templates but uses jinja to generate headers from templates with the language environment provided but no T (DSDL type) global set. This generator always copies files from those returned by the file_iterator to locations under nunavut.Namespace.get_support_output_folder()

generate_all(is_dryrun: bool = False, allow_overwrite: bool = True) Iterable[Path][source]

Generates all output for a given nunavut.Namespace and using the templates found by this object.

Parameters:
  • is_dryrun (bool) – If True then no output files will actually be written but all other operations will be performed.

  • allow_overwrite (bool) – If True then the generator will attempt to overwrite any existing files it encounters. If False then the generator will raise an error if the output file exists and the generation is not a dry-run.

Returns:

Iterator over the files generated.

Raises:

PermissionError if allow_overwrite is False and the file exists.

get_templates() Iterable[Path][source]

Enumerate all templates found in the templates path. TEMPLATE_SUFFIX as the suffix for the filename.

Returns:

A list of paths to all templates found by this Generator object.

exception nunavut.UnsupportedLanguageError[source]

Bases: ValueError

Error type raised if an unsupported language type is used.

class nunavut.YesNoDefault(*values)[source]

Bases: Enum

Trinary type for decisions that allow a default behavior to be requested that can be different based on other contexts. For example:

def should_we_order_pizza(answer: YesNoDefault) -> bool:
    if answer == YesNoDefault.YES or (
       answer == YesNoDefault.DEFAULT and
       datetime.today().isoweekday() == 5):
        # if yes or if we are taking the default action which is to
        # order pizza on Friday, and today is Friday, then we order pizza
        return True
    else:
        return False
classmethod test_truth(ynd_value: YesNoDefault, default_value: bool) bool[source]

Helper method to test a YesNoDefault value and return a default boolean value.

'''
    let "is YES" be Y
    let "is DEFAULT" be D where:
        if Y then not D and if D then not Y
        and "is NO" is Y = D = 0
    let "is default_value true" be d

    Y | D | d | Y or (D and d)
    1   *   *    1
    0   1   0    0
    0   1   1    1
    0   0   *    0
'''

assert YesNoDefault.test_truth(YesNoDefault.YES, False)
assert not YesNoDefault.test_truth(YesNoDefault.DEFAULT, False)
assert YesNoDefault.test_truth(YesNoDefault.DEFAULT, True)
assert not YesNoDefault.test_truth(YesNoDefault.NO, True)