Skip to content

Commit 633d86d

Browse files
author
Sylvain MARIE
committed
assert_instance_of and assert_subclass_of (used in the validate inline entry point) fixed so as to support Enum types. Fixed #28. **Important**: only tuple are now supported when several types are provided in validate's instance_of and subclass_of arguments. This is to has a closer behaviour to the python stdlib.
1 parent b46837d commit 633d86d

4 files changed

Lines changed: 31 additions & 30 deletions

File tree

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ install:
3131
if [ "${TRAVIS_PYTHON_VERSION}" = "2.7" ]; then
3232
echo "No need to install enforce pytypes checktypes BUT need to install future"
3333
pip install future
34+
pip install enum34
3435
else
3536
pip install autoclass
3637
pip install enforce

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# *************** Dependencies *********
1414
INSTALL_REQUIRES = ['makefun', 'future;python_version<"3.3"', 'funcsigs;python_version<"3.3"', 'decopatch'] # 'typing_inspect' is now copied internally so as to be compliant with very old versions of typing module
1515
DEPENDENCY_LINKS = []
16-
SETUP_REQUIRES = ['pytest-runner', 'setuptools_scm', 'pypandoc', 'pandoc']
16+
SETUP_REQUIRES = ['pytest-runner', 'setuptools_scm', 'pypandoc', 'pandoc', 'enum34;python_version<"3.4"']
1717
TESTS_REQUIRE = ['pytest', 'pytest-logging', 'pytest-cov', 'enforce', 'mini_lambda', 'attrs', 'numpy', 'autoclass',
1818
'checktypes', 'pytest-cases']
1919
EXTRAS_REQUIRE = {}

valid8/entry_points_inline.py

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import sys
2+
from inspect import isclass
23
from warnings import warn
34

45
from linecache import getline
@@ -12,7 +13,7 @@
1213

1314
try: # python 3.5+
1415
# noinspection PyUnresolvedReferences
15-
from typing import Any, Union, Set, Iterable, Callable, Container
16+
from typing import Any, Union, Set, Iterable, Callable, Container, Tuple
1617
try: # python 3.5.3-
1718
from typing import Type
1819
except ImportError:
@@ -22,7 +23,7 @@
2223

2324

