schemagic package

Submodules

schemagic.core module

schemagic.core.validate_against_schema(schema, value)

Testing to ensure changes to docs are getting reflected in generated documentation Ensures that the data is valid with the given schema

Parameters:
  • schema

    A data definition. This definition can take any of 5 forms –

    1. function:
    the function will be called fn(data) and expected to return the data, if correct, or throw an error
    e.g. int
    1. map template:
    a dict with one item, where both the key and value are data definitions,
    e.g. {int: [str]}
    1. keyed mapping:
    A map of strings to data definitions,
    e.g. {"name": str, "age": int}
    1. sequence template:
    A one element sequence, where the element is a data definition,
    e.g. [int] or [{str: int}]
    1. strict sequence:
    A sequence of data definitions,
    e.g. [int, {str:int}, [str, int, int], {"age": int}]

    Notable things that do not count as data definitions include primitive data such as strings, integers, or bools. These data could be used as components of data definition, but should not be used alone in places that expect data definitions. For instance ["hello"] is not a valid sequence template, because the element in it is not a data definition.

    I suppose you could also compose custom classes into your data definitions if you wanted. you heathen. ;)

  • value – Any data which will be checked to make sure it matches the prescribed pattern
Returns:

The data after it has been run through its validators.

schemagic.core.validate_keyed_mapping(schema, value)

Ensures all required keys are present, and that their corresponding value matches with the schema’s prescription

Parameters:
  • schema
    A map of strings to data definitions,
    e.g. {"name": str, "age": int}
  • value – Any data which will be checked to make sure it matches the prescribed pattern
Returns:

The data after it has been run through its validators.

schemagic.core.validate_map_template(schema, value)

Ensures all the keys and values of the given data are valid with the schema’s key and value validators

Parameters:
  • schema
    A map template, i.e. a dict with one item, and the key is not a string,
    e.g. {int: str}
  • value – Any data which will be checked to make sure it matches the prescribed pattern
Returns:

The data after it has been run through its validators.

schemagic.core.validate_sequence_template(schema, value)

Ensures each item of the value is of the patterns specified by the schema[‘s first element].

Parameters:
  • schema
    A sequence of one element, and that element is a data definition,
    e.g. [int] or [{str: int}]
  • value – Any data which will be checked to make sure it matches the prescribed pattern
Returns:

The data after it has been run through its validators.

schemagic.core.validate_strict_sequence(schema, value)

Ensures that the elements of the value are in the same order and valid with the same definitions in the schema.

Parameters:
  • schema
    A sequence of data definitions,
    e.g. [int, {str:int}, [str, int, int], {"age": int}]
  • value – Any data which will be checked to make sure it matches the prescribed pattern
Returns:

The data after it has been run through its validators.

schemagic.core.validator(schema, subject_name_str, validation_predicate=None, coerce_data=False, data=None)

Creates a validation function which conditionally applies validation and coercion to data

Parameters:
  • schema – a data definition as described in the function validate_against_schema
  • subject_name_str

    a string which will be passed into the error message if validation fails. an example of an error message with subject_name_str="My Business Type"

    ValueError: Bad value provided for My Business Type. - error: <some error> schema: <the schema> value: <the val>
    
  • validation_predicate – a function that takes no arguments and returns a boolean. This will be called before validation occurs. If it returns False, validation will be skipped.
  • coerce_data

    True or False - indicates whether the validator should return the output of applying validate_against_schema to the data, or simply return the original data. NOTE: if your validator applies functions that mutate their inputs, the data may be altered regardless of the

    value of this parameter. Mutable state. Not even once.
  • data – The data which will ultimately be passed into the validator.
Returns:

  • when data is not supplied - returns a validator function (i.e. it returns a copy of validator with all arguments supplied except data)
  • when data is supplied: returns data (possibly modified, depending on the value of coerce_data) if the data is valid with the given schema, else throws a ValueError.

schemagic.func module

NOTE EVERYTHING IN THIS FILE IS EXPERIMENTAL. DO NOT EXPECT STABILITY OR USABILITY IN CURRENT FORM

schemagic.func.ALWAYS()
schemagic.func.IDENTITY(x)
schemagic.func.WHEN_DEBUGGING()
schemagic.func.validate_function_input(input_validator, arg_list, kwarg_dict)
schemagic.func.validated(validation_predicate=None, coerce_data=True, input_schema=None, output_schema=None, fn=None)

schemagic.utils module

schemagic.utils.assert_raises(*args, **kwds)
schemagic.utils.is_string(obj)
schemagic.utils.merge_with(fn, a, b)

returns a new dictionary that is the merger of a and b. applies fn to the values of colliding keys.

>>> merge_with(operator.add, {"a": 1}, {"a": 1, "b": 1})
{'a': 2, 'b': 1}
schemagic.utils.multiple_dispatch_fn(dispatch_map, default=None)

creates a multiple dispatch function.

returns a function whose implementation of the function is based on the arguments passed to it. it decides what implementation to use by testing the arguments against a series of predicates to detect what situation is applicable.

For example,

>>> add_if_ints_multiply_if_floats = multiple_dispatch_fn(
... {lambda *nums: all(isinstance(num, int) for num in nums): operator.add,
...  lambda *nums: all(isinstance(num, float) for num in nums): operator.mul})
>>> add_if_ints_multiply_if_floats(10, 10)
20
>>> add_if_ints_multiply_if_floats(10.0, 10.0)
100.0

