Config Schema

class pydoover.config.Schema[source]

Represents the configuration schema for a Doover application.

A config schema is a definition of the config for your application.

It is used as .config in your application and can generate a JSON Schema which will provide user validation and a “form” in the Doover UI.

Any attributes added in the __init__ method will be added to the schema. Order is preserved from the order you define them in the __init__ method.

The schema can be exported to a JSON file using the export method, although in a template application this is done for you.

To export the schema to the doover_config.json file, use the Doover cli: doover config-schema export. This will validate and export the schema to the doover_config.json file in the root of your Doover project.

If you want to mark the entire application as “Advanced Config” and hide it from the UI, set advanced=True in the subclass init.

Examples

>>> from pydoover import config
>>> class MyAppConfig(config.Schema):
...     pump_pin = config.Integer("Digital Output Number", description="The digital output pin to drive the pump.")
...     pump_on_time = config.Number("Pump On Time", default=5.2, description="The time in seconds to run the pump.")
...     engine_type = config.Enum(
...         "Engine Type",
...         choices=["Honda", "John Deere", "Cat"],
...         description="The type of diesel engine attached to the pump.",
...     )
classmethod export(fp: Path, app_name: str)[source]

Export the config schema to a JSON file.

This will export the config schema to the config_schema field in the doover_config.json file in the root of your project .

Examples

Generally, this will be done in the application template.

>>> from pydoover import config
>>> class MyAppConfig(config.Schema):
...     def __init__(self):
...         pump_pin = config.Integer("Digital Output Number", description="The digital output pin to drive the pump.")
...
... if __name__ == "__main__":
...     from pathlib import Path
...     MyAppConfig.export(pathlib.Path("/path/to/my/app/doover_config.json"), "my_app_name")
Parameters:
  • fp (pathlib.Path) – The path to the JSON file to export the config schema to.

  • app_name (str) – The name of the application to export the config schema for. This will be used as the key in the doover_config.json file.

Config Elements

class pydoover.config.ConfigElement(display_name, *, default: Any = <class 'pydoover.config.NotSet'>, description: str | None = None, deprecated: bool | None = None, hidden: bool = False, format: str | None = None, position: int | None = None, name: str | None = None, advanced: bool | None = None, required: bool | None = None)[source]

Represents a config element in the Doover configuration schema.

display_name

The display name of the config element. This is used in the UI.

Type:

str

default

The default value for the element. If NotSet (and required is left at None), the element is treated as required.

Type:

Any

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

required

Explicit override of the required-ness derived from default. None (default) → required is True iff default is NotSet (the historical behaviour). True → required regardless of default (config file must carry the key explicitly even though a fallback exists). False → not required; the loader uses default when absent. Passing required=False without a default raises ValueError because there’d be no value to fall back to.

Type:

bool | None

property required

Whether the config element is required.

If an explicit override was passed to __init__ (required=True or required=False), that wins. Otherwise falls back to the historical default-derived behaviour: required iff default is NotSet.

property value

The value of the config element.

class pydoover.config.Integer(display_name, *, minimum: int = None, exclusive_minimum: int = None, maximum: int = None, exclusive_maximum: int = None, multiple_of: int = None, **kwargs)[source]

Represents a JSON Integer type. Internally represented as an int.

display_name

The display name of the config element. This is used in the UI.

Type:

str

default

The default value for the integer. If NotSet, the value is required.

Type:

int

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

minimum

The minimum value for the integer. If None, no minimum is enforced.

Type:

int | None

exclusive_minimum

The exclusive minimum value for the integer. If None, no exclusive minimum is enforced.

Type:

int | None

maximum

The maximum value for the integer. If None, no maximum is enforced.

Type:

int | None

exclusive_maximum

The exclusive maximum value for the integer. If None, no exclusive maximum is enforced.

Type:

int | None

multiple_of

The value that the integer must be a multiple of. If None, no multiple is enforced.

Type:

int | None

property required

Whether the config element is required.

If an explicit override was passed to __init__ (required=True or required=False), that wins. Otherwise falls back to the historical default-derived behaviour: required iff default is NotSet.

property value

The value of the config element.

class pydoover.config.Number(display_name, *, minimum: int = None, exclusive_minimum: int = None, maximum: int = None, exclusive_maximum: int = None, multiple_of: int = None, **kwargs)[source]

Represents a JSON Number type, for any numeric type. Internally represented as a float.

display_name

The display name of the config element. This is used in the UI.

Type:

str

default

The default value for the integer. If NotSet, the value is required.

Type:

float

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

property required

Whether the config element is required.

If an explicit override was passed to __init__ (required=True or required=False), that wins. Otherwise falls back to the historical default-derived behaviour: required iff default is NotSet.

property value

The value of the config element.

class pydoover.config.String(display_name, *, length: int | None = None, pattern: str | None = None, **kwargs)[source]

Represents a JSON String type. Internally represented as a str.

display_name

The display name of the config element. This is used in the UI.

Type:

str

default

The default value for the integer. If NotSet, the value is required.

Type:

str

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

length

The length of the string. If None, no length is enforced.

Type:

int | None

pattern

A regex pattern that the string must match. If None, no pattern is enforced.

Type:

