Supported types

conjector can work with deep nested data structures and recursively cast them to corresponding type hints. The table below shows how config values (json syntax example) are cast to Python types:

Python type

Config file type

Config example

int

int
str

10
"10"

float

float
int
str

10.5
10
"10.5"

str

str

"string value"

bool

bool
int
str

true / false
1 / 0
"True" / "False", "true" / "false"

None

null

null

dict

dict

{"key": "value"}

list
tuple
set
frozenset

list

["val1", "val2"]

TypedDict

dict

{"str_var": "value"}

NamedTuple

list
dict

["value", 10]
{"str_val": "value", "int_val": 10}

dataclass

dict

{"str_val": "str", "int_val": 10}

datetime.datetime

str
int
list
dict

"2022-12-11T10:20:23"
1670754600
[2022, 12, 11, 10, 20, 23]
{"year": 2022, "month": 12, "day": 11, "hour": 10, "minute": 20, "second": 23}

datetime.date

str
list
dict

"2022-12-11"
[2022, 12, 11]
{"year": 2022, "month": 12, "day": 11}

datetime.time

str
list
dict

"12:30:02"
[12, 30, 2]
{"hour": 12, "minute": 30, "second": 2}

datetime.timedelta

dict

{"days": 1, "hours": 2, "minutes": 10}

enum.Enum

str
int

"VALUE"
10

re.Pattern

str

"\w+"

decimal.Decimal

str
int
float
list[int, list[int], int

"12.150"
100
12.5
[1, [1, 2, 5], -3]

pathlib.Path

str

"some/path/to/file.txt"/"some/path/to/dir/"

Optional types

The default behavior for the Optional type hint: try to convert the value to a specified type, if successful - use the converted value, else use None. Also, None will be used if no value is provided.

optional_types.yml

optional_value_presented: "10"
optional_value_missing:
optional_value_invalid: "invalid integer"

optional_types.py:

from typing import Optional

from conjector import properties


@properties(filename="optional_types.yml")
class SomeOptionalClass:
    optional_value_presented: Optional[int]
    optional_value_missing: Optional[int]
    optional_value_invalid: Optional[int]


assert SomeOptionalClass.optional_value_presented == 10
assert SomeOptionalClass.optional_value_missing is None
assert SomeOptionalClass.optional_value_invalid is None

Union types

How the Union type hint works: in a specified order (e.g. Union[float, dict, str]) the value will be cast first to float, then, if the attempt fails, to dict, and finally to str. If the value cannot be converted to any of the provided types, ValueError will be thrown. The casting process will be stopped immediately after the first successful attempt.

union_types.yml:

union_value_float: 125
union_value_dict:
  key: value
union_value_str: "str value"
union_values_dict:
  some: value
union_values_list:
  - some: val1
  - some: val2

union_types.py:

from typing import List, Union

from conjector import properties


@properties(filename="union_types.yml")
class SomeUnionClass:
    union_value_float: Union[float, dict, str]
    union_value_dict: Union[float, dict, str]
    union_value_str: Union[float, dict, str]

    union_values_dict: Union[dict, List[dict]]
    union_values_list: Union[dict, List[dict]]


assert SomeUnionClass.union_value_float == 125
assert SomeUnionClass.union_value_dict == {"key": "value"}
assert SomeUnionClass.union_value_str == "str value"
assert SomeUnionClass.union_values_dict == {"some": "value"}
assert SomeUnionClass.union_values_list == [{"some": "val1"}, {"some": "val2"}]