You can also provide a default implementation to use if none of the predicates match. For example,

>>> add_if_ints_else_return_unmodified = multiple_dispatch_fn(
... {lambda *nums: all(isinstance(num, int) for num in nums): operator.add},
...  default=lambda *items: items)
>>> add_if_ints_else_return_unmodified(25, 25)
50
>>> add_if_ints_else_return_unmodified("hello", None)
('hello', None)
Parameters:
  • dispatch_map – mapping {predicate_fn: implementation_fn}
  • default – implementation fn to be used if none of the predicates are satisfied
Returns:

schemagic.utils.remove_key(dict_, key)
schemagic.utils.separate_dict(initial_dict, *keys_to_remove)

returns 2 new dicts, one with some keys removed, and another with only those keys

schemagic.validators module

schemagic.validators.enum(*possible_vals)
schemagic.validators.formatted_string(str_format, **kwargs)
schemagic.validators.or_(*schemata)
schemagic.validators.predicate_validator(predicate, name=None, coercer=None, message=None, data=None)

Builds new validator function that tests, and optionally coerces, data against the supplied predicate and coercer

Parameters:
  • predicate – function that accepts one argument, the data, returns true if data is good, false otherwise.
  • name – name of the supplied predicate. useful when building validators from anonymous functions.
  • coercer – a function that accepts the data and returns a modification of that data. If no coercer is provided, the data will still be subject to any coercions that occur within the validation. This is to allow for additional flexibility, for instance, you may want to convert a datetime string into a datatime object before validating it.
  • message – A message that described the problem with the data if it wasn’t validated correctly. This message will be automatically suffixed with a printout of the data recieved by the validator. If message is not provided, a default message is used that references the predicate by name.
  • data – the data to be validated
Returns:

if data is not supplied, returns a copy of the predicate validator function with all the other

values “filled in”. i.e. it returns a curried function.

If the data is supplied, returns the, possibly transformed, data if it is valid, else throws an error.

schemagic.web module

schemagic.web.dispatch_to_fn(fn, args)
Dispatches a json object to a function. The way the data is applied depends on the structure of the data.
  • if the data is a sequence, it will unpack it and pass each item into the function, i.e. it will use *args
  • if the data is a mapping, it will unpack it and pass in the items as keywords, i.e. it will use **kwargs
  • if the data is anything else (i.e. it is a primitive, non iterable), it will pass it in directly.
NOTE
an important “gotcha” of this implementation is that a function that expects a single, iterable object will have to have its argument passed to it by keyword. This causes a lot builtin functions in earlier versions of python to be ineligible for this kind of dispatch. For instance, the sum function in 2.7 takes a single iterable argument, and that argument can not be passed by keyword. as such, this function can not be used to dispatch json to the sum function in 2.7
Parameters:
  • fn – the function which is to recieve the values from the arg data
  • args – a data structure (usually rehydrated json) that is to be applied piecemeal to the function. see rules presented above.
schemagic.web.service_registry(service, validation_pred=None, coerce_data=True, *service_definitions)

Registers all the service descriptions provided on the app specified by the service parameter.

Parameters:
  • service – Service to register functions on. see description of same parameter in service_route documentation.
  • validation_pred – function returning boolean. see description of same parameter in service_route documentation.
  • coerce_data – boolean. see description of same parameter in service_route documentation.
  • service_definitions – mappings that contain the keyword args to service_route.
Returns:

if service definitions not provided, returns the a function that accepts service definitions. if service definitions provided, returns nothing.

schemagic.web.service_route(service, validation_pred=None, coerce_data=True, rule=None, input_schema=None, output_schema=None, fn=None)

Function decorator that registers a webservice_fn version of the function on the provided service.

Note that this function is used primarily to register functions en masse with the service_registry interface. However, it can be used as a traditional decorator if desired. e.g.:

I find there to be 2 important pitfalls to bear in mind if using the decorator this way: 1. This makes it seem like the function is being somehow modified, which it is not.

It can confuse people reading your code into thinking they have to make separate, dedicated webservice versions of the function in order to register them.
  1. It becomes unsafe to use positional arguments when using the decorator like this. If I had defined that decorator using the canonical flask pattern, e.g. @my_service_route("/this-route") it would have caused everything to explode. To get consistent behavior, you MUST specify the arguments by keyword.
Parameters:
  • service – The service or app which is to have the rule added to it. Must support the add_url_rule interface as described in the flask documentation.
  • validation_pred – see description in validator fn of the same param. function that returns true or false The default value for validation on webservice routes is to use the value of __debug__ as a guide.
  • coerce_data – see description in validator fn of the same param. boolean flag for coercing data. The default is to coerce data. This is often very helpful in parsing json from a web request.
  • rule – the url route to use when accessing this function
  • input_schema – a data definition as described in the validate_against_schema fn documentation. This value is not required. If none is given, no validation will be done on the input.
  • output_schema – a data definition as decribed in the validate_against_schema fn documentation. This value is not required. If none is given, no validation will be done on the output.
  • fn – The function intended to implement the request.
Returns:

the original function, unmodified.

schemagic.web.webservice_fn(fn, input_validator, output_validator)

Handles the minutia of pulling data from the request object and passing it into the function and validators

Parameters:
  • fn – the function which is supposed to fulfill the contract defined by the input and output schemata
  • input_validator – a validator as described in the core function of the same name
  • output_validator – a validator as described in the core function of the same name
Returns:

a json Flask Response that contains either the requested data or an error.

Module contents