Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Latest commit

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Definitions

Load and validate YAML definitions against a schema. Classes are directly instantiated from names in your definition files.

Definition

Definitions can contain any valid YAML. The only reserved key in definitions is type which can hold the name of a subclass of the the type defined in the schema. If for a key just a single value is provided, it will be parsed as a type name if possible, and otherwise as a value.

key1: fookey2: SubClassNamekey3:
argument1: fooargument2: 42key4:
type: SubClassNameargument1: fooargument2: 42key5:
- value1
- value2
- value3

Schema

Schemas are defined in a nested way. For example, you can specify the schemas for required keys of a dict or for constructor arguments of a class. The following keys have a special meaning.

KeyDescription
typeName of Python type Name of the Python type or base class.
moduleWhere to import non-primitive types from.
defaultParsed when the key is not specified.
argumentsMapping or single nested schema describing constructor arguments.
elementsNested schema of elements that are passed as a list to the constructor.
mappingNested schema of values that are passed as a dict with string keys to the constructor.

Only one of arguments and elements and mapping can be specified at the same time. Also, those keys can only be parsed if a type is specified. Each schema is validated to ensure these constraints.

Example

Definition

cost: SquaredErrorconstraints:
- angle: 70
- angle: 120distribution:
type: Gaussianvariance: 2.5

Schema

type: dictmapping:
cost:
type: Costmodule: mypackage.costconstraints:
type: listelements:
type: Constraintmodule: mypackage.constraintarguments:
angle: {type: int}distribution:
type: Distributionmodule: mypackage.distributionarguments:
mean:
type: floatdefault: 0backup:
type: booldefault: false

Usage in Code

fromdefinitionsimportParserfrommypackage.costimportSquaredErrorfrommypackage.contraintimportConstraintfrommypackage.distributionimportGaussianparser=Parser('schema.yaml')
definition=parser('definition.yaml')
assertisinstance(definition.cost, SquaredError)
assertlen(definition.constraints) ==2assertall(isinstance(x, Constraint) forxindefinition.constraints)
assertdefinition.constraints[0].angle==70assertdefinition.constraints[1].angle==120assertisinstance(definition.distribution, Gaussian)
assertdefinition.distribution.mean==0assertdefinition.distribution.variance==2.5

Advanced Features

Access items in dict as properties

The attrdicts argument, which defaults to true, replaces all dict object in the definition with AttrDict. This is just a Python dict except keys can be accessed as attributes. You can also explicitly use this type in the schema to allow attribute access only for some of the dicts.

definition=Parser('schema.yaml', attrdicts=True)('definition.yaml')
assertdefinition.key==valuedefinition=Parser('schema.yaml', attrdicts=False)('definition.yaml')
assertdefinition['key'] ==value

Collection of arbitrary types

Don't specify the value for the elements or mapping key.

type: listelements:

Defaults for constructor arguments

It is recommended to define arguments defaults in the constructor of the base class. However, for standard types, it can make sense to define argument defaults.

type: datemodule: datetimearguments:
year:
type: intdefault: 2000month:
type: intdefault: 1day:
type: intdefault: 1

Unknown arguments

Keys without a special meaning will always be passed as keyword arguments to the constructur of the type. This allows subclasses to accept additional parameters that are not listed in the base constructor.

Shorter syntax

YAML provides a shorter syntax for mappings, that's similar to JSON. You can even use real JSON for your schemas and definitions since YAML is a superset of that.

type: datemodule: datetimearguments:
year: {type: int, default: 2000}...

Enumerations

All types will get instantiated normally but this doesn't work for Python enum. If you are interested in using enums, please comment on the issue.

Referencing dependencies

It's possible to reference keys in the definition or schema to use the instantiated objects in other places. For example, you can define a configuration object and construct several other objects from it. Just use $path.to.object either in the schema or definition. The dependency graph must be acyclic.

About

Load and validate YAML definitions against a schema

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages