Skip to main content

pychecktype

Documentation Status PyPI

A type-checker which can process recursive types and data

Documents: http://pychecktype.readthedocs.io/en/latest/

Install

pip install pychecktype

Basic Usage

from pychecktype import check_type

check_type({"abc": [1,2,3], "def": {"test": "abc"}}, {"abc": [int], "def": {"test": [str]}})

# Returns: {"abc": [1,2,3], "def": {"test": ["abc"]}}

Highlight

The most intersting thing of this implementation is that it fully support recursive types and data, for example:

from pychecktype import check_type


my_type = []
my_type.append((int, my_type))

# my_type accepts: recursive lists with only sub-list and integers with any depth - even infinite

check_type([], my_type) # []

check_type([1,2,3,[1,2],[1,2,[3,4]]], my_type) # [1,2,3,[1,2],[1,2,[3,4]]]

check_type([1,2,3,[1,2],[1,2,["3",4]]], my_type) # failed

my_obj = []
my_obj.append(my_obj)
my_obj.append(2)
check_type(my_obj, my_type) # [[...], 2]

Rules

This type-checker has some specialized rules suitable for YAML. For example, this type-checker accepts a single value against a list type, and convert the value to [value].

This type-checker uses a slightly simpler and more readable DSL rules than other libraries like typing and trafaret, most of them are Python builtin objects.

The check_type method not only checks that the value is matched with the given type; it returns a corrected version of that object.

Generally:

  1. A Python type matches any object in that type (e.g str, int) except:

  1. str and unicode always match both str and unicode objects both in Python 2 and Python 3

  2. int and long always match both int and long objects both in Python 2 and Python 3

  3. bool objects are never matched with int or long, they are only matched with bool (though bool is a subclass of int)

Specially, object matches any value including None. A helper class NoMatch is provided to do not match any instances, it can be embedded in other types to create assertions.

  1. None matches None only (equivalent to NoneType)

  2. Tuple as a type:

  1. () matches any object EXCEPT None

  2. A tuple of multiple valid types (type1, type2, ...) tries to match the object with each sub-type from left to right. For example, (str, int) matches a str object or an int object; (str, None) matches a str object or None

  1. List as a type:

  1. [] matches any list, or convert the object to a list contains the object

  2. [type] matches a list of items which all match the inner type, or convert an object which matches with the inner type to a list contains it

  3. By default, list types matches both list objects and tuple objects, and convert them to lists. For example, [int] matches (1,2,3) and returns [1,2,3]. Use list_ factory method to create a customized list type which accepts only types that are specified. You may also use it to accept more iterable types e.g. set

  4. By default, list types can convert non-list objects to a list contains only that object, e.g. 1 to [1], {"a":1} to [{"a":1}]. This conversion cannot happen when the object itself is a list/tuple, e.g. [list] cannot match [1], because it is not allowed to be converted to [[1]].

    You may disable the conversion by creating a customized list type with list_ factory method with strict=True

  5. List types return a shallow copy of the input list.

  1. Dist as a type:

  1. {} matches any dict

  2. When dict contains key-value pairs, they become restricts to the input dict:

    1). Keys start with ‘!’ are required keys, and the corresponding value is a type. The value of the specified key in the input dict must match the specified type in the type dict.

    2). Keys start with ‘?’ are optional keys, they are not needed to appear in the input dict, but if they appear they must be matched with the value in the type dict.

    3). Keys start with ‘~’ are regular expressions. For all keys in the input dict that are matched by the regular expression followed by the ‘~’, the corresponding value must match with the specified type. Regular expressions only match the keys that are not required or optional keys.

    4). Other keys are regarded as required keys (as if they are prepended by ‘!’)

    5). Extra keys in the input dict do not affect the match. You may use '~': NoMatch to disable extra keys.

    Examples:

    `{"abc": int}` matches `{"abc": 1}` and `{"abc": 1, "d": 2}` but not `{"d": 2}`
    
    `{"!abc": int}` matches `{"abc": 1}` and `{"abc": 1, "d": 2}` but not `{"d": 2}`
    
    `{"?abc": int}` matches `{"abc": 1}`, `{"abc": 1, "d": 2}` and `{"d": 1}`, but not `{"abc": "a"}`
    
    `{"~a.b": int}` matches `{"acb": 1}` but not `{"facbg": "a"}` because "facbg" is matched by 'a.b'
    
    `{"~a.b": int, "adb": str}` matches `{"adb": "abc"}` but not `{"adb": 1}`
  1. tuple_((type1, type2, type3, ...)) creates a customized type (tuple type) which matches any tuple/list that contains exactly the same number of items, each matches the corresponding sub type.

  2. map_(key_type, value_type) creates a customized type (map type) which matches any dict, in which each key matches the key_type, and each value matches the value_type

  3. extra_ and class_ are advanced customized types, they do customized additional checks for the input object e.g. check against a regular expression etc.

See docstring in pychecktype.py for details.

Python 3 Annotation Checks

You may use pychecktype.checked.checked decorator to check input parameters and return values of a function

from pychecktype.checked import checked
@checked
def f(a: str, b: int)->str:
    """
    check `a` is str, `b` is int, and returns str
    """
    return a + str(b)

@checked
def f2(a, b: int):
    """
    You may check only part of the parameters.
    """
    return str(a) + str(b)

@checked
async def f3(a: str, *args: [int], **kwargs: {'?join': bool})->str:
    """
    Async functions are decorated to async functions

    *args , keyword-only arguments and **kwargs can also be checked
    """
    if kwargs.get('join'):
        return a.join(str(v) for v in args)
    else:
        return a + str(sum(args))

from functools import wraps
def testdecorator(f):
    @wraps
    def _f(*args, **kwargs):
        print("Wrapped")
        return f(*args, **kwargs)

@checked
@testdecorator
def f4(a: int):
    """
    Works well with decorators that are correctly using `functools.wraps`
    and not modifying the argument list
    """
    return a + 1

Metadata

Release files for pychecktype 1.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pychecktype 1.4.1
File Size Uploaded
pychecktype-1.4.1.tar.gz 18.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pychecktype 1.4.1
File Interpreter ABI Platform
pychecktype-1.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 38.9 kB

Release files / pychecktype-1.4.1.tar.gz

Download URL pychecktype-1.4.1.tar.gz
Size 18.4 kB
Tags Source
SHA-256 checksum
How to use checksums
3010d1f9951db1f8d6c39ac5907d7b6142174af3f467d659715252aa703157e4
BLAKE2b-256 checksum
How to use checksums
b1b4b280d07a67a79ce9636c032b1d9aee1701139b0b8e77cf1b4fc3148c8f48
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.29.1 CPython/3.7.2

Release files / pychecktype-1.4.1-py3-none-any.whl

Download URL pychecktype-1.4.1-py3-none-any.whl
Size 20.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
088a9fe69ce45978d5c6426372439e2b4ac9bd3e03efab93ba368682102e1639
BLAKE2b-256 checksum
How to use checksums
685cadd6471f7a079d8ed3fb9531e32b2365a34b42f00f0e01e7903bf7ac1140
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.29.1 CPython/3.7.2

Release history Release notifications | RSS feed

This release

1.4.1 This release

2 release files

1.4.0

8 release files

1.3.0

8 release files

1.2.0

8 release files

1.1

8 release files

1.0

8 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page