Skip to content
Commits on Source (3)
......@@ -8,7 +8,7 @@ __title__ = 'dataclasses-config'
__author__ = 'Peter Zaitcev / USSX Hares'
__license__ = 'BSD 2-clause'
__copyright__ = 'Copyright 2019 Peter Zaitcev'
__version__ = '0.1.2'
__version__ = '0.1.3'
VersionInfo = namedtuple('VersionInfo', 'major minor micro releaselevel serial')
version_info = VersionInfo(*__version__.split('.'), releaselevel='alpha', serial=0)
......
import os
import warnings
from dataclasses import field
from importlib import import_module
from types import ModuleType
from typing import *
from dataclasses import field
from typing_inspect import get_origin, get_args
from ._decorations import *
......@@ -59,6 +59,9 @@ class DynamicClass(Generic[T]):
expected_parent = type_args[0]
if (not issubclass(self.cls, expected_parent)):
raise TypeError(f"{self.cls!r} is not a subclass of {expected_parent!r} (from {tp!r}).")
def __repr__(self):
return f'{type(self).__name__}({self.cls!r})'
del T
@deserialize_with(ConstructorDataType.String)
......
import os
from abc import ABC
from copy import deepcopy
from dataclasses import fields, dataclass, Field, field, replace
from logging import getLogger
from typing import *
import pkg_resources
from dataclasses import fields, dataclass, Field, field, replace
from dataclasses_json import DataClassJsonMixin
from dataclasses_json.core import Json
from functional import Option
from pyhocon import ConfigTree, ConfigFactory, ConfigException
from typing_inspect import is_generic_type, get_origin, is_optional_type, get_args
from typing_inspect import is_generic_type, get_origin, is_optional_type, get_last_args
from ._classes import Path, RelPath
from ._decorations import *
......@@ -112,7 +112,7 @@ class Config(DataClassJsonMixin, ABC):
for f in fields(cls): # type: Field
tp = f.type
if (is_optional_type(tp)):
tp = get_args(tp)[0]
tp = get_last_args(tp)[0]
if (is_generic_type(tp)):
tp = get_origin(tp)
if (isinstance(tp, type) and issubclass(tp, Config)):
......@@ -128,6 +128,12 @@ class Config(DataClassJsonMixin, ABC):
# # noinspection PyDataclass
for f in fields(self): # type: Field
tp = f.type
if (is_optional_type(tp)):
tp = get_last_args(tp)[0]
is_optional = True
else:
is_optional = False
if (is_generic_type(tp)):
tp = get_origin(tp)
if (hasattr(tp, _FIELD_CONSTRUCTOR_ARGUMENT_TYPE)):
......@@ -135,6 +141,9 @@ class Config(DataClassJsonMixin, ABC):
post: PostInitFunctionType = getattr(tp, _FIELD_CONSTRUCTOR_POST_INIT)
v = getattr(self, f.name)
if (is_optional and v is None):
continue
v = tp(v)
if (post is not None):
x = post(v, f.type, parent=self)
......@@ -437,7 +446,7 @@ class ConfigWithRoot(Config, ABC):
for f in fields(self): # type: Field
tp = f.type
if (is_optional_type(tp)):
tp = get_args(tp)[0]
tp = get_last_args(tp)[0]
if (is_generic_type(tp)):
tp = get_origin(tp)
if (isinstance(tp, type) and issubclass(tp, RelPath)):
......