diff --git a/README.md b/README.md index e0a782f..b72f8f6 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ -
v0.1
v0.1.9
zod
inspired library for Python 3.11+
@@ -116,19 +116,20 @@ Name Stmts Miss Cover
----------------------------------------------
src/parasite/__init__.py 22 0 100%
src/parasite/_const.py 17 0 100%
+src/parasite/_utils.py 7 0 100%
src/parasite/any.py 27 0 100%
src/parasite/array.py 70 0 100%
src/parasite/boolean.py 72 0 100%
src/parasite/errors.py 1 0 100%
src/parasite/never.py 18 0 100%
src/parasite/null.py 29 0 100%
-src/parasite/number.py 105 0 100%
+src/parasite/number.py 106 0 100%
src/parasite/object.py 93 0 100%
src/parasite/string.py 207 0 100%
src/parasite/type.py 29 0 100%
src/parasite/variant.py 61 0 100%
----------------------------------------------
-TOTAL 751 0 100%
+TOTAL 759 0 100%
```
diff --git a/pyproject.toml b/pyproject.toml
index 27a834d..6505c0b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -134,3 +134,4 @@ select = [
# flake8-simplify
"SIM",
]
+ignore = ["UP007", "UP035"]
diff --git a/src/parasite/_utils.py b/src/parasite/_utils.py
new file mode 100644
index 0000000..f3d7216
--- /dev/null
+++ b/src/parasite/_utils.py
@@ -0,0 +1,21 @@
+from typing import Optional, TypeVar, Callable
+
+T = TypeVar("T")
+U = TypeVar("U")
+
+
+def map_optional(func: Callable[[T], U], value: Optional[T]) -> Optional[U]:
+ """
+ Calls the mapping function on the value, if it is not None.
+
+ Args:
+ func (callable[[T], U]): mapping function
+ value (Optional[T]): value to map
+
+ Returns:
+ Optional[U]: mapped value
+ """
+ if value is None:
+ return value
+
+ return func(value)
diff --git a/src/parasite/number.py b/src/parasite/number.py
index b1e6d07..7d30a06 100644
--- a/src/parasite/number.py
+++ b/src/parasite/number.py
@@ -11,6 +11,7 @@
# -- Package Imports --
from parasite.errors import ValidationError
from parasite.type import ParasiteType, _NotFound
+from parasite._utils import map_optional
K = TypeVar("K")
"""Template type for the key in a dictionary."""
@@ -254,21 +255,24 @@ def _parse(self, obj: Numerical) -> Numerical:
"""
# cast to integer, if required
if self._f_integer:
- self._m_ll = int(self._m_ll) if self._m_ll is not None else None
- self._m_ul = int(self._m_ul) if self._m_ul is not None else None
+ self._m_ll = map_optional(int, self._m_ll)
+ self._m_ul = map_optional(int, self._m_ul)
+ # validate upper limit values and guard clauses
if self._f_lt and obj >= self._m_ul:
raise ValidationError(f"object has to be < '{self._m_ul}', but is {obj!r}")
elif self._f_lte and obj > self._m_ul:
raise ValidationError(f"object has to be =<'{self._m_ul}', but is {obj!r}")
+ # validate lower limit values and guard clauses
if self._f_gt and obj <= self._m_ll:
raise ValidationError(f"object has to be > '{self._m_ll}', but is {obj!r}")
elif self._f_gte and obj < self._m_ll:
raise ValidationError(f"object has to be >='{self._m_ll}', but is {obj!r}")
+ # return the parsed value
return obj
def parse(self, obj: Any) -> Numerical:
diff --git a/tests/test_00_parasite/test_04_number.py b/tests/test_00_parasite/test_04_number.py
index 13ab833..09739c6 100644
--- a/tests/test_00_parasite/test_04_number.py
+++ b/tests/test_00_parasite/test_04_number.py
@@ -62,12 +62,20 @@ def test_number_gt() -> None:
assert p.number().gt(1).parse_safe(1).is_err()
assert p.number().gt(1).parse_safe(0).is_err()
+ assert p.number().integer().gt(1).parse_safe(2) == Ok(2)
+ assert p.number().integer().gt(1).parse_safe(1).is_err()
+ assert p.number().integer().gt(1).parse_safe(0).is_err()
+
def test_number_gte() -> None:
assert p.number().gte(1).parse_safe(2) == Ok(2)
assert p.number().gte(1).parse_safe(1) == Ok(1)
assert p.number().gte(1).parse_safe(0).is_err()
+ assert p.number().integer().gte(1).parse_safe(2) == Ok(2)
+ assert p.number().integer().gte(1).parse_safe(1) == Ok(1)
+ assert p.number().integer().gte(1).parse_safe(0).is_err()
+
def test_number_positive() -> None:
assert p.number().positive().parse_safe(1) == Ok(1)
@@ -92,12 +100,20 @@ def test_number_lt() -> None:
assert p.number().lt(1).parse_safe(1).is_err()
assert p.number().lt(1).parse_safe(2).is_err()
+ assert p.number().integer().lt(1).parse_safe(0) == Ok(0)
+ assert p.number().integer().lt(1).parse_safe(1).is_err()
+ assert p.number().integer().lt(1).parse_safe(2).is_err()
+
def test_number_lte() -> None:
assert p.number().lte(1).parse_safe(0) == Ok(0)
assert p.number().lte(1).parse_safe(1) == Ok(1)
assert p.number().lte(1).parse_safe(2).is_err()
+ assert p.number().integer().lte(1).parse_safe(0) == Ok(0)
+ assert p.number().integer().lte(1).parse_safe(1) == Ok(1)
+ assert p.number().integer().lte(1).parse_safe(2).is_err()
+
def test_number_negative() -> None:
assert p.number().negative().parse_safe(-1) == Ok(-1)