Skip to content

Commit

Permalink
add datetime support (#32)
Browse files Browse the repository at this point in the history
#minor adding datetime support
  • Loading branch information
zifeo authored Nov 7, 2021
1 parent ed5f5eb commit f9bc35f
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- datetime parsing

### Changed

### Fixed
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ import os
from dataclasses import dataclass, field
from typing import List, Dict, Text, Union
from dateutil.relativedelta import relativedelta
from datetime import datetime
import dataconf

conf = """
str_name = test
str_name = ${?HOME}
dash-to-underscore = true
float_num = 2.2
iso_datetime = "2000-01-01T20:00:00"
# this is a comment
list_data = [
a
Expand Down Expand Up @@ -83,6 +85,7 @@ class Config:
str_name: Text
dash_to_underscore: bool
float_num: float
iso_datetime: datetime
list_data: List[Text]
nested: Nested
nested_list: List[Nested]
Expand Down
1 change: 1 addition & 0 deletions confs/readme.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ str_name = test
str_name = ${?HOME}
dash-to-underscore = true
float_num = 2.2
iso_datetime = "2000-01-01T20:00:00"
# this is a comment
list_data = [
a
Expand Down
14 changes: 13 additions & 1 deletion dataconf/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
class TypeConfigException(Exception):
"""Type mismatch exception."""

pass


class MissingTypeException(Exception):
"""Missing type exception (e.g. List instead of List[int]."""

pass


class MalformedConfigException(Exception):
"""Missing values exception."""

pass


class UnexpectedKeysException(Exception):
"""Unexpected keys exception."""

pass


class EnvListOrderException(Exception):
"""Ordering exception."""

pass


class EnvParseException(Exception):
class ParseException(Exception):
"""Parsing exception."""

pass
17 changes: 14 additions & 3 deletions dataconf/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
from dataclasses import asdict
from dataclasses import fields
from dataclasses import is_dataclass
from datetime import datetime
from typing import get_args
from typing import get_origin
from typing import Union

from dataconf.exceptions import EnvListOrderException
from dataconf.exceptions import EnvParseException
from dataconf.exceptions import MalformedConfigException
from dataconf.exceptions import MissingTypeException
from dataconf.exceptions import ParseException
from dataconf.exceptions import TypeConfigException
from dataconf.exceptions import UnexpectedKeysException
from dateutil.parser import isoparse
from dateutil.relativedelta import relativedelta
from pyhocon import ConfigFactory
from pyhocon.config_tree import ConfigList
Expand Down Expand Up @@ -136,6 +138,15 @@ def __parse(value: any, clazz, path):
if clazz is str:
return __parse_type(value, clazz, path, isinstance(value, str))

if clazz is datetime:
dt = __parse_type(value, clazz, path, isinstance(value, str))
try:
return isoparse(dt)
except ValueError as e:
raise ParseException(
f"expected type {clazz} at {path}, cannot parse due to {e}"
)

if clazz is relativedelta:
return __parse_type(value, clazz, path, isinstance(value, relativedelta))

Expand Down Expand Up @@ -251,8 +262,8 @@ def int_or_string(v):
try:
v = ConfigFactory.parse_string(v)
except pyparsing.ParseBaseException as e:
raise EnvParseException(
f"env var {k} ends with `_` and expects a nested config, but got: {e}"
raise ParseException(
f"env var {k} ends with `_` and expects a nested config, got: {e}"
)
k = k[:-1]

Expand Down
4 changes: 2 additions & 2 deletions tests/test_dict_list_parsing.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataconf.exceptions import EnvListOrderException
from dataconf.exceptions import EnvParseException
from dataconf.exceptions import ParseException
from dataconf.utils import __dict_list_parsing as dict_list_parsing
import pytest

Expand Down Expand Up @@ -82,5 +82,5 @@ def test_bad_nested_config(self) -> None:
env = {
"P_A_0_": "::",
}
with pytest.raises(EnvParseException):
with pytest.raises(ParseException):
dict_list_parsing("P", env)
26 changes: 26 additions & 0 deletions tests/test_parse.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from dataclasses import dataclass
from dataclasses import field
from datetime import datetime
from datetime import timezone
import os
from typing import Dict
from typing import List
Expand All @@ -11,6 +13,7 @@
from dataconf import loads
from dataconf.exceptions import MalformedConfigException
from dataconf.exceptions import MissingTypeException
from dataconf.exceptions import ParseException
from dataconf.exceptions import TypeConfigException
from dataconf.exceptions import UnexpectedKeysException
from dateutil.relativedelta import relativedelta
Expand Down Expand Up @@ -154,6 +157,29 @@ class A:
"""
assert loads(conf, A) == A(b="test")

def test_datetime(self) -> None:
@dataclass
class A:
b: datetime

conf = """
b = "1997-07-16T19:20:07+01:00"
"""
assert loads(conf, A) == A(
b=datetime(1997, 7, 16, 18, 20, 7, tzinfo=timezone.utc)
)

def test_bad_datetime(self) -> None:
@dataclass
class A:
b: datetime

conf = """
b = "1997-07-16 19:20:0701:00"
"""
with pytest.raises(ParseException):
assert loads(conf, A)

def test_optional_with_default(self) -> None:
@dataclass
class A:
Expand Down
3 changes: 3 additions & 0 deletions tests/test_regression.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from abc import ABCMeta
from dataclasses import dataclass
from dataclasses import field
from datetime import datetime
import os
from typing import Dict
from typing import List
Expand Down Expand Up @@ -39,6 +40,7 @@ class Config:
str_name: Text
dash_to_underscore: bool
float_num: float
iso_datetime: datetime
list_data: List[Text]
nested: Nested
nested_list: List[Nested]
Expand All @@ -56,6 +58,7 @@ class Config:
str_name=os.environ.get("HOME", "test"),
dash_to_underscore=True,
float_num=2.2,
iso_datetime=datetime(2000, 1, 1, 20),
list_data=["a", "b"],
nested=Nested(a="test", b=1),
nested_list=[Nested(a="test1", b=2.5)],
Expand Down

0 comments on commit f9bc35f

Please sign in to comment.