diff --git a/app_properties/type_converter.py b/app_properties/type_converter.py index 153ff75..1ec0ee9 100644 --- a/app_properties/type_converter.py +++ b/app_properties/type_converter.py @@ -11,6 +11,7 @@ ) import inspect +import re from collections.abc import Iterable, Mapping from dataclasses import MISSING, Field, fields, is_dataclass from datetime import date, datetime, time, timedelta @@ -46,13 +47,17 @@ def cast_types(self, type_: Union[type, Any], value: Any) -> Any: return self._apply_dataclass(type_, value) return self._cast_base(type_, value) - def _cast_base(self, type_: type, value: Any) -> Any: + def _cast_base(self, type_: Type, value: Any) -> Any: if self._is_none_type(type_): return None - if value is None and not issubclass(type_, Enum): - return type_() if type_ == bool: return self._cast_bool(value) + if type_ == re.Pattern: + return self._apply_regex_pattern(value) + if issubclass(type_, Enum): + return self._apply_enum(type_, value) + if value is None: + return type_() return type_(value) def _cast_bool(self, value: Any) -> Optional[bool]: @@ -61,7 +66,7 @@ def _cast_bool(self, value: Any) -> Optional[bool]: value = str(value) if value in ("true", "True", "1"): return True - if value in ("false", "False", "0"): + if value in ("false", "False", "0", "None"): return False return None @@ -178,6 +183,14 @@ def _apply_union(self, args: Any, value: Any) -> Any: return None raise ValueError(f"Couldn't cast '{value}' to any of types: {args}") + def _apply_regex_pattern(self, values: Any) -> re.Pattern: + if not isinstance(values, str): + raise ValueError("Regex pattern should be string!") + return re.compile(values) + + def _apply_enum(self, type_: Type[Enum], values: Any) -> Enum: + return type_(values) + def _is_terminate(self, type_: Any, args: tuple) -> bool: return ( self._is_any(args) diff --git a/tests/test_type_converter/test_regex_pattern_field.py b/tests/test_type_converter/test_regex_pattern_field.py new file mode 100644 index 0000000..86f31dc --- /dev/null +++ b/tests/test_type_converter/test_regex_pattern_field.py @@ -0,0 +1,26 @@ +import pytest +import re +from re import Pattern + +from app_properties import properties + + +@pytest.fixture +def regex_class_fixt(): + @properties(filename="types_cast.yml", root="regex") + class RegexClass: + some_pattern_var: Pattern + + return RegexClass + + +def test_regex_pattern_field(regex_class_fixt): + assert regex_class_fixt.some_pattern_var == re.compile(r"\w+") + + +def test_regex_pattern_wrong_value(): + with pytest.raises(ValueError): + + @properties(filename="types_cast.yml", root="regex") + class WrongRegexClass: + wrong_pattern_var: Pattern diff --git a/tests/test_type_converter/types_cast.yml b/tests/test_type_converter/types_cast.yml index 5ce4d4f..50d6807 100644 --- a/tests/test_type_converter/types_cast.yml +++ b/tests/test_type_converter/types_cast.yml @@ -220,4 +220,8 @@ datetime: enum: simple_enum_var: GREEN int_enum_var: 3 - invalid_enum_var: INVALID \ No newline at end of file + invalid_enum_var: INVALID + +regex: + some_pattern_var: \w+ + wrong_pattern_var: 10 \ No newline at end of file