str | None

property required

Whether the config element is required.

If an explicit override was passed to __init__ (required=True or required=False), that wins. Otherwise falls back to the historical default-derived behaviour: required iff default is NotSet.

property value

The value of the config element.

class pydoover.config.Boolean(display_name, *, default: Any = <class 'pydoover.config.NotSet'>, description: str | None = None, deprecated: bool | None = None, hidden: bool = False, format: str | None = None, position: int | None = None, name: str | None = None, advanced: bool | None = None, required: bool | None = None)[source]

Represents a JSON Boolean type. Internally represented as a bool.

display_name

The display name of the config element. This is used in the UI.

Type:

str

default

The default value for the integer. If NotSet, the value is required.

Type:

bool

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

class pydoover.config.Enum(display_name, *, choices: list | EnumType = None, default: Any, **kwargs)[source]

Represents a JSON Enum type. Internally represented as a list of choices.

The UI renders this as a drop-down.

Examples

You can specify a list of choices as strings or floats, or use an EnumType:

from pydoover import config

class MyChoice(enum.Enum):
    A = "Choice 1"
    B = "Choice 2"
    C = "Choice 3"

class AppConfig(config.Schema):
    def __init__(self):
        self.choice = config.Enum(
            "Choose Something",
            choices=MyChoice,
            default=MyChoice.A,
        )

        self.other_choice = config.Enum(
            "Other Choice",
            choices=["a", "b", "c"],
            default="a"
        )

You can also set enum values to be objects to allow for custom attributes, provided your object implements __str__:

from pydoover import config

class Choice:
    def __init__(self, name, level):
        self.name = name
        self.level = level

    def __str__(self):
        return self.name

class ChoiceType(enum.Enum):
    A = Choice("A", 1)
    B = Choice("B", 2)
    C = Choice("C", 3)

class AppConfig(config.Schema):
    def __init__(self):
        self.choice = config.Enum(
            "Choose Something",
            choices=ChoiceType,
            default=ChoiceType.A,
        )

    @property
    def choice_value(self):
        return self.choice.value.level
display_name

The display name of the config element. This is used in the UI.

Type:

str

default

The default value for the integer. If NotSet, the value is required.

Type:

same type as choices.

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

choices

A list of choices for the enum. All choices must be of the same type (str or float). This optionally accepts an EnumType, with the value of the enum denoting the choice. The value can be an object which implements the __str__ method. Each __str__ value must be unique.

Type:

EnumType or list of str | float

property value

The value of the config element.

class pydoover.config.Array(display_name, *, element: ConfigElement | None = None, min_items: int | None = None, max_items: int | None = None, unique_items: bool | None = None, **kwargs)[source]

Represents a JSON Array type. Internally represented as a list.

Only a subset of JSON Schema is supported: - Item type - Minimum and maximum number of items - Unique items

display_name

The display name of the config element. This is used in the UI.

Type:

str

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

element

The type of elements in the array. This can be any ConfigElement, such as String, Integer, etc.

Type:

ConfigElement

min_items

The minimum number of items in the array. If None, no minimum is enforced.

Type:

int | None

max_items

The maximum number of items in the array. If None, no maximum is enforced.

Type:

int | None

unique_items

Whether the items in the array must be unique. If None, no uniqueness is enforced.

Type:

bool | None

property value: list[ConfigElement]

The value of the config element.

class pydoover.config.Object(display_name, *, additional_elements: bool | dict[str, Any] = True, collapsible: bool = True, default_collapsed: bool = False, **kwargs)[source]

Represents a JSON Object type.

This is a complex type that can contain multiple elements, each with its own type. It can also have additional elements that are not defined in the schema.

The UI renders this as a form with fields for each element.

Examples

>>> from pydoover import config
>>> class MyAppConfig(config.Schema):
...     def __init__(self):
...         self.pump = config.Object(
...             "Pump Settings",
...          )
...         self.pump.add_elements(
...             config.Integer("Digital Output Number", description="The digital output pin to drive the pump."),
...             config.Number("On Time", default=5.2, description="The time in seconds to run the pump."),
...         )
display_name

The display name of the config element. This is used in the UI.

Type:

str

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

additional_elements

If True, allows additional elements that are not defined in the schema. If a dict, defines the schema for additional elements. If False, no additional elements are allowed.

Type:

bool | dict[str, Any]

class pydoover.config.Variable(scope: str, name: str)[source]

Represents a variable in the config schema.

This is a special type of config element that is used to reference other config elements. It is used to create dynamic references to other config elements, such as device-specific settings.

display_name

The display name of the config element. This is used in the UI.

Type:

str

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool

scope

The scope of the variable, which is usually the application name.

Type:

str

name

The name of the variable, which is usually the key of the config element.

Type:

str

class pydoover.config.Application(display_name: str = 'Application', *, description: str = 'Application', **kwargs)[source]

Represents a Doover application configuration element.

This is used to reference other Doover applications in the configuration schema.

This is rendered as a dropdown in the UI, allowing the user to select an available application.

display_name

The display name of the config element. This is used in the UI.

Type:

str

description

A help text for the config element.

Type:

str | None

hidden

Whether the config element should be hidden in the UI.

Type:

bool