File: __init__.py

package info (click to toggle)
python-typechecks 0.1.0%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 92 kB
  • sloc: python: 133; makefile: 11
file content (109 lines) | stat: -rw-r--r-- 3,859 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""
Routines for testing or asserting that a value is certain type, in a way that
works in both Python 2.7 and Python 3.4.
"""
from __future__ import print_function, division, absolute_import

# In Python 3, the "unicode" and "long" types went away.
string_types = (str,)  # Python 2 and 3.
try:
    string_types += (unicode,)  # Python 2.
except NameError:
    pass  # Python 3.

integer_types = (int,)  # Python 2 and 3.
try:
    integer_types += (long,)  # Python 2.
except NameError:
    pass  # Python 3.

def is_string(obj):
    """
    Is the object a string?
    """
    return isinstance(obj, string_types)

def is_integer(obj):
    """
    Is the object an integer?
    """
    return isinstance(obj, integer_types)

def require_string(obj, name=None, nonempty=False):
    """
    Raise an exception if the obj is not of type str or unicode.

    If name is provided it is used in the exception message.

    If nonempty=True, then an exception is raised if the object is the empty
    string.
    """
    require_instance(obj, string_types, name, "string")
    if nonempty and not obj:
        raise ValueError(
            (("%s: " % name) if name else "") +
            "string must be nonempty.")

def require_integer(obj, name=None):
    """
    Raise an exception if the obj is not of type int or long.

    If name is provided it is used in the exception message.

    If nonzero=True, then an exception is raised if the integer is 0.

    If positive=True, then an exception is raised if the integer is < 1.
    """
    require_instance(obj, integer_types, name, "integer")

def require_instance(obj, types=None, name=None, type_name=None, truncate_at=80):
    """
    Raise an exception if obj is not an instance of one of the specified types.

    Similarly to isinstance, 'types' may be either a single type or a tuple of
    types.

    If name or type_name is provided, it is used in the exception message.
    The object's string representation is also included in the message,
    truncated to 'truncate_at' number of characters.
    """
    if not isinstance(obj, types):
        obj_string = str(obj)
        if len(obj_string) > truncate_at:
            obj_string = obj_string[:truncate_at - 3] + "..."
        if type_name is None:
            try:
                type_name = "one of " + ", ".join(str(t) for t in types)
            except TypeError:
                type_name = str(types)
        name_string = ("%s: " % name) if name else ""
        error_message = "%sexpected %s. Got: '%s' of type '%s'" % (
            name_string, type_name, obj_string, type(obj))
        raise TypeError(error_message)

def require_iterable_of(objs, types, name=None, type_name=None, truncate_at=80):
    """
    Raise an exception if objs is not an iterable with each element an instance
    of one of the specified types.

    See `require_instance` for descriptions of the other parameters.
    """
    # Fast pass for common case where all types are correct.
    # This avoids the more expensive loop below. A typical speedup from this
    # optimization is 6.6 sec -> 1.7 sec, for testing a list of size 10,000,000.
    try:
        if all(isinstance(obj, types) for obj in objs):
            return
    except TypeError:
        # We don't require that objs is a list in this function, just that it's
        # iterable. We specify 'list' below as a convenient way to throw the
        # desired error.
        require_instance(objs, list, name, "iterable", truncate_at)

    # Some type isn't correct. We reuse the require_instance function to raise
    # the exception.
    prefix = ("%s: " % name) if name else ""
    for (i, obj) in enumerate(objs):
        element_name = prefix + ("element at index %d" % i)
        require_instance(obj, types, element_name, type_name, truncate_at)
    assert False, "Shouldn't reach here."