Skip to content

Commit

Permalink
Add pathlib.Path data type
Browse files Browse the repository at this point in the history
  • Loading branch information
y.kikvadze authored and yar-kik committed Feb 7, 2023
1 parent 5353b8a commit 8dfa885
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 4 deletions.
11 changes: 11 additions & 0 deletions conjector/type_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import decimal
import enum
import inspect
import pathlib
import re
from collections.abc import Iterable, Mapping
from dataclasses import MISSING, Field, fields, is_dataclass
Expand All @@ -31,6 +32,7 @@ class TypeConverter:
type(None),
enum.Enum,
decimal.Decimal,
pathlib.Path,
)

def cast_types(self, type_: Type, value: Any) -> Any:
Expand Down Expand Up @@ -70,6 +72,8 @@ def _cast_base(self, type_: Type, value: Any) -> Any:
return self._apply_enum(type_, value)
if issubclass(type_, decimal.Decimal):
return self._apply_decimal(value)
if issubclass(type_, pathlib.Path):
return self._apply_path(value)
if value is None:
return type_()
return type_(value)
Expand Down Expand Up @@ -223,6 +227,13 @@ def _apply_decimal(self, value: Any) -> decimal.Decimal:
"Decimal value should be int, float, str or 3-items list!"
)

def _apply_path(self, value: Any) -> pathlib.Path:
if value is None:
return pathlib.Path()
if isinstance(value, str):
return pathlib.Path(value)
raise ValueError("Path constructor accept only string argument!")

def _is_number(self, num: Any) -> bool:
if isinstance(num, (int, float)):
return True
Expand Down
1 change: 1 addition & 0 deletions docs/supported_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The table below shows how config values (`json` syntax example) are cast to Pyth
| `enum.Enum` | `str`<br/>`int` | `"VALUE"`<br/>`10` |
| `re.Pattern` | `str` | `"\w+"` |
| `decimal.Decimal` | `str`<br/>`int`<br/>`float` | `"12.150"`<br/>`100`<br/>`12.5` |
| `pathlib.Path` | `str` | `"some/path/to/file.txt"`/`"some/path/to/dir/"` |

## Optional types
The default behavior for the `Optional` type hint: try to convert the value to a specified type, if successful - use the converted value, else use None. Also, None will be used if no value is provided.
Expand Down
38 changes: 38 additions & 0 deletions tests/test_type_converter/test_path_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import pytest
from pathlib import Path

from conjector import properties


@pytest.fixture
def path_class_fixt(request):
@properties(filename=request.param, root="path")
class PathClass:
str_file_path_var: Path
str_dir_path_var: Path
missing_path_var: Path

return PathClass


@pytest.mark.parametrize(
"path_class_fixt",
("types_cast.yml", "types_cast.json", "types_cast.toml", "types_cast.ini"),
indirect=True,
)
def test_path_field_ok(path_class_fixt):
assert path_class_fixt.str_file_path_var == Path("some/path/file.txt")
assert path_class_fixt.str_dir_path_var == Path("some/file/")
assert path_class_fixt.missing_path_var == Path()


@pytest.mark.parametrize(
"filename",
("types_cast.yml", "types_cast.json", "types_cast.toml", "types_cast.ini"),
)
def test_invalid_path_field(filename):
with pytest.raises(ValueError):

@properties(filename=filename, root="path")
class InvalidPathClass:
invalid_path_var: Path
7 changes: 7 additions & 0 deletions tests/test_type_converter/types_cast.ini
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,10 @@ str_decimal_var = 15.150

[decimal.general_invalid_decimal_var]
invalid = "value"

[path]
str_file_path_var = some/path/file.txt
str_dir_path_var = some/file/

[path.invalid_path_var]
key = value
7 changes: 6 additions & 1 deletion tests/test_type_converter/types_cast.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,5 +278,10 @@
"float_decimal_var": 12.5,
"str_decimal_var": "15.150",
"general_invalid_decimal_var": {"invalid": "value"}
},
"path": {
"str_file_path_var": "some/path/file.txt",
"str_dir_path_var": "some/file/",
"invalid_path_var": {"key": "value"}
}
}
}
7 changes: 5 additions & 2 deletions tests/test_type_converter/types_cast.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ wrong_pattern_var = 10
int_decimal_var = 10
float_decimal_var = 12.5
str_decimal_var = "15.150"
general_invalid_decimal_var = {invalid = "value"}

[decimal.general_invalid_decimal_var]
invalid = "value"
[path]
str_file_path_var = "some/path/file.txt"
str_dir_path_var = "some/file/"
invalid_path_var = {key = "value"}
8 changes: 7 additions & 1 deletion tests/test_type_converter/types_cast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,10 @@ decimal:
float_decimal_var: 12.5
str_decimal_var: "15.150"
general_invalid_decimal_var:
invalid: value
invalid: value

path:
str_file_path_var: some/path/file.txt
str_dir_path_var: some/file/
invalid_path_var:
key: value

0 comments on commit 8dfa885

Please sign in to comment.