Skip to content

Commit b305228

Browse files
Denis Navarroticdenis
Denis Navarro
authored andcommitted
feat(*): Support multiple casting for variables and allows "None" as None for default values
1 parent 61155b3 commit b305228

File tree

7 files changed

+36
-11
lines changed

7 files changed

+36
-11
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ pip install aiodi
3131
name = "%env(str:APP_NAME, 'sample')%"
3232
version = "%env(int:APP_VERSION, '1')%"
3333
log_level = "%env(APP_LEVEL, 'INFO')%"
34+
debug = "%env(bool:int:APP_DEBUG, '0')%"
35+
text = "Hello World"
3436

3537
[tool.aiodi.services."_defaults"]
3638
project_dir = "../../.."

aiodi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from .builder import ContainerBuilder
44
from .container import Container, ContainerKey
55

6-
__version__ = '1.1.1'
6+
__version__ = '1.1.2'
77

88
__all__ = (
99
# di

aiodi/resolver/variable.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
from ..helpers import raise_, re_finditer
55
from . import Resolver, ValueNotFound, ValueResolutionPostponed
66

7-
REGEX = r"%(static|env|var)\((str:|int:|float:|bool:)?([\w]+)(,\s{1}'.*?')?\)%"
7+
REGEX = r"%(static|env|var)\(([str:int:float:bool:]*?)([\w]+)(,\s{1}'.*?')?\)%"
88
STATIC_TEMPLATE: str = "%static({0}:{1}, '{2}')%"
9+
_VAR_DEFAULTS = ...
910

1011

1112
class VariableMetadata(NamedTuple):
@@ -15,18 +16,24 @@ class VariableMetadata(NamedTuple):
1516

1617
class MatchMetadata(NamedTuple): # type: ignore
1718
source_kind: str
18-
type: Type[Any]
19+
types: List[Type[Any]]
1920
source_name: str
2021
default: Any
2122
match: Match
2223

2324
@classmethod
2425
def from_match(cls, match: Match) -> 'VariableMetadata.MatchMetadata':
26+
raw_types = (
27+
['str']
28+
if match.groups()[1] is None or len(str(match.groups()[1])) == 0
29+
else [s for s in str(match.groups()[1]).split(':') if s.strip() != '']
30+
)
31+
raw_default = _VAR_DEFAULTS if match.groups()[3] is None else str(match.groups()[3])[3:-1]
2532
return cls(
2633
source_kind=str(match.groups()[0]),
27-
type=str if match.groups()[1] is None else globals()['__builtins__'][str(match.groups()[1])[:-1]],
34+
types=[globals()['__builtins__'][raw_type] for raw_type in raw_types],
2835
source_name=str(match.groups()[2]),
29-
default=None if match.groups()[3] is None else str(match.groups()[3])[3:-1],
36+
default=None if isinstance(raw_default, str) and raw_default == 'None' else raw_default,
3037
match=match,
3138
)
3239

@@ -36,6 +43,11 @@ def __init__(self, name: str) -> None:
3643
super().__init__(kind='Variable', name=name)
3744

3845

46+
class EnvironmentVariableNotFound(ValueNotFound):
47+
def __init__(self, name: str) -> None:
48+
super().__init__(kind='EnvironmentVariable', name=name)
49+
50+
3951
class VariableResolutionPostponed(ValueResolutionPostponed[VariableMetadata]):
4052
pass
4153

@@ -77,7 +89,12 @@ def parse_value(
7789
if metadata_.source_kind == 'static':
7890
typ_val = metadata_.default
7991
elif metadata_.source_kind == 'env':
80-
typ_val = getenv(key=metadata_.source_name, default=metadata_.default or '')
92+
typ_val = getenv(key=metadata_.source_name, default=metadata_.default)
93+
if typ_val is None:
94+
# can only concatenate str to str
95+
return typ_val
96+
if metadata_.default is _VAR_DEFAULTS and typ_val == metadata_.default:
97+
raise EnvironmentVariableNotFound(name=metadata_.source_name)
8198
elif metadata_.source_kind == 'var':
8299
if metadata_.source_name not in _variables:
83100
if retries != -1:
@@ -94,7 +111,9 @@ def parse_value(
94111
values += metadata.value[metadata_.match.end() :]
95112
value: Any = ''.join(values)
96113
if len(metadata.matches) == 1:
97-
value = metadata.matches[0].type(value)
114+
# multiple casting
115+
for type_ in reversed(metadata.matches[0].types):
116+
value = type_(value)
98117
return value
99118

100119

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = "aiodi"
3-
version = "1.1.1"
3+
version = "1.1.2"
44
description = "Container for the Dependency Injection in Python."
55
license = "MIT"
66
authors = ["ticdenis <[email protected]>"]

requirements-dev.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ autoflake==1.4
33
# fixed due to Python 3.6 support
44
bandit==1.7.1
55
black==22.1.0
6-
commitizen==2.20.5
6+
commitizen==2.21.0
77
isort==5.10.1
88
liccheck==0.6.5
99
mkdocs==1.2.3
10-
mkdocs-material==8.1.10
10+
mkdocs-material==8.2.1
1111
mypy==0.931
1212
pre-commit==2.17.0
1313
psutil==5.9.0
@@ -23,5 +23,5 @@ setuptools==59.6.0
2323
# fixed due to Python 3.6 support
2424
shellcheck-py==0.8.0.3
2525
twine==3.8.0
26-
types-toml==0.10.3
26+
types-toml==0.10.4
2727
wheel==0.37.1

sample/pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
name = "%env(str:APP_NAME, 'sample')%"
33
version = "%env(int:APP_VERSION, '1')%"
44
log_level = "%env(APP_LEVEL, 'INFO')%"
5+
debug = "%env(bool:int:APP_DEBUG, '0')%"
6+
text = "Hello World"
57

68
[tool.aiodi.services."_defaults"]
79
project_dir = "../../.."

tests/integration/aiodi/test_builder.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def test_container() -> None:
2020
assert 'env.log_level' in di and di.get('env.log_level', typ=str) == 'INFO'
2121
assert 'env.name' in di and di.get('env.name', typ=str) == 'sample'
2222
assert 'env.version' in di and di.get('env.version', typ=int) == 1
23+
assert 'env.debug' in di and di.get('env.debug', typ=bool) is False
24+
assert 'env.text' in di and di.get('env.text', typ=str) == 'Hello World'
2325

2426
assert 'UserLogger' in di and di.get('UserLogger', typ=InMemoryUserLogger)
2527
assert 'logging.Logger' in di and di.get(Logger)

0 commit comments

Comments
 (0)