Skip to content

Commit

Permalink
Strict mode (#36) #minor
Browse files Browse the repository at this point in the history
* add strict mode opt

* update deps

* update changelog
  • Loading branch information
zifeo authored Feb 9, 2022
1 parent a3837cc commit 904b293
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 94 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
repos:
- repo: https://github.com/sqlalchemyorg/zimports/
rev: v0.4.1
rev: v0.4.3
hooks:
- id: zimports
- repo: https://github.com/psf/black
rev: 21.9b0
rev: 22.1.0
hooks:
- id: black
- repo: https://gitlab.com/pycqa/flake8
Expand Down
22 changes: 10 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

## [1.2.0]
## [1.3.0]

### Added

- dict source support

### Changed
- strict mode is now optional #36

### Fixed

## [1.1.0]

### Added
- `.env` source disable strict mode #36

- datetime parsing
## [1.2.0]

### Changed
### Added

### Fixed
- dict source support

## [1.0.1]
## [1.1.0]

### Added

### Changed
- datetime parsing

## [1.0.1]

### Fixed

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ is equivalent to
}
```

Note that when using `.env` source, the strict mode is disabled and value might be casted.

## CLI usage

Can be used for validation or converting between supported file formats (`-o`).
Expand Down
18 changes: 10 additions & 8 deletions dataconf/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import pyparsing


def parse(conf: ConfigTree, clazz):
def parse(conf: ConfigTree, clazz, strict=True):
try:
return utils.__parse(conf, clazz, "")
return utils.__parse(conf, clazz, "", strict)
except pyparsing.ParseSyntaxException as e:
raise MalformedConfigException(
f'parsing failure line {e.lineno} character {e.col}, got "{e.line}"'
Expand All @@ -23,33 +23,35 @@ def env_dict_list(prefix: str):


class Multi:
def __init__(self, confs: List[ConfigTree]) -> None:
def __init__(self, confs: List[ConfigTree], strict: bool = True) -> None:
self.confs = confs
self.strict = strict

def env(self, prefix: str) -> "Multi":
self.strict = False
return self.dict(env_dict_list(prefix))

def dict(self, obj: str) -> "Multi":
conf = ConfigFactory.from_dict(obj)
return Multi(self.confs + [conf])
return Multi(self.confs + [conf], self.strict)

def string(self, s: str) -> "Multi":
conf = ConfigFactory.parse_string(s)
return Multi(self.confs + [conf])
return Multi(self.confs + [conf], self.strict)

def url(self, uri: str) -> "Multi":
conf = ConfigFactory.parse_URL(uri)
return Multi(self.confs + [conf])
return Multi(self.confs + [conf], self.strict)

def file(self, path: str) -> "Multi":
conf = ConfigFactory.parse_file(path)
return Multi(self.confs + [conf])
return Multi(self.confs + [conf], self.strict)

def on(self, clazz):
conf, *nxts = self.confs
for nxt in nxts:
conf = ConfigTree.merge_configs(conf, nxt)
return parse(conf, clazz)
return parse(conf, clazz, self.strict)


multi = Multi([])
Expand Down
33 changes: 25 additions & 8 deletions dataconf/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def is_optional(type):
return get_origin(type) is Union and NoneType in get_args(type)


def __parse(value: any, clazz, path):
def __parse(value: any, clazz, path, strict):

if is_dataclass(clazz):

Expand All @@ -65,7 +65,7 @@ def __parse(value: any, clazz, path):
val = f.default

if not isinstance(val, _MISSING_TYPE):
fs[f.name] = __parse(val, f.type, f"{path}.{f.name}")
fs[f.name] = __parse(val, f.type, f"{path}.{f.name}", strict)

elif is_optional(f.type):
# Optional not found
Expand All @@ -91,7 +91,7 @@ def __parse(value: any, clazz, path):
if len(args) != 1:
raise MissingTypeException("expected list with type information: List[?]")
if value is not None:
return [__parse(v, args[0], f"{path}[]") for v in value]
return [__parse(v, args[0], f"{path}[]", strict) for v in value]
return None

if origin is dict:
Expand All @@ -100,13 +100,15 @@ def __parse(value: any, clazz, path):
"expected dict with type information: Dict[?, ?]"
)
if value is not None:
return {k: __parse(v, args[1], f"{path}.{k}") for k, v in value.items()}
return {
k: __parse(v, args[1], f"{path}.{k}", strict) for k, v in value.items()
}
return None

if is_optional(clazz):
left, right = args
try:
return __parse(value, left if right is NoneType else right, path)
return __parse(value, left if right is NoneType else right, path, strict)
except TypeConfigException:
# cannot parse Optional
return None
Expand All @@ -115,22 +117,37 @@ def __parse(value: any, clazz, path):
left, right = args

try:
return __parse(value, left, path)
return __parse(value, left, path, strict)
except TypeConfigException as left_failure:
try:
return __parse(value, right, path)
return __parse(value, right, path, strict)
except TypeConfigException as right_failure:
raise TypeConfigException(
f"expected type {clazz} at {path}, failed both:\n- {left_failure}\n- {right_failure}"
)

if clazz is bool:
if not strict:
try:
value = bool(value)
except ValueError:
pass
return __parse_type(value, clazz, path, isinstance(value, bool))

if clazz is int:
if not strict:
try:
value = int(value)
except ValueError:
pass
return __parse_type(value, clazz, path, isinstance(value, int))

if clazz is float:
if not strict:
try:
value = float(value)
except ValueError:
pass
return __parse_type(
value, clazz, path, isinstance(value, float) or isinstance(value, int)
)
Expand All @@ -157,7 +174,7 @@ def __parse(value: any, clazz, path):
for child_clazz in sorted(clazz.__subclasses__(), key=lambda c: c.__name__):
if is_dataclass(child_clazz):
try:
return __parse(value, child_clazz, path)
return __parse(value, child_clazz, path, strict)
except (
TypeConfigException,
MalformedConfigException,
Expand Down
Loading

0 comments on commit 904b293

Please sign in to comment.