2425
def assert_instance_of(value,
25-
allowed_types # type: Union[type, Iterable[type]]
26+
allowed_types # type: Union[Type, Tuple[Type]]
2627
):
2728
"""
2829
An inlined version of instance_of(var_types)(value) without 'return True': it does not return anything in case of
@@ -31,16 +32,10 @@ def assert_instance_of(value,
3132
Used in validate and validation/validator
3233
3334
:param value: the value to check
34-
:param allowed_types: the type(s) to enforce. If a set of types is provided it is considered alternate types: one
35+
:param allowed_types: the type(s) to enforce. If a tuple of types is provided it is considered alternate types: one
3536
match is enough to succeed. If None, type will not be enforced
3637
:return:
3738
"""
38-
try:
39-
# isinstance does not allow anything else than tuples when several are provided
40-
allowed_types = tuple(allowed_types)
41-
except TypeError:
42-
pass
43-
4439
if not isinstance(value, allowed_types):
4540
try:
4641
# more than 1 ?
@@ -57,7 +52,7 @@ def assert_instance_of(value,
5752

5853

5954
def assert_subclass_of(typ,
60-
allowed_types # type: Union[type, Iterable[type]]
55+
allowed_types # type: Union[Type, Tuple[Type]]
6156
):
6257
"""
6358
An inlined version of subclass_of(var_types)(value) without 'return True': it does not return anything in case of
@@ -66,16 +61,10 @@ def assert_subclass_of(typ,
6661
Used in validate and validation/validator
6762
6863
:param typ: the type to check
69-
:param allowed_types: the type(s) to enforce. If a set of types is provided it is considered alternate types:
64+
:param allowed_types: the type(s) to enforce. If a tuple of types is provided it is considered alternate types:
7065
one match is enough to succeed. If None, type will not be enforced
7166
:return:
7267
"""
73-
try:
74-
# issubclass does not allow anything else than tuples when several are provided
75-
allowed_types = tuple(allowed_types)
76-
except TypeError:
77-
pass
78-
7968
if not issubclass(typ, allowed_types):
8069
try:
8170
# more than 1 ?
@@ -137,8 +126,8 @@ def validate(name, # type: str
137126
value, # type: Any
138127
enforce_not_none=True, # type: bool
139128
equals=None, # type: Any
140-
instance_of=None, # type: Union[type, Iterable[type]]
141-
subclass_of=None, # type: Union[type, Iterable[type]]
129+
instance_of=None, # type: Union[Type, Tuple[Type]]
130+
subclass_of=None, # type: Union[Type, Tuple[Type]]
142131
is_in=None, # type: Container
143132
subset_of=None, # type: Set
144133
contains = None, # type: Union[Any, Iterable]
@@ -172,9 +161,9 @@ def validate(name, # type: str
172161
:param value: the value to check
173162
:param enforce_not_none: boolean, default True. Whether to enforce that `value` is not None.
174163
:param equals: an optional value to enforce.
175-
:param instance_of: optional type(s) to enforce. If a set of types is provided it is considered alternate types: one
164+
:param instance_of: optional type(s) to enforce. If a tuple of types is provided it is considered alternate types: one
176165
match is enough to succeed. If None, type will not be enforced
177-
:param subclass_of: optional type(s) to enforce. If a set of types is provided it is considered alternate types: one
166+
:param subclass_of: optional type(s) to enforce. If a tuple of types is provided it is considered alternate types: one
178167
match is enough to succeed. If None, type will not be enforced
179168
:param is_in: an optional set of allowed values.
180169
:param subset_of: an optional superset for the variable
@@ -381,8 +370,8 @@ class validator(Validator):
381370
def __init__(self,
382371
name, # type: str
383372
value, # type: Any
384-
instance_of=None, # type: Union[type, Iterable[type]]
385-
subclass_of=None, # type: Union[type, Iterable[type]]
373+
instance_of=None, # type: Union[Type, Tuple[Type]]
374+
subclass_of=None, # type: Union[Type, Tuple[Type]]
386375
error_type=None, # type: Type[ValidationError]
387376
help_msg=None, # type: str
388377
**kw_context_args):
@@ -400,9 +389,9 @@ def __init__(self,
400389
401390
:param name: the name of the variable being validated
402391
:param value: the value being validated
403-
:param instance_of: the type(s) to enforce. If a set of types is provided it is considered alternate types:
392+
:param instance_of: the type(s) to enforce. If a tuple of types is provided it is considered alternate types:
404393
one match is enough to succeed. If None, type will not be enforced
405-
:param subclass_of: the type(s) to enforce. If a set of types is provided it is considered alternate types: one
394+
:param subclass_of: the type(s) to enforce. If a tuple of types is provided it is considered alternate types: one
406395
match is enough to succeed. If None, type will not be enforced
407396
:param error_type: a subclass of `ValidationError` to raise in case of validation failure. By default a
408397
`ValidationError` will be raised with the provided `help_msg`

valid8/tests/test_entry_points_inline.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ def test_validate_():
1616
# nominal
1717
surf = 2
1818
validate('surface', surf, instance_of=int, min_value=0)
19-
validate('surface', surf, instance_of=[int], min_value=0)
20-
validate('surface', surf, instance_of={int, str}, min_value=0)
21-
validate('surface', surf, instance_of=(t for t in {int, str}), min_value=0)
19+
validate('surface', surf, instance_of=(int, ), min_value=0)
20+
validate('surface', surf, instance_of=(int, str), min_value=0)
2221

2322
# error wrong value
2423
surf = -1
@@ -31,7 +30,8 @@ def test_validate_():
3130
# error wrong type
3231
surf = 1j
3332
with pytest.raises(ValidationError) as exc_info:
34-
validate('surface', surf, instance_of=(t for t in {int}), min_value=0)
33+
# note: we use a length-1 tuple on purpose to see if the error msg takes length into account
34+
validate('surface', surf, instance_of=(int, ), min_value=0)
3535
e = exc_info.value
3636
assert str(e) == "Error validating [surface=1j]. " \
3737
"HasWrongType: Value should be an instance of %s. Wrong value: [1j]." % repr(int)
@@ -236,3 +236,14 @@ def test_function_setter_name_in_valid8_error_message():
236236

237237
from ._test_pep484 import test_function_setter_name_in_valid8_error_message
238238
test_function_setter_name_in_valid8_error_message()
239+
240+
241+
def test_enum_isinstance():
242+
"""Tests that enum can be used in validate/instance_of"""
243+
from enum import Enum
244+
245+
class MyEnum(Enum):
246+
a = 1
247+
b = 2
248+
249+
validate('a', MyEnum.a, instance_of=MyEnum)

0 commit comments

Comments
 (0)