Skip to content
Permalink
Browse files

Info.py: Validate value with type signature

Adds functionality to pass complete type_signature as
value_type to validate the values stored in the ``Info`` class.
This provides more flexiblity in defining and restricting the values
that can be stored inside an instance of Info class.

Related to #101
  • Loading branch information...
satwikkansal committed Jun 19, 2017
1 parent b9e9746 commit 7a3a8d3f24d75fe4c196d03329d1ca6111e85a81
@@ -1,7 +1,10 @@
from coala_quickstart.info_extraction.Utilities import assert_type_signature


class Info:
description = 'Some information'

# tuple of allowed types for the information value.
# type signature for the information value.
value_type = (object,)

def __init__(self,
@@ -18,9 +21,7 @@ def __init__(self,
if not self.value_type:
self.value_type = (object,)

if not isinstance(value, self.value_type):
raise TypeError("The value {} does not match the allowed "
"value types {}".format(value, self.value_type))
assert_type_signature(value, self.value_type, "value")
self.source = source
self._value = value
self.extractor = extractor
@@ -0,0 +1,43 @@
def assert_type_signature(value, type_signature, argname):
"""
Validates the value with the type_signature recursively. The type
signature is either a single type object, or a collection of type
objects or allowed values or type signatures.
>>> assert_type_signature(3, int, "var")
True
>>> assert_type_signature(3, (3,), "var")
True
>>> assert_type_signature([3,4], ([int],), "var")
True
>>> assert_type_signature([3.0 ,4], ([int, float],), "var")
True
>>> assert_type_signature([3,4], ([1, 2, 3, 4],), "var")
True
>>> assert_type_signature(["foo", 420], [[str, int]], "var")
True
>>> assert_type_signature("tab", {"tab", "space"}, "var")
True
:param value: Object to be validated against ``type_signature``.
:param type_signature: Object that describes allowed types and values for
the ``value``.
"""
iterables = (tuple, list, set)
if isinstance(type_signature, type):
type_signature = (type_signature,)
else:
if not isinstance(type_signature, iterables):
raise TypeError("type_signature must be an Iterable or a type "
"object. Provided value: {}".format(
type_signature))
for typ in type_signature:
if value == typ or (isinstance(typ, type) and isinstance(value, typ)):
return True
elif isinstance(value, iterables) and isinstance(value, type(typ)):
for v in value:
assert_type_signature(v, typ, argname)
return True

raise TypeError("{} must be an instance of one of {} (provided value: "
"{})".format(argname, type_signature, repr(value)))
@@ -56,7 +56,8 @@ def test_derived_instances(self):
def test_value_type(self):
with self.assertRaisesRegexp(
TypeError,
'The value 5.5 does not match the allowed value types'):
"value must be an instance of one of "
"\(<class 'str'>, <class 'int'>\) \(provided value: 5.5\)"):
self.InfoA("source_file", 5.5)

self.InfoB("source_file", 5.5)

0 comments on commit 7a3a8d3

Please sign in to comment.
You can’t perform that action at this time.