diff --git a/CHANGELOG.md b/CHANGELOG.md index ca311cc..b9ac3ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Changelog ========= +3.5.0 +----- +- [feature] add `NUMBER` that accepts float and integer + + 3.4.1 ----- - Fix `dsv` decorator to work with `DSVError`. diff --git a/README.md b/README.md index af3d7cb..7b8019d 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,9 @@ validate_data_spec(multirow_data, SingleSpec, multirow=True) # return True ### FLOAT `float_field = Checker([FLOAT])` or `Checker([float])` +### NUMBER +`number_field = Checker([NUMBER])` + ### STR `str_field = Checker([STR])` or `Checker([str])` diff --git a/data_spec_validator/__version__.py b/data_spec_validator/__version__.py index da4564d..01bd03c 100644 --- a/data_spec_validator/__version__.py +++ b/data_spec_validator/__version__.py @@ -1 +1 @@ -__version__ = '3.4.1' +__version__ = '3.5.0' diff --git a/data_spec_validator/spec/__init__.py b/data_spec_validator/spec/__init__.py index a72d09b..55fb432 100644 --- a/data_spec_validator/spec/__init__.py +++ b/data_spec_validator/spec/__init__.py @@ -25,6 +25,7 @@ LIST, LIST_OF, NONE, + NUMBER, ONE_OF, REGEX, SELF, @@ -66,6 +67,7 @@ "LIST", "LIST_OF", "NONE", + "NUMBER", "ONE_OF", "REGEX", "SELF", diff --git a/data_spec_validator/spec/checks.py b/data_spec_validator/spec/checks.py index ca29f45..c7000f0 100644 --- a/data_spec_validator/spec/checks.py +++ b/data_spec_validator/spec/checks.py @@ -28,6 +28,7 @@ LIST, LIST_OF, NONE, + NUMBER, ONE_OF, RAW_CHECK_TYPE, REGEX, @@ -68,6 +69,7 @@ def _get_default_check_2_validator_map() -> Dict[str, BaseValidator]: ListOfValidator, ListValidator, NoneValidator, + NumberValidator, OneOfValidator, RegexValidator, SpecValidator, @@ -79,6 +81,7 @@ def _get_default_check_2_validator_map() -> Dict[str, BaseValidator]: return { INT: IntValidator(), FLOAT: FloatValidator(), + NUMBER: NumberValidator(), STR: StrValidator(), DIGIT_STR: DigitStrValidator(), BOOL: BoolValidator(), diff --git a/data_spec_validator/spec/defines.py b/data_spec_validator/spec/defines.py index ffd0dc4..7630c25 100644 --- a/data_spec_validator/spec/defines.py +++ b/data_spec_validator/spec/defines.py @@ -6,6 +6,7 @@ NONE = 'none' INT = 'int' FLOAT = 'float' +NUMBER = 'number' DIGIT_STR = 'digit_str' # URL params cannot distinguish from strings and numbers STR = 'str' BOOL = 'bool' diff --git a/data_spec_validator/spec/validators.py b/data_spec_validator/spec/validators.py index 1e5eb55..46ebccc 100644 --- a/data_spec_validator/spec/validators.py +++ b/data_spec_validator/spec/validators.py @@ -34,6 +34,7 @@ LIST, LIST_OF, NONE, + NUMBER, ONE_OF, REGEX, SPEC, @@ -216,6 +217,16 @@ def validate(value, extra, data): return ok, info +class NumberValidator(BaseValidator): + name = NUMBER + + @staticmethod + def validate(value, extra, data): + ok = type(value) is float or type(value) is int + info = '' if ok else TypeError(f'{repr(value)} is not a number') + return ok, info + + class StrValidator(BaseValidator): name = STR diff --git a/test/test_spec.py b/test/test_spec.py index 726948d..cd906d2 100644 --- a/test/test_spec.py +++ b/test/test_spec.py @@ -26,6 +26,7 @@ LIST, LIST_OF, NONE, + NUMBER, ONE_OF, REGEX, SELF, @@ -67,6 +68,19 @@ class FloatSpec: nok_data = dict(float_field=3) assert is_something_error(TypeError, validate_data_spec, nok_data, FloatSpec) + def test_number(self): + class NumberSpec: + number_field = Checker([NUMBER]) + + ok_data = dict(number_field=3.0) + assert validate_data_spec(ok_data, NumberSpec) + + ok_data = dict(number_field=3) + assert validate_data_spec(ok_data, NumberSpec) + + nok_data = dict(number_field='3.0') + assert is_something_error(TypeError, validate_data_spec, nok_data, NumberSpec) + def test_str(self): class StrSpec: str_field = Checker([STR])