Welcome to Validobj’s documentation!

Validobj is a library that processes semistructured input coming from sources a JSON mapping or a YAML configuration file into more structured Python objects. Currently it only has one API function, validobj.validation.parse_input(), but it can do quite a bit!

import dataclasses
import enum
from typing import Mapping, Set, Tuple, List

from validobj import parse_input

inp = {
    'global_environment': {'CI_ACTIVE': '1'},
    'stages': [
        {
            'name': 'compile',
            'os': ['linux', 'mac'],
            'script_path': 'build.sh',
            'disk_permissions': ['READ', 'WRITE', 'EXECUTE'],
        },
        {
            'name': 'test',
            'os': ['linux', 'mac'],
            'script_path': 'test.sh',
            'framework_version': [4, 0],
        },
    ],
}


class DiskPermissions(enum.Flag):
    READ = enum.auto()
    WRITE = enum.auto()
    EXECUTE = enum.auto()


class OS(enum.Enum):
    mac = enum.auto()
    windows = enum.auto()
    linux = enum.auto()


@dataclasses.dataclass
class Job:
    name: str
    os: Set[OS]
    script_path: str
    framework_version: Tuple[int, int] = (1, 0)
    disk_permissions: DiskPermissions = DiskPermissions.READ


@dataclasses.dataclass
class CIConf:
    stages: List[Job]
    global_environment: Mapping[str, str] = dataclasses.field(default_factory=dict)



print(parse_input(inp, CIConf))
# This results in a dataclass instance with the correct types:
#
#CIConf(
#    stages=[
#        Job(
#            name='compile',
#            os={<OS.linux: 3>, <OS.mac:1>},
#            script_path='build.sh',
#            framework_version=(1, 0),
#            disk_permissions=<DiskPermissions.EXECUTE|WRITE|READ: 7>,
#        ),
#        Job(
#            name='test',
#            os={<OS.linux: 3>, <OS.mac: 1>},
#            script_path='test.sh',
#            framework_version=(4, 0),
#            disk_permissions='<DiskPermissions.READ: 1>',
#        ),
#    ],
#    global_environment={'CI_ACTIVE': '1'},
#)
#

The full set of applied checks and transformations is described in Input and output.

Validobj aims at providing building blocks to construct the most human friendly error handling in town. Its exceptions provide lots of information on what went wrong as well as good error messages, which even contain suggestions on typos.

>>> import enum
>>> import validobj
>>> class DiskPermissions(enum.Flag):
...     READ = enum.auto()
...     WRITE = enum.auto()
...     EXECUTE = enum.auto()
...
>>> validobj.parse_input(['EXECUTE', 'RAED'], DiskPermissions) 
NotAnEnumItemError                        Traceback (most recent call last)
...
NotAnEnumItemError: 'RAED' is not a valid member of 'DiskPermissions'.
Alternatives to invalid value 'RAED' include:
  - READ
All valid values are:
  - READ
  - WRITE
  - EXECUTE

The above exception was the direct cause of the following exception:
...
WrongListItemError: Cannot process item 2 into 'DiskPermissions'.

Indices and tables