Python combination
Project description
PyComb
Tcomb port for Python 3. It provides a means to apply runtime type checking.
Installation
pip install pycomb
Basic examples
from pycomb import combinators # A simple string MyStringType = combinators.String s1 = combinators.String('hello') # This IS a 'str' object s2 = combinators.String(10) # This will fail # A list that contains only strings ListOfStrings = combinators.list(combinators.String) l1 = ListOfStrings(['1', '2', '3']) # This IS a native tuple l1 = ListOfStrings(['1', '2', 3]) # This will fail # Structured data User = combinators.struct( { 'name': combinators.String, 'age': combinators.Int, 'city': combinators.maybe(combinators.String) } ) my_user = User({'name': 'John Burns', 'age': 30}) # This IS a dict my_user2 = User({'name': 'John Burns', 'age': '30'}) # This will fail my_user3 = User({'name': 'John Burns', 'age': 30, 'city': 'New York'}) # This IS a dict # Subtypes SmallString = combinators.subtype( combinators.String, lambda d: len(d) <= 10) # Strings shorter than 11 characters SmallString('12345678901') # This will fail SmallString('12345') # This IS a 'str' object # Constants john_data = {'name': 'John'} John = combinators.constant(john_data, name='JohnConstant') John({'name': 'John'}) John({'name': 'Jack'}) # Error on JohnConstant: expected JohnConstant but was dict # Regexp with groups import re def name_condition(d): return d in ('John', 'Jack') def age_condition(d): return int(d) > 0 Name = combinators.subtype(combinators.String, name_condition, name='Name') Age = combinators.subtype(combinators.String, age_condition, name='Age') NameAndAge = combinators.regexp_group('(\w+) +(-?[0-9]+)', Name, Age, name='NameAndAge') NameAndAge('John 32') # Ok NameAndAge('John 3x') # Error on NameAndAge: expected NameAndAge but was str NameAndAge('John -32') # Error on NameAndAge[1]: expected Age but was str NameAndAge('WRONG 32') # Error on NameAndAge[0]: expected Name but was str
Validation context
The validation procedure runs within a context that controls:
- The behavior in case of error
- The production mode: if active, no such error is raised during validation
Context Examples
from pycomb import combinators, context # Example of production mode ListOfNumbers = combinators.list(combinators.Number, 'ListOfNumbers') production_ctx = context.create(production_mode=True) numbers = ListOfNumbers([1, 2, 'hello'], ctx=production_ctx) # This will NOT fail # Example of custom behavior in case of error class MyObserver(context.ValidationErrorObserver): def on_error(self, ctx, expected_type, found_type): print('Expected {}, got {}'.format(expected_type, found_type)) ListOfNumbers = combinators.list(combinators.Number, 'ListOfNumbers') notification_ctx = context.create(validation_error_observer=MyObserver()) numbers = ListOfNumbers([1, 2, 'hello'], ctx=production_ctx) # This will NOT fail # Expected output: # > Expected Int or Float, got <class 'str'>
Decorators
It is possible to wrap functions in order to protect the input parameters, or ensure the type of its return value
Decorators example
from pycomb import combinators # Example of input parameters check @combinators.function( combinators.String, combinators.Int, c=combinators.Float, d=combinators.list(combinators.Int)) def f(a, b, c=None, d=None): pass f('John', 1, c=1.0, d=[3, 4]) # OK f(1, 1, c=1.0, d=[3, 4]) # This will fail # Example of output check @returning(cmb.subtype(cmb.String, lambda d: len(d) < 10)) def f(n): return ' ' * n f(3) # OK f(10) # This will fail
More types are supported, such as:
- Unions
- Intersections
- Functions
- Enums
- …
All the base types have a default example field. Please read the test code to find more examples.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
pycomb-0.1.18.tar.gz
(16.2 kB
view hashes)