API

Converters

biryani

Biryani package

This root module is kept nearly empty to allow client applications to import only the converters they need, module by module.

biryani.custom_conv(*modules)[source]

Import given conversion modules and return a module-like object containing their aggregated content.

How to use:

import biryani
import biryani.baseconv
import biryani.datetimeconv
import any.custom.module
conv = biryani.custom_conv(biryani.baseconv, biryani.datetimeconv, any.custom.module)
>>> import biryani.baseconv
>>> import biryani.datetimeconv
>>> conv = custom_conv(biryani.baseconv, biryani.datetimeconv)
>>> conv.input_to_int(u'42') # input_to_int is defined in baseconv module.
(42, None)
>>> conv.iso8601_input_to_date(u'1789-07-14') # iso8601_input_to_date is defined in datetimeconv module.
(datetime.date(1789, 7, 14), None)

biryani.baseconv

Base Conversion Functions

Note

Most converters do only one operation and can fail when given wrong data. To ensure that they don’t fail, they must be combined with other converters.

Note

Most converters work on unicode strings. To use them you must first convert your strings to unicode. By using converter decode_str(), for example.

biryani.baseconv.anything_to_bool(value, state=None)

Convert any Python data to a boolean.

Warning

Like most converters, a None value is not converted.

When you want None to be converted to False, use:

pipe(anything_to_bool, default(False))
>>> anything_to_bool(0)
(False, None)
>>> anything_to_bool(-1)
(True, None)
>>> anything_to_bool(u'0')
(True, None)
>>> anything_to_bool(u'1')
(True, None)
>>> anything_to_bool(u'true')
(True, None)
>>> anything_to_bool(u'false')
(True, None)
>>> anything_to_bool(u'  0  ')
(True, None)
>>> anything_to_bool(u'    ')
(True, None)
>>> anything_to_bool(None)
(None, None)
biryani.baseconv.anything_to_float(value, state=None)[source]

Convert any python data to a float.

Warning

Like most converters, a None value is not converted.

>>> anything_to_float(42)
(42.0, None)
>>> anything_to_float('42')
(42.0, None)
>>> anything_to_float(u'42')
(42.0, None)
>>> anything_to_float(42.75)
(42.75, None)
>>> anything_to_float(None)
(None, None)
biryani.baseconv.anything_to_int(value, state=None)[source]

Convert any python data to an integer.

Warning

Like most converters, a None value is not converted.

>>> anything_to_int(42)
(42, None)
>>> anything_to_int('42')
(42, None)
>>> anything_to_int(u'42')
(42, None)
>>> anything_to_int(42.75)
(42, None)
>>> anything_to_int(u'42.75')
(42, None)
>>> anything_to_int(u'42,75')
(u'42,75', u'Value must be an integer')
>>> anything_to_int(None)
(None, None)
biryani.baseconv.anything_to_str(value, state=None)[source]

Convert any Python data to unicode.

Warning

Like most converters, a None value is not converted.

>>> anything_to_str(42)
(u'42', None)
>>> anything_to_str('42')
(u'42', None)
>>> anything_to_str(None)
(None, None)
biryani.baseconv.bool_to_str(value, state=None)[source]

Convert a boolean to a “0” or “1” string.

Warning

Like most converters, a None value is not converted.

When you want None to be converted to "0", use:

pipe(bool_to_str, default(u'0'))
>>> bool_to_str(False)
(u'0', None)
>>> bool_to_str(True)
(u'1', None)
>>> bool_to_str(0)
(u'0', None)
>>> bool_to_str('')
(u'0', None)
>>> bool_to_str('any non-empty string')
(u'1', None)
>>> bool_to_str('0')
(u'1', None)
>>> bool_to_str(None)
(None, None)
>>> pipe(default(False), bool_to_str)(None)
(u'0', None)
biryani.baseconv.catch_error(converter, error_value=None)[source]

Make a converter that calls another converter and ignore its errors.

>>> catch_error(noop)(42)
(42, None)
>>> catch_error(fail())(42)
(None, None)
>>> catch_error(noop, error_value = 0)(42)
(42, None)
>>> catch_error(fail(), error_value = 0)(42)
(0, None)
biryani.baseconv.check(converter_or_value_and_error, clear_on_error=False)[source]

Check a conversion and either return its value or raise a ValueError exception.

This function can be called with either a converter or the result of a conversion.

Usage with a converter:

>>> check(input_to_int)(u'42')
42
>>> check(input_to_int)(u'hello world')
Traceback (most recent call last):
ValueError:
>>> check(pipe(anything_to_str, test_isinstance(unicode), input_to_bool))(42)
True
>>> check(input_to_int, clear_on_error = True)(u'42')
42
>>> print check(input_to_int, clear_on_error = True)(u'hello world')
None
Traceback (most recent call last):
ValueError:

Usage with a conversion result :

>>> check(input_to_int(u'42'))
42
>>> check(input_to_int(u'hello world'))
Traceback (most recent call last):
ValueError:
>>> check(pipe(anything_to_str, test_isinstance(unicode), input_to_bool)(42))
True
>>> check(input_to_int(u'42'), clear_on_error = True)
42
>>> print check(input_to_int(u'hello world'), clear_on_error = True)
None
Traceback (most recent call last):
ValueError:
biryani.baseconv.cleanup_line(*args, **kwargs)

Strip spaces from a string and remove it when empty.

>>> cleanup_line(u'   Hello world!   ')
(u'Hello world!', None)
>>> cleanup_line('   ')
(None, None)
>>> cleanup_line(None)
(None, None)
biryani.baseconv.cleanup_text(*args, **kwargs)

Replaces CR + LF or CR to LF in a string, then strip spaces and remove it when empty.

>>> cleanup_text(u'   Hello\r\n world!\r   ')
(u'Hello\n world!', None)
>>> cleanup_text('   ')
(None, None)
>>> cleanup_text(None)
(None, None)
biryani.baseconv.condition(test_converter, ok_converter, error_converter=None)[source]

When test_converter succeeds (ie no error), then apply ok_converter, otherwise apply error_converter.

Note

See also first_match().

>>> detect_unknown_values = condition(
...     test_in(['?', 'x']),
...     set_value(False),
...     set_value(True),
...     )
>>> detect_unknown_values(u'Hello world!')
(True, None)
>>> detect_unknown_values(u'?')
(False, None)
biryani.baseconv.decode_str(encoding='utf-8')[source]

Return a string to unicode converter that uses given encoding.

>>> decode_str()('   Hello world!   ')
(u'   Hello world!   ', None)
>>> decode_str()(u'   Hello world!   ')
(u'   Hello world!   ', None)
>>> decode_str()(42)
(42, None)
>>> decode_str()(None)
(None, None)
biryani.baseconv.default(constant)[source]

Return a converter that replace a None value by given one.

Note

See converter set_value() to replace a non-None value.

>>> default(42)(None)
(42, None)
>>> default(42)(u'1234')
(u'1234', None)
>>> pipe(input_to_int, default(42))(u'1234')
(1234, None)
>>> pipe(input_to_int, default(42))(u'    ')
(42, None)
>>> pipe(input_to_int, default(42))(None)
(42, None)
biryani.baseconv.empty_to_none(value, state=None)[source]

When value is comparable to False (ie None, 0 , ‘’, etc) replace it with None else keep it as is.

>>> empty_to_none(0)
(None, None)
>>> empty_to_none('')
(None, None)
>>> empty_to_none([])
(None, None)
>>> empty_to_none([42, 43])
([42, 43], None)
>>> empty_to_none({})
(None, None)
>>> empty_to_none({'answer': 42})
({'answer': 42}, None)
>>> empty_to_none(u'hello world')
(u'hello world', None)
>>> empty_to_none(u'   hello world   ')
(u'   hello world   ', None)
biryani.baseconv.encode_str(encoding='utf-8')[source]

Return a unicode to string converter that uses given encoding.

>>> encode_str()(u'   Hello world!   ')
('   Hello world!   ', None)
>>> encode_str()('   Hello world!   ')
('   Hello world!   ', None)
>>> encode_str()(42)
(42, None)
>>> encode_str()(None)
(None, None)
biryani.baseconv.extract_when_singleton(value, state=None)

Extract first item of sequence when it is a singleton and it is not itself a sequence, otherwise keep it unchanged.

>>> extract_when_singleton([42])
(42, None)
>>> extract_when_singleton([42, 43])
([42, 43], None)
>>> extract_when_singleton([])
([], None)
>>> extract_when_singleton(None)
(None, None)
>>> extract_when_singleton([[42]])
([[42]], None)
biryani.baseconv.fail(error=u'An error occured')[source]

Return a converter that always returns an error.

>>> fail(u'Wrong answer')(42)
(42, u'Wrong answer')
>>> fail()(42)
(42, u'An error occured')
>>> fail()(None)
(None, u'An error occured')
biryani.baseconv.first_match(*converters)[source]

Try each converter successively until one succeeds. When every converter fail, return the result of the last one.

>>> first_match(test_equals(u'NaN'), input_to_int)(u'NaN')
(u'NaN', None)
>>> first_match(test_equals(u'NaN'), input_to_int)(u'42')
(42, None)
>>> first_match(test_equals(u'NaN'), input_to_int)(u'abc')
(u'abc', u'Value must be an integer')
>>> first_match(test_equals(u'NaN'), input_to_int, set_value(0))(u'Hello world!')
(0, None)
>>> first_match()(u'Hello world!')
(u'Hello world!', None)
biryani.baseconv.function(function, handle_none_value=False, handle_state=False)[source]

Return a converter that applies a function to value and returns a new value.

Note

Like most converters, by default a None value is not converted (ie function is not called). Set handle_none_value to True to call function when value is None.

Note

When your function doesn’t modify value but may generate an error, use a test() instead.

Note

When your function modifies value and may generate an error, write a full converter instead of a function.

See How to create your own converter for more information.

>>> function(int)('42')
(42, None)
>>> function(sorted)([3, 2, 1])
([1, 2, 3], None)
>>> function(lambda value: value + 1)(42)
(43, None)
>>> function(lambda value: value + 1)(None)
(None, None)
>>> function(lambda value: value + 1)(u'hello world')
Traceback (most recent call last):
TypeError:
>>> function(lambda value: value + 1, handle_none_value = True)(None)
Traceback (most recent call last):
TypeError:
Traceback (most recent call last):
TypeError:
biryani.baseconv.get(key, default=<type 'exceptions.UnboundLocalError'>, error=None)[source]

Return a converter that returns an item of a collection.

Collection can either be a mapping (ie dict, etc) or a sequence (ie list, tuple, string, etc).

Usage with a mapping:

>>> get('a')(dict(a = 1, b = 2))
(1, None)
>>> get('c')(dict(a = 1, b = 2))
(None, u'Unknown key: c')
>>> get('c', default = None)(dict(a = 1, b = 2))
(None, None)
>>> get('c', error = u'Key Error')(dict(a = 1, b = 2))
(None, u'Key Error')
>>> get(u'a')(None)
(None, None)

Usage with a sequence: >>> get(0)(u’ab’) (u’a’, None) >>> get(-2)([u’a’, u’b’]) (u’a’, None) >>> get(-3)(u’ab’) (None, u’Index out of range: -3’) >>> get(2, error = u”Index Error’)([u’a’, u’b’]) (None, u”Index Error’) >>> get(-3, default = None)(u’ab’) (None, None) >>> get(0)(None) (None, None)

biryani.baseconv.guess_bool(value, state=None)[source]

Convert the content of a string (or a number) to a boolean. Do nothing when input value is already a boolean.

This converter accepts usual values for True and False: “0”, “f”, “false”, “n”, etc.

Warning

Like most converters, a None value is not converted.

When you want None to be converted to False, use:

pipe(guess_bool, default(False))
>>> guess_bool(u'0')
(False, None)
>>> guess_bool(u'f')
(False, None)
>>> guess_bool(u'FALSE')
(False, None)
>>> guess_bool(u'false')
(False, None)
>>> guess_bool(u'n')
(False, None)
>>> guess_bool(u'no')
(False, None)
>>> guess_bool(u'off')
(False, None)
>>> guess_bool(u'  0  ')
(False, None)
>>> guess_bool(u'  f  ')
(False, None)
>>> guess_bool(False)
(False, None)
>>> guess_bool(0)
(False, None)
>>> guess_bool(u'1')
(True, None)
>>> guess_bool(u'on')
(True, None)
>>> guess_bool(u't')
(True, None)
>>> guess_bool(u'TRUE')
(True, None)
>>> guess_bool(u'true')
(True, None)
>>> guess_bool(u'y')
(True, None)
>>> guess_bool(u'yes')
(True, None)
>>> guess_bool(u'  1  ')
(True, None)
>>> guess_bool(u'  tRuE  ')
(True, None)
>>> guess_bool(True)
(True, None)
>>> guess_bool(1)
(True, None)
>>> guess_bool(2)
(True, None)
>>> guess_bool(-1)
(True, None)
>>> guess_bool(u'')
(None, None)
>>> guess_bool(u'   ')
(None, None)
>>> guess_bool(None)
(None, None)
>>> guess_bool(u'vrai')
(u'vrai', u'Value must be a boolean')
biryani.baseconv.input_to_bool(*args, **kwargs)

Convert a string to a boolean.

Warning

Like most converters, a None value is not converted.

When you want None to be converted to False, use:

pipe(input_to_bool, default(False))
>>> input_to_bool(u'0')
(False, None)
>>> input_to_bool(u'   0   ')
(False, None)
>>> input_to_bool(u'1')
(True, None)
>>> input_to_bool(u'   1   ')
(True, None)
>>> input_to_bool(None)
(None, None)
>>> input_to_bool(u'vrai')
(u'vrai', u'Value must be a boolean')
>>> input_to_bool(u'on')
(u'on', u'Value must be a boolean')
biryani.baseconv.input_to_email(*args, **kwargs)

Convert a string to an email address.

>>> input_to_email(u'john@doe.name')
(u'john@doe.name', None)
>>> input_to_email(u'mailto:john@doe.name')
(u'john@doe.name', None)
>>> input_to_email(u'root@localhost')
(u'root@localhost', None)
>>> input_to_email('root@127.0.0.1')
('root@127.0.0.1', u'Invalid domain name')
>>> input_to_email(u'root')
(u'root', u'An email must contain exactly one "@"')
>>> input_to_email(u'    john@doe.name  ')
(u'john@doe.name', None)
>>> input_to_email(None)
(None, None)
>>> input_to_email(u'    ')
(None, None)
biryani.baseconv.input_to_float(*args, **kwargs)

Convert a string to float.

>>> input_to_float('42')
(42.0, None)
>>> input_to_float(u'   42.25   ')
(42.25, None)
>>> input_to_float(u'hello world')
(u'hello world', u'Value must be a float')
>>> input_to_float(None)
(None, None)
biryani.baseconv.input_to_int(*args, **kwargs)

Convert a string to an integer.

>>> input_to_int('42')
(42, None)
>>> input_to_int(u'   42   ')
(42, None)
>>> input_to_int(u'42.75')
(42, None)
>>> input_to_int(u'42,75')
(u'42,75', u'Value must be an integer')
>>> input_to_int(None)
(None, None)
biryani.baseconv.input_to_slug(value, state=None)

Convert a string to a slug.

Note

For a configurable converter, see make_input_to_slug().

Note

For a converter that doesn’t use “-” as word separators or doesn’t convert characters to lower case, see input_to_normal_form().

>>> input_to_slug(u'   Hello world!   ')
(u'hello-world', None)
>>> input_to_slug('   Hello world!   ')
(u'hello-world', None)
>>> input_to_slug(u'')
(None, None)
>>> input_to_slug(u'   ')
(None, None)
biryani.baseconv.input_to_url_name(value, state=None)

Normalize a string to allow its use in an URL (or file system) path or a query parameter.

Note

For a configurable converter, see make_input_to_url_name().

Note

For a converter that keep only letters, digits and separator, see make_input_to_slug() or input_to_slug().

Note

For a converter that doesn’t use “_” as word separators or doesn’t convert characters to lower case, see input_to_normal_form().

>>> input_to_url_name(u'   Hello world!   ')
(u'hello_world!', None)
>>> input_to_url_name(u'   ')
(None, None)
>>> input_to_url_name(u'')
(None, None)
biryani.baseconv.input_to_url_path_and_query(*args, **kwargs)

Convert a string to the path and query of an URL.

>>> input_to_url_path_and_query(u'/Biryani/presentation.html#tutorial')
(u'/Biryani/presentation.html', None)
>>> input_to_url_path_and_query(u'/Biryani/search.html?q=pipe')
(u'/Biryani/search.html?q=pipe', None)
>>> input_to_url_path_and_query(u'   /Biryani/search.html?q=pipe   ')
(u'/Biryani/search.html?q=pipe', None)
>>> input_to_url_path_and_query(u'http://packages.python.org/Biryani/search.html?q=pipe')
(u'http://packages.python.org/Biryani/search.html?q=pipe', u'URL must not be complete')
>>> print input_to_url_path_and_query(None)
(None, None)
biryani.baseconv.item_or_sequence(converter, constructor=<type 'list'>, drop_none_items=False)[source]

Return a converter that accepts either an item or a sequence of items and applies a converter to them.

>>> item_or_sequence(input_to_int)(u'42')
(42, None)
>>> item_or_sequence(input_to_int)([u'42'])
(42, None)
>>> item_or_sequence(input_to_int)([u'42', u'43'])
([42, 43], None)
>>> item_or_sequence(input_to_int)([u'42', u'43', u'Hello world!'])
([42, 43, u'Hello world!'], {2: u'Value must be an integer'})
>>> item_or_sequence(input_to_int)([None, None])
([None, None], None)
>>> item_or_sequence(input_to_int, drop_none_items = True)([None, None])
([], None)
>>> item_or_sequence(input_to_int)([u'42', None, u'43'])
([42, None, 43], None)
>>> item_or_sequence(input_to_int, drop_none_items = True)([u'42', None, u'43'])
([42, 43], None)
>>> item_or_sequence(input_to_int)([u'42', u'43', u'Hello world!'])
([42, 43, u'Hello world!'], {2: u'Value must be an integer'})
>>> item_or_sequence(input_to_int, constructor = set)(set([u'42', u'43']))
(set([42, 43]), None)
biryani.baseconv.make_item_to_singleton(constructor=<type 'list'>)[source]

Convert an item to a singleton, but keep a sequence of items unchanged.

>>> make_item_to_singleton()(u'Hello world!')
([u'Hello world!'], None)
>>> make_item_to_singleton()([u'Hello world!'])
([u'Hello world!'], None)
>>> make_item_to_singleton()([42, u'Hello world!'])
([42, u'Hello world!'], None)
>>> make_item_to_singleton()([])
([], None)
>>> make_item_to_singleton()(None)
(None, None)
>>> make_item_to_singleton(constructor = set)(u'Hello world!')
(set([u'Hello world!']), None)
>>> make_item_to_singleton(constructor = set)(set([u'Hello world!']))
(set([u'Hello world!']), None)
>>> make_item_to_singleton(constructor = set)(set([42, u'Hello world!']))
(set([u'Hello world!', 42]), None)
>>> make_item_to_singleton(constructor = set)([42, u'Hello world!'])
Traceback (most recent call last):
TypeError:
>>> make_item_to_singleton(constructor = set)(set())
(set([]), None)
>>> make_item_to_singleton(constructor = set)(None)
(None, None)
Traceback (most recent call last):
TypeError:
biryani.baseconv.make_input_to_normal_form(encoding='utf-8', separator=u' ', transform=<function lower at 0x7f5d608c2a28>)[source]

Return a convert that simplifies a string to normal form using compatibility decomposition and removing combining characters.

Note

For a converter that is dedicated to a name in an URL path, see input_to_url_name().

Note

For a converter that keep only letters, digits and separator, see make_input_to_slug() or input_to_slug().

>>> make_input_to_normal_form()(u'Hello world!')
(u'hello world!', None)
>>> make_input_to_normal_form()('Hello world!')
(u'hello world!', None)
>>> make_input_to_normal_form()(u'   Hello world!   ')
(u'hello world!', None)
>>> make_input_to_normal_form(encoding = u'iso-8859-1')(u'Hello world!')
(u'hello world!', None)
>>> make_input_to_normal_form(separator = u'_')(u'Hello world!')
(u'hello_world!', None)
>>> from biryani import strings
>>> make_input_to_normal_form(separator = u' ', transform = strings.upper)(u'Hello world!')
(u'HELLO WORLD!', None)
>>> make_input_to_normal_form()(u'')
(None, None)
>>> make_input_to_normal_form()(u'   ')
(None, None)
biryani.baseconv.make_input_to_slug(encoding='utf-8', separator=u'-', transform=<function lower at 0x7f5d608c2a28>)[source]

Return a convert that simplifies a string to a slug.

Note

For a converter that uses default parameters, see input_to_slug().

>>> make_input_to_slug()(u'Hello world!')
(u'hello-world', None)
>>> make_input_to_slug()('Hello world!')
(u'hello-world', None)
>>> make_input_to_slug()(u'   Hello world!   ')
(u'hello-world', None)
>>> make_input_to_slug(encoding = u'iso-8859-1')(u'Hello world!')
(u'hello-world', None)
>>> make_input_to_slug(separator = u' ')(u'Hello world!')
(u'hello world', None)
>>> from biryani import strings
>>> make_input_to_slug(separator = u' ', transform = strings.upper)(u'Hello world!')
(u'HELLO WORLD', None)
>>> make_input_to_slug()(u'')
(None, None)
>>> make_input_to_slug()(u'   ')
(None, None)
biryani.baseconv.make_input_to_url(add_prefix=None, error_if_fragment=False, error_if_path=False, error_if_query=False, full=False, remove_fragment=False, remove_path=False, remove_query=False, schemes=(u'http', u'https'))[source]

Return a converter that converts an string to an URL.

>>> make_input_to_url()(u'http://packages.python.org/Biryani/')
(u'http://packages.python.org/Biryani/', None)
>>> make_input_to_url()(u'packages.python.org/Biryani/')
(u'packages.python.org/Biryani/', None)
>>> make_input_to_url(full = True)(u'packages.python.org/Biryani/')
(u'packages.python.org/Biryani/', u'URL must be complete')
>>> make_input_to_url(add_prefix = u'http://', full = True)(u'packages.python.org/Biryani/')
(u'http://packages.python.org/Biryani/', None)
>>> make_input_to_url()(u'/Biryani/presentation.html#tutorial')
(u'/Biryani/presentation.html#tutorial', None)
>>> make_input_to_url(full = True)(u'/Biryani/presentation.html#tutorial')
(u'/Biryani/presentation.html#tutorial', u'URL must be complete')
>>> make_input_to_url(remove_path = True)(u'http://packages.python.org/Biryani/presentation.html')
(u'http://packages.python.org/', None)
>>> make_input_to_url(error_if_path = True)(u'http://packages.python.org/Biryani/presentation.html')
(u'http://packages.python.org/Biryani/presentation.html', u'URL must not contain a path')
>>> make_input_to_url(remove_query = True)(u'http://packages.python.org/Biryani/presentation.html?tuto=1')
(u'http://packages.python.org/Biryani/presentation.html', None)
>>> make_input_to_url(error_if_query = True)(u'http://packages.python.org/Biryani/presentation.html?tuto=1')
(u'http://packages.python.org/Biryani/presentation.html?tuto=1', u'URL must not contain a query')
>>> make_input_to_url(remove_fragment = True)(u'http://packages.python.org/Biryani/presentation.html#tutorial')
(u'http://packages.python.org/Biryani/presentation.html', None)
>>> make_input_to_url(error_if_fragment = True)(u'http://packages.python.org/Biryani/presentation.html#tutorial')
(u'http://packages.python.org/Biryani/presentation.html#tutorial', u'URL must not contain a fragment')
>>> make_input_to_url()(u'    http://packages.python.org/Biryani/   ')
(u'http://packages.python.org/Biryani/', None)
biryani.baseconv.make_input_to_url_name(encoding='utf-8', separator=u'_', transform=<function lower at 0x7f5d608c2a28>)[source]

Return a converts that normalizes a string to allow its use in an URL (or file system) path or a query parameter.

Note

For a converter that keep only letters, digits and separator, see make_input_to_slug() or input_to_slug().

>>> make_input_to_url_name()(u'   Hello world!   ')
(u'hello_world!', None)
>>> make_input_to_url_name()(u'   ')
(None, None)
>>> make_input_to_url_name()(u'')
(None, None)
biryani.baseconv.make_str_to_url(add_prefix=None, error_if_fragment=False, error_if_path=False, error_if_query=False, full=False, remove_fragment=False, remove_path=False, remove_query=False, schemes=(u'http', u'https'))[source]

Return a converter that converts a clean string to an URL.

Note

For a converter that doesn’t require a clean string, see make_input_to_url().

>>> make_str_to_url()(u'http://packages.python.org/Biryani/')
(u'http://packages.python.org/Biryani/', None)
>>> make_str_to_url()(u'packages.python.org/Biryani/')
(u'packages.python.org/Biryani/', None)
>>> make_str_to_url(full = True)(u'packages.python.org/Biryani/')
(u'packages.python.org/Biryani/', u'URL must be complete')
>>> make_str_to_url(add_prefix = u'http://', full = True)(u'packages.python.org/Biryani/')
(u'http://packages.python.org/Biryani/', None)
>>> make_str_to_url()(u'/Biryani/presentation.html#tutorial')
(u'/Biryani/presentation.html#tutorial', None)
>>> make_str_to_url(full = True)(u'/Biryani/presentation.html#tutorial')
(u'/Biryani/presentation.html#tutorial', u'URL must be complete')
>>> make_str_to_url(remove_path = True)(u'http://packages.python.org/Biryani/presentation.html')
(u'http://packages.python.org/', None)
>>> make_str_to_url(error_if_path = True)(u'http://packages.python.org/Biryani/presentation.html')
(u'http://packages.python.org/Biryani/presentation.html', u'URL must not contain a path')
>>> make_str_to_url(remove_query = True)(u'http://packages.python.org/Biryani/presentation.html?tuto=1')
(u'http://packages.python.org/Biryani/presentation.html', None)
>>> make_str_to_url(error_if_query = True)(u'http://packages.python.org/Biryani/presentation.html?tuto=1')
(u'http://packages.python.org/Biryani/presentation.html?tuto=1', u'URL must not contain a query')
>>> make_str_to_url(remove_fragment = True)(u'http://packages.python.org/Biryani/presentation.html#tutorial')
(u'http://packages.python.org/Biryani/presentation.html', None)
>>> make_str_to_url(error_if_fragment = True)(u'http://packages.python.org/Biryani/presentation.html#tuto')
(u'http://packages.python.org/Biryani/presentation.html#tuto', u'URL must not contain a fragment')
>>> make_str_to_url(full = True)(u'[www.nordnet.fr/grandmix/]')
(u'[www.nordnet.fr/grandmix/]', u'URL must be complete')
>>> make_str_to_url(full = True)(u'http://[www.nordnet.fr/grandmix/]')
(u'http://[www.nordnet.fr/grandmix/]', u'Invalid URL')
biryani.baseconv.merge(*converters)[source]

Return a converter that merge the resulsts of several structured_mapping() converters.

>>> ab_converter = struct(
... dict(
...     a = input_to_int,
...     b = input_to_float,
...     ),
... default = 'drop',
... )
>>> c_converter = struct(
... dict(
...     c = input_to_email,
...     ),
... default = 'drop',
... )
>>> abc_converter = merge(ab_converter, c_converter)
>>> abc_converter(dict(a = u'1', b = u'2', c = u'john@doe.name'))
({'a': 1, 'c': u'john@doe.name', 'b': 2.0}, None)
>>> abc_converter(dict(a = u'1'))
({'a': 1, 'c': None, 'b': None}, None)
>>> abc_converter(dict(c = u'john@doe.name'))
({'a': None, 'c': u'john@doe.name', 'b': None}, None)
>>> abc_converter(dict(a = u'a', b = u'b', c = u'1'))
({'a': u'a', 'c': u'1', 'b': u'b'}, {'a': u'Value must be an integer', 'c': u'An email must contain exactly one "@"', 'b': u'Value must be a float'})
>>> abc_converter({})
({'a': None, 'c': None, 'b': None}, None)
>>> abc_converter(None)
(None, None)
biryani.baseconv.new_mapping(converters, constructor=None, drop_none_values=False, handle_none_value=False)[source]

Return a converter that constructs a mapping (ie dict, etc) from any kind of value.

Note

This converter should not be used directly. Use new_struct() instead.

Note

When input value has the same structure, converter struct() should be used instead.

>>> def convert_list_to_dict(constructor = None, drop_none_values = False, handle_none_value = False):
...     return new_mapping(
...         dict(
...             name = get(0),
...             age = pipe(get(1), input_to_int),
...             email = pipe(get(2), input_to_email),
...             ),
...         constructor = constructor,
...         drop_none_values = drop_none_values,
...         handle_none_value = handle_none_value,
...         )
>>> convert_list_to_dict()([u'John Doe', u'72', u'john@doe.name'])
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> convert_list_to_dict()([u'John Doe', u'72'])
({'age': 72, 'email': None, 'name': u'John Doe'}, {'email': u'Index out of range: 2'})
>>> convert_list_to_dict()([u'John Doe', u'72', None])
({'age': 72, 'email': None, 'name': u'John Doe'}, None)
>>> convert_list_to_dict()([None, u' ', None])
({'age': None, 'email': None, 'name': None}, None)
>>> convert_list_to_dict(drop_none_values = True)([None, u' ', None])
({}, None)
>>> convert_list_to_dict()(None)
(None, None)
>>> convert_list_to_dict(handle_none_value = True)(None)
({'age': None, 'email': None, 'name': None}, None)
>>> convert_list_to_dict(drop_none_values = True, handle_none_value = True)(None)
({}, None)
>>> import collections
>>> new_mapping(
...     dict(
...         name = get(0),
...         age = pipe(get(1), input_to_int),
...         email = pipe(get(2), input_to_email),
...         ),
...     constructor = collections.OrderedDict,
...     )([u'John Doe', u'72', u'john@doe.name'])
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)
>>> new_mapping(
...     collections.OrderedDict(
...         name = get(0),
...         age = pipe(get(1), input_to_int),
...         email = pipe(get(2), input_to_email),
...         ),
...     )([u'John Doe', u'72', u'john@doe.name'])
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)
biryani.baseconv.new_sequence(converters, constructor=None, handle_none_value=False)[source]

Return a converter that constructs a sequence (ie list, tuple, etc) from any kind of value.

Note

This converter should not be used directly. Use new_struct() instead.

Note

When input value has the same structure, converter struct() should be used instead.

>>> def convert_dict_to_list(constructor = None, handle_none_value = False):
...     return new_sequence(
...         [
...             get('name', default = None),
...             pipe(get('age', default = None), input_to_int),
...             pipe(get('email', default = None), input_to_email),
...             ],
...         constructor = constructor,
...         handle_none_value = handle_none_value,
...         )
>>> convert_dict_to_list()({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
([u'John Doe', 72, u'john@doe.name'], None)
>>> convert_dict_to_list(constructor = tuple)({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
((u'John Doe', 72, u'john@doe.name'), None)
>>> convert_dict_to_list()({'email': u'john@doe.name', 'name': u'John Doe'})
([u'John Doe', None, u'john@doe.name'], None)
>>> convert_dict_to_list()({})
([None, None, None], None)
>>> convert_dict_to_list()(None)
(None, None)
>>> convert_dict_to_list(handle_none_value = True)(None)
([None, None, None], None)
>>> import collections
>>> new_sequence(
...     [
...         get('name', default = None),
...         pipe(get('age', default = None), input_to_int),
...         pipe(get('email', default = None), input_to_email),
...         ],
...     constructor = tuple,
...     )({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
((u'John Doe', 72, u'john@doe.name'), None)
>>> new_sequence(
...     (
...         get('name', default = None),
...         pipe(get('age', default = None), input_to_int),
...         pipe(get('email', default = None), input_to_email),
...         ),
...     )({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
((u'John Doe', 72, u'john@doe.name'), None)
biryani.baseconv.new_struct(converters, constructor=None, drop_none_values=False, handle_none_value=False)[source]

Return a converter that constructs a collection (ie dict, list, set, etc) from any kind of value.

Note

When input value has the same structure, converter struct() should be used instead.

Note

Parameter drop_none_values is not used for sequences.

Usage to create a mapping (ie dict, etc):

>>> def convert_list_to_dict(constructor = None, drop_none_values = False, handle_none_value = False):
...     return new_struct(
...         dict(
...             name = get(0),
...             age = pipe(get(1), input_to_int),
...             email = pipe(get(2), input_to_email),
...             ),
...         constructor = constructor,
...         drop_none_values = drop_none_values,
...         handle_none_value = handle_none_value,
...         )
>>> convert_list_to_dict()([u'John Doe', u'72', u'john@doe.name'])
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> convert_list_to_dict()([u'John Doe', u'72'])
({'age': 72, 'email': None, 'name': u'John Doe'}, {'email': u'Index out of range: 2'})
>>> convert_list_to_dict()([u'John Doe', u'72', None])
({'age': 72, 'email': None, 'name': u'John Doe'}, None)
>>> convert_list_to_dict()([None, u' ', None])
({'age': None, 'email': None, 'name': None}, None)
>>> convert_list_to_dict(drop_none_values = True)([None, u' ', None])
({}, None)
>>> convert_list_to_dict()(None)
(None, None)
>>> convert_list_to_dict(handle_none_value = True)(None)
({'age': None, 'email': None, 'name': None}, None)
>>> convert_list_to_dict(drop_none_values = True, handle_none_value = True)(None)
({}, None)
>>> import collections
>>> new_struct(
...     dict(
...         name = get(0),
...         age = pipe(get(1), input_to_int),
...         email = pipe(get(2), input_to_email),
...         ),
...     constructor = collections.OrderedDict,
...     )([u'John Doe', u'72', u'john@doe.name'])
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)
>>> new_struct(
...     collections.OrderedDict(
...         name = get(0),
...         age = pipe(get(1), input_to_int),
...         email = pipe(get(2), input_to_email),
...         ),
...     )([u'John Doe', u'72', u'john@doe.name'])
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)

Usage to create a sequence (ie list, tuple, etc) or a set:

>>> def convert_dict_to_list(constructor = None, handle_none_value = False):
...     return new_struct(
...         [
...             get('name', default = None),
...             pipe(get('age', default = None), input_to_int),
...             pipe(get('email', default = None), input_to_email),
...             ],
...         constructor = constructor,
...         handle_none_value = handle_none_value,
...         )
>>> convert_dict_to_list()({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
([u'John Doe', 72, u'john@doe.name'], None)
>>> convert_dict_to_list(constructor = tuple)({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
((u'John Doe', 72, u'john@doe.name'), None)
>>> convert_dict_to_list()({'email': u'john@doe.name', 'name': u'John Doe'})
([u'John Doe', None, u'john@doe.name'], None)
>>> convert_dict_to_list()({})
([None, None, None], None)
>>> convert_dict_to_list()(None)
(None, None)
>>> convert_dict_to_list(handle_none_value = True)(None)
([None, None, None], None)
>>> import collections
>>> new_struct(
...     [
...         get('name', default = None),
...         pipe(get('age', default = None), input_to_int),
...         pipe(get('email', default = None), input_to_email),
...         ],
...     constructor = tuple,
...     )({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
((u'John Doe', 72, u'john@doe.name'), None)
>>> new_struct(
...     (
...         get('name', default = None),
...         pipe(get('age', default = None), input_to_int),
...         pipe(get('email', default = None), input_to_email),
...         ),
...     )({'age': u'72', 'email': u'john@doe.name', 'name': u'John Doe'})
((u'John Doe', 72, u'john@doe.name'), None)
biryani.baseconv.noop(value, state=None)[source]

Return value as is.

>>> noop(42)
(42, None)
>>> noop(None)
(None, None)
biryani.baseconv.not_none(value, state=None)

Return an error when value is None.

Note

To change error message “Missing value”, use test_not_none() instead.

>>> not_none(42)
(42, None)
>>> not_none(u'')
(u'', None)
>>> not_none(None)
(None, u'Missing value')
biryani.baseconv.ok(converter_or_value_and_error)[source]

Run a conversion and return True when it doesn’t generate an error or False otherwise.

This function can be called with either a converter or the result of a conversion.

Usage with a converter:

>>> ok(input_to_int)(u'42')
True
>>> ok(input_to_int)(u'hello world')
False

Usage with a conversion result :

>>> ok(input_to_int(u'42'))
True
>>> ok(input_to_int(u'hello world'))
False
biryani.baseconv.pipe(*converters)[source]

Return a compound converter that applies each of its converters till the end or an error occurs.

>>> input_to_bool(42)
Traceback (most recent call last):
AttributeError:
>>> pipe(input_to_bool)(42)
Traceback (most recent call last):
AttributeError:
>>> pipe(test_isinstance(unicode), input_to_bool)(42)
(42, u"Value is not an instance of <type 'unicode'>")
>>> pipe(anything_to_str, test_isinstance(unicode), input_to_bool)(42)
(True, None)
>>> pipe()(42)
(42, None)
Traceback (most recent call last):
AttributeError:
biryani.baseconv.rename_item(old_key, new_key)[source]

Return a converter that renames a key in a mapping.

>>> rename_item('a', 'c')(dict(a = 1, b = 2))
({'c': 1, 'b': 2}, None)
>>> rename_item('c', 'd')(dict(a = 1, b = 2))
({'a': 1, 'b': 2}, None)
>>> rename_item('c', 'd')(None)
(None, None)
biryani.baseconv.set_value(constant, handle_none_value=False)[source]

Return a converter that replaces any value by given one.

>>> set_value(42)(u'Answer to the Ultimate Question of Life, the Universe, and Everything')
(42, None)
>>> set_value(42)(None)
(None, None)
>>> set_value(42, handle_none_value = True)(None)
(42, None)
biryani.baseconv.str_to_bool(value, state=None)[source]

Convert a clean string to a boolean.

Note

For a converter that doesn’t require a clean string, see input_to_bool().

Note

For a converter that accepts special strings like “f”, “off”, “no”, etc, see guess_bool().

Warning

Like most converters, a None value is not converted.

When you want None to be converted to False, use:

pipe(str_to_bool, default(False))
>>> str_to_bool(u'0')
(False, None)
>>> str_to_bool(u'1')
(True, None)
>>> str_to_bool(None)
(None, None)
>>> str_to_bool(u'vrai')
(u'vrai', u'Value must be a boolean')
>>> str_to_bool(u'on')
(u'on', u'Value must be a boolean')
biryani.baseconv.str_to_email(value, state=None)[source]

Convert a clean string to an email address.

Note

For a converter that doesn’t require a clean string, see input_to_email().

>>> str_to_email(u'john@doe.name')
(u'john@doe.name', None)
>>> str_to_email(u'mailto:john@doe.name')
(u'john@doe.name', None)
>>> str_to_email(u'root@localhost')
(u'root@localhost', None)
>>> str_to_email(u'root@127.0.0.1')
(u'root@127.0.0.1', u'Invalid domain name')
>>> str_to_email(u'root')
(u'root', u'An email must contain exactly one "@"')
biryani.baseconv.str_to_url_path_and_query(value, state=None)[source]

Convert a clean string to the path and query of an URL.

Note

For a converter that doesn’t require a clean string, see input_to_url_path_and_query().

>>> str_to_url_path_and_query(u'/Biryani/presentation.html#tutorial')
(u'/Biryani/presentation.html', None)
>>> str_to_url_path_and_query(u'/Biryani/search.html?q=pipe')
(u'/Biryani/search.html?q=pipe', None)
>>> str_to_url_path_and_query(u'http://packages.python.org/Biryani/search.html?q=pipe')
(u'http://packages.python.org/Biryani/search.html?q=pipe', u'URL must not be complete')
>>> str_to_url_path_and_query(u'[www.nordnet.fr/grandmix/]')
(u'[www.nordnet.fr/grandmix/]', None)
>>> print str_to_url_path_and_query(None)
(None, None)
>>> import urlparse
>>> pipe(
...     make_str_to_url(),
...     function(lambda value: urlparse.urlunsplit([u'', u''] + list(urlparse.urlsplit(value))[2:])),
...     str_to_url_path_and_query,
...     )(u'http://packages.python.org/Biryani/search.html?q=pipe')
(u'/Biryani/search.html?q=pipe', None)
biryani.baseconv.struct(converters, constructor=None, default=None, drop_none_values=False, keep_value_order=False, skip_missing_items=False)[source]

Return a converter that maps a collection of converters to a collection (ie dict, list, set, etc) of values.

Note

Parameters drop_none_values, keep_value_order & skip_missing_items are not used for sequences.

Usage to convert a mapping (ie dict, etc):

>>> strict_converter = struct(dict(
...     name = pipe(cleanup_line, not_none),
...     age = input_to_int,
...     email = input_to_email,
...     ))
...
>>> strict_converter(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> strict_converter(dict(name = u'John Doe', email = u'john@doe.name'))
({'age': None, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> strict_converter(dict(name = u'John Doe', age = None, email = u'john@doe.name'))
({'age': None, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> strict_converter(dict(name = u'John Doe', age = u'72', phone = u'   +33 9 12 34 56 78   '))
({'phone': u'   +33 9 12 34 56 78   ', 'age': 72, 'email': None, 'name': u'John Doe'}, {'phone': u'Unexpected item'})
>>> non_strict_converter = struct(
...     dict(
...         name = pipe(cleanup_line, not_none),
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     )
...
>>> non_strict_converter(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> non_strict_converter(dict(name = u'John Doe', email = u'john@doe.name'))
({'age': None, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> non_strict_converter(dict(name = u'John Doe', age = u'72', email = u'john@doe.name',
...     phone = u'   +33 9 12 34 56 78   '))
({'phone': u'+33 9 12 34 56 78', 'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> struct(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     )(dict(name = u'   ', email = None))
({'age': None, 'email': None, 'name': None}, None)
>>> struct(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     drop_none_values = True,
...     )(dict(name = u'   ', email = None))
({}, None)
>>> struct(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     drop_none_values = 'missing',
...     )(dict(name = u'   ', email = None))
({'email': None, 'name': None}, None)
>>> struct(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     skip_missing_items = True,
...     )(dict(name = u'   ', email = None))
({'email': None, 'name': None}, None)
>>> import collections
>>> struct(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     constructor = collections.OrderedDict,
...     )(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)
>>> struct(
...     collections.OrderedDict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     )(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)
>>> struct(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     )(collections.OrderedDict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)

Usage to convert a sequence (ie list, tuple, etc) or a set:

>>> strict_converter = struct([
...     pipe(cleanup_line, not_none),
...     input_to_int,
...     input_to_email,
...     ])
...
>>> strict_converter([u'John Doe', u'72', u'john@doe.name'])
([u'John Doe', 72, u'john@doe.name'], None)
>>> strict_converter([u'John Doe', u'john@doe.name'])
([u'John Doe', u'john@doe.name', None], {1: u'Value must be an integer'})
>>> strict_converter([u'John Doe', None, u'john@doe.name'])
([u'John Doe', None, u'john@doe.name'], None)
>>> strict_converter([u'John Doe', u'72', u'john@doe.name', u'   +33 9 12 34 56 78   '])
([u'John Doe', 72, u'john@doe.name', u'   +33 9 12 34 56 78   '], {3: u'Unexpected item'})
>>> non_strict_converter = struct(
...     [
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ],
...     default = cleanup_line,
...     )
...
>>> non_strict_converter([u'John Doe', u'72', u'john@doe.name'])
([u'John Doe', 72, u'john@doe.name'], None)
>>> non_strict_converter([u'John Doe', u'john@doe.name'])
([u'John Doe', u'john@doe.name', None], {1: u'Value must be an integer'})
>>> non_strict_converter([u'John Doe', None, u'john@doe.name'])
([u'John Doe', None, u'john@doe.name'], None)
>>> non_strict_converter([u'John Doe', u'72', u'john@doe.name', u'   +33 9 12 34 56 78   '])
([u'John Doe', 72, u'john@doe.name', u'+33 9 12 34 56 78'], None)
>>> import collections
>>> struct(
...     [
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ],
...     constructor = tuple,
...     )([u'John Doe', u'72', u'john@doe.name'])
((u'John Doe', 72, u'john@doe.name'), None)
>>> struct(
...     (
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ),
...     )([u'John Doe', u'72', u'john@doe.name'])
((u'John Doe', 72, u'john@doe.name'), None)
>>> struct(
...     [
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ],
...     )((u'John Doe', u'72', u'john@doe.name'))
([u'John Doe', 72, u'john@doe.name'], None)
biryani.baseconv.structured_mapping(converters, constructor=None, default=None, drop_none_values=False, keep_value_order=False, skip_missing_items=False)[source]

Return a converter that maps a mapping of converters to a mapping (ie dict, etc) of values.

Note

This converter should not be used directly. Use struct() instead.

>>> strict_converter = structured_mapping(dict(
...     name = pipe(cleanup_line, not_none),
...     age = input_to_int,
...     email = input_to_email,
...     ))
...
>>> strict_converter(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> strict_converter(dict(name = u'John Doe', email = u'john@doe.name'))
({'age': None, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> strict_converter(dict(name = u'John Doe', age = None, email = u'john@doe.name'))
({'age': None, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> strict_converter(dict(name = u'John Doe', age = u'72', phone = u'   +33 9 12 34 56 78   '))
({'phone': u'   +33 9 12 34 56 78   ', 'age': 72, 'email': None, 'name': u'John Doe'}, {'phone': u'Unexpected item'})
>>> non_strict_converter = structured_mapping(
...     dict(
...         name = pipe(cleanup_line, not_none),
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     )
...
>>> non_strict_converter(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> non_strict_converter(dict(name = u'John Doe', email = u'john@doe.name'))
({'age': None, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> non_strict_converter(dict(name = u'John Doe', age = u'72', email = u'john@doe.name',
...     phone = u'   +33 9 12 34 56 78   '))
({'phone': u'+33 9 12 34 56 78', 'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
>>> structured_mapping(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     )(dict(name = u'   ', email = None))
({'age': None, 'email': None, 'name': None}, None)
>>> structured_mapping(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     drop_none_values = True,
...     )(dict(name = u'   ', email = None))
({}, None)
>>> structured_mapping(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     drop_none_values = 'missing',
...     )(dict(name = u'   ', email = None))
({'email': None, 'name': None}, None)
>>> structured_mapping(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     default = cleanup_line,
...     skip_missing_items = True,
...     )(dict(name = u'   ', email = None))
({'email': None, 'name': None}, None)
>>> import collections
>>> structured_mapping(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     constructor = collections.OrderedDict,
...     )(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)
>>> structured_mapping(
...     collections.OrderedDict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     )(dict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
(OrderedDict([('age', 72), ('email', u'john@doe.name'), ('name', u'John Doe')]), None)
>>> structured_mapping(
...     dict(
...         name = cleanup_line,
...         age = input_to_int,
...         email = input_to_email,
...         ),
...     )(collections.OrderedDict(name = u'John Doe', age = u'72', email = u'john@doe.name'))
({'age': 72, 'email': u'john@doe.name', 'name': u'John Doe'}, None)
biryani.baseconv.structured_sequence(converters, constructor=None, default=None)[source]

Return a converter that map a sequence of converters to a sequence of values.

Note

This converter should not be used directly. Use struct() instead.

>>> strict_converter = structured_sequence([
...     pipe(cleanup_line, not_none),
...     input_to_int,
...     input_to_email,
...     ])
...
>>> strict_converter([u'John Doe', u'72', u'john@doe.name'])
([u'John Doe', 72, u'john@doe.name'], None)
>>> strict_converter([u'John Doe', u'john@doe.name'])
([u'John Doe', u'john@doe.name', None], {1: u'Value must be an integer'})
>>> strict_converter([u'John Doe', None, u'john@doe.name'])
([u'John Doe', None, u'john@doe.name'], None)
>>> strict_converter([u'John Doe', u'72', u'john@doe.name', u'   +33 9 12 34 56 78   '])
([u'John Doe', 72, u'john@doe.name', u'   +33 9 12 34 56 78   '], {3: u'Unexpected item'})
>>> non_strict_converter = structured_sequence(
...     [
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ],
...     default = cleanup_line,
...     )
...
>>> non_strict_converter([u'John Doe', u'72', u'john@doe.name'])
([u'John Doe', 72, u'john@doe.name'], None)
>>> non_strict_converter([u'John Doe', u'john@doe.name'])
([u'John Doe', u'john@doe.name', None], {1: u'Value must be an integer'})
>>> non_strict_converter([u'John Doe', None, u'john@doe.name'])
([u'John Doe', None, u'john@doe.name'], None)
>>> non_strict_converter([u'John Doe', u'72', u'john@doe.name', u'   +33 9 12 34 56 78   '])
([u'John Doe', 72, u'john@doe.name', u'+33 9 12 34 56 78'], None)
>>> import collections
>>> structured_sequence(
...     [
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ],
...     constructor = tuple,
...     )([u'John Doe', u'72', u'john@doe.name'])
((u'John Doe', 72, u'john@doe.name'), None)
>>> structured_sequence(
...     (
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ),
...     )([u'John Doe', u'72', u'john@doe.name'])
((u'John Doe', 72, u'john@doe.name'), None)
>>> structured_sequence(
...     [
...         pipe(cleanup_line, not_none),
...         input_to_int,
...         input_to_email,
...         ],
...     )((u'John Doe', u'72', u'john@doe.name'))
([u'John Doe', 72, u'john@doe.name'], None)
biryani.baseconv.submapping(keys, converter, remaining_converter=None, constructor=None)[source]

Return a converter that splits a mapping into 2 mappings, converts them separately and merge both results.

>>> submapping(
...     ['x', 'y'],
...     function(lambda subdict: dict(a = subdict['x'], b = subdict['y'])),
...     )(dict(x = 1, y = 2, z = 3, t = 4))
({'a': 1, 'b': 2, 'z': 3, 't': 4}, None)
>>> submapping(
...     ['x', 'y'],
...     function(lambda subdict: dict(a = subdict['x'], b = subdict['y'])),
...     uniform_mapping(noop, anything_to_str),
...     )(dict(x = 1, y = 2, z = 3, t = 4))
({'a': 1, 'b': 2, 'z': u'3', 't': u'4'}, None)
>>> submapping(
...     ['x', 'y'],
...     uniform_mapping(noop, test_equals(1)),
...     uniform_mapping(noop, anything_to_str),
...     )(dict(x = 1, y = 2, z = 3, t = 4))
({'y': 2, 'x': 1, 'z': u'3', 't': u'4'}, {'y': u'Value must be equal to 1'})
>>> submapping(
...     ['x', 'y'],
...     uniform_mapping(noop, test_equals(1)),
...     uniform_mapping(noop, test_equals(3)),
...     )(dict(x = 1, y = 2, z = 3, t = 4))
({'y': 2, 'x': 1, 'z': 3, 't': 4}, {'y': u'Value must be equal to 1', 't': u'Value must be equal to 3'})
>>> submapping(
...     ['x', 'y'],
...     test_equals(1),
...     uniform_mapping(noop, test_equals(3)),
...     )(dict(x = 1, y = 2, z = 3, t = 4))
({'y': 2, 'x': 1, 'z': 3, 't': 4}, u'Value must be equal to 1')
>>> submapping(
...     ['x', 'y'],
...     uniform_mapping(noop, test_equals(1)),
...     uniform_mapping(noop, test_equals(3)),
...     )({})
({}, None)
>>> submapping(
...     ['x', 'y'],
...     uniform_mapping(noop, test_equals(1)),
...     uniform_mapping(noop, test_equals(3)),
...     )(None)
(None, None)
biryani.baseconv.switch(key_converter, converters, default=None, handle_none_value=False)[source]

Return a converter that extracts a key from value and then converts value using the converter matching the key.

>>> simple_type_switcher = switch(
...     function(lambda value: type(value)),
...     {
...         bool: set_value(u'boolean'),
...         int: anything_to_str,
...         str: set_value(u'encoded string'),
...         },
...     handle_none_value = True,
...     )
>>> simple_type_switcher(True)
(u'boolean', None)
>>> simple_type_switcher(42)
(u'42', None)
>>> simple_type_switcher('Hello world!')
(u'encoded string', None)
>>> simple_type_switcher(u'Hello world!')
(u'Hello world!', u'Expression "<type \'unicode\'>" doesn\'t match any key')
>>> simple_type_switcher(None)
(None, u'Expression "None" doesn\'t match any key')
>>> type_switcher = switch(
...     function(lambda value: type(value)),
...     {
...         list: uniform_sequence(simple_type_switcher),
...         },
...     default = anything_to_str,
...     )
>>> type_switcher([False, 42])
([u'boolean', u'42'], None)
>>> type_switcher(u'Hello world!')
(u'Hello world!', None)
>>> type_switcher(None)
(None, None)
>>> type_switcher([None])
([None], {0: u'Expression "None" doesn\'t match any key'})
biryani.baseconv.test(function, error=u'Test failed', handle_none_value=False, handle_state=False)[source]

Return a converter that applies a test function to a value and returns an error when test fails.

test always returns the initial value, even when test fails.

See How to create your own converter for more information.
>>> test(lambda value: isinstance(value, basestring))('hello')
('hello', None)
>>> test(lambda value: isinstance(value, basestring))(1)
(1, u'Test failed')
>>> test(lambda value: isinstance(value, basestring), error = u'Value is not a string')(1)
(1, u'Value is not a string')
biryani.baseconv.test_between(min_value, max_value, error=None)[source]

Return a converter that accepts only values between the two given bounds (included).

Warning

Like most converters, a None value is not compared.

>>> test_between(0, 9)(5)
(5, None)
>>> test_between(0, 9)(0)
(0, None)
>>> test_between(0, 9)(9)
(9, None)
>>> test_between(0, 9)(10)
(10, u'Value must be between 0 and 9')
>>> test_between(0, 9, error = u'Number must be a digit')(10)
(10, u'Number must be a digit')
>>> test_between(0, 9)(None)
(None, None)
biryani.baseconv.test_conv(converter)[source]

Return a converter that applies a converter to test a value without modifying it.

test_conv always returns the initial value, even when test fails.

>>> test_conv(input_to_int)(u'42')
(u'42', None)
>>> test_conv(input_to_int)(u'Hello world!')
(u'Hello world!', u'Value must be an integer')
biryani.baseconv.test_equals(constant, error=None)[source]

Return a converter that accepts only values equals to given constant.

Warning

Like most converters, a None value is not compared. Furthermore, when constant is None, value is never compared.

>>> test_equals(42)(42)
(42, None)
>>> test_equals(dict(a = 1, b = 2))(dict(a = 1, b = 2))
({'a': 1, 'b': 2}, None)
>>> test_equals(41)(42)
(42, u'Value must be equal to 41')
>>> test_equals(41, error = u'Value is not the answer')(42)
(42, u'Value is not the answer')
>>> test_equals(None)(42)
(42, None)
>>> test_equals(42)(None)
(None, None)
biryani.baseconv.test_greater_or_equal(constant, error=None)[source]

Return a converter that accepts only values greater than or equal to given constant.

Warning

Like most converters, a None value is not compared.

>>> test_greater_or_equal(0)(5)
(5, None)
>>> test_greater_or_equal(9)(5)
(5, u'Value must be greater than or equal to 9')
>>> test_greater_or_equal(9, error = u'Value must be a positive two-digits number')(5)
(5, u'Value must be a positive two-digits number')
>>> test_greater_or_equal(9)(None)
(None, None)
>>> test_greater_or_equal(None)(5)
(5, None)
biryani.baseconv.test_in(values, error=None)[source]

Return a converter that accepts only values belonging to a given set (or list or...).

Warning

Like most converters, a None value is not compared. Furthermore, when values is None, value is never compared.

>>> test_in('abcd')('a')
('a', None)
>>> test_in(['a', 'b', 'c', 'd'])('a')
('a', None)
>>> test_in(['a', 'b', 'c', 'd'])('z')
('z', u"Value must belong to ['a', 'b', 'c', 'd']")
>>> test_in(['a', 'b', 'c', 'd'], error = u'Value must be a letter less than "e"')('z')
('z', u'Value must be a letter less than "e"')
>>> test_in([])('z')
('z', u'Value must belong to []')
>>> test_in(None)('z')
('z', None)
>>> test_in(['a', 'b', 'c', 'd'])(None)
(None, None)
biryani.baseconv.test_is(constant, error=None)[source]

Return a converter that accepts only values that are strictly equal to given constant.

Warning

Like most converters, a None value is not compared. Furthermore, when constant is None, value is never compared.

>>> test_is(42)(42)
(42, None)
>>> test_is(dict(a = 1, b = 2))(dict(a = 1, b = 2))
({'a': 1, 'b': 2}, u"Value must be {'a': 1, 'b': 2}")
>>> test_is(41)(42)
(42, u'Value must be 41')
>>> test_is(41, error = u'Value is not the answer')(42)
(42, u'Value is not the answer')
>>> test_is(None)(42)
(42, None)
>>> test_is(42)(None)
(None, None)
biryani.baseconv.test_isinstance(class_or_classes, error=None)[source]

Return a converter that accepts only an instance of given class (or tuple of classes).

>>> test_isinstance(basestring)('This is a string')
('This is a string', None)
>>> test_isinstance(basestring)(42)
(42, u"Value is not an instance of <type 'basestring'>")
>>> test_isinstance(basestring, error = u'Value is not a string')(42)
(42, u'Value is not a string')
>>> test_isinstance((float, int))(42)
(42, None)
biryani.baseconv.test_issubclass(class_or_classes, error=None)[source]

Return a converter that accepts only a class (or tuple of classes).

>>> test_issubclass(basestring)(int)
(<type 'int'>, u"Value is not a subclass of <type 'basestring'>")
>>> test_issubclass(basestring)('This is a string')
('This is a string', u"Value is not a subclass of <type 'basestring'>")
>>> test_issubclass(basestring)(str)
(<type 'str'>, None)
>>> test_issubclass(basestring, error = u'Value is not a string')(int)
(<type 'int'>, u'Value is not a string')
>>> test_issubclass((float, int, basestring))(unicode)
(<type 'unicode'>, None)
biryani.baseconv.test_less_or_equal(constant, error=None)[source]

Return a converter that accepts only values less than or equal to given constant.

Warning

Like most converters, a None value is not compared.

>>> test_less_or_equal(9)(5)
(5, None)
>>> test_less_or_equal(0)(5)
(5, u'Value must be less than or equal to 0')
>>> test_less_or_equal(0, error = u'Value must be negative')(5)
(5, u'Value must be negative')
>>> test_less_or_equal(9)(None)
(None, None)
>>> test_less_or_equal(None)(5)
(5, None)
biryani.baseconv.test_none(error=u'Unexpected value')[source]

Return a converters that signals an error when value is not None.

>>> test_none()(42)
(42, u'Unexpected value')
>>> test_none(error = u'No value allowed')(42)
(42, u'No value allowed')
>>> test_none()(u'')
(u'', u'Unexpected value')
>>> test_none()(None)
(None, None)
biryani.baseconv.test_not_in(values, error=None)[source]

Return a converter that rejects only values belonging to a given set (or list or...).

Warning

Like most converters, a None value is not compared. Furthermore, when values is None, value is never compared.

>>> test_not_in('abcd')('e')
('e', None)
>>> test_not_in(['a', 'b', 'c', 'd'])('e')
('e', None)
>>> test_not_in('abcd')('a')
('a', u'Value must not belong to abcd')
>>> test_not_in(['a', 'b', 'c', 'd'])('a')
('a', u"Value must not belong to ['a', 'b', 'c', 'd']")
>>> test_not_in(['a', 'b', 'c', 'd'], error = u'Value must not be a letter less than "e"')('a')
('a', u'Value must not be a letter less than "e"')
>>> test_not_in([])('z')
('z', None)
>>> test_not_in(None)('z')
('z', None)
>>> test_not_in(['a', 'b', 'c', 'd'])(None)
(None, None)
biryani.baseconv.test_not_none(error=u'Missing value')[source]

Return a converters that signals an error when value is None.

Note

When error message “Missing value” can be kept, use exists() instead.

>>> test_not_none()(42)
(42, None)
>>> test_not_none()(u'')
(u'', None)
>>> test_not_none()(None)
(None, u'Missing value')
>>> test_not_none(error = u'Required value')(None)
(None, u'Required value')
biryani.baseconv.translate(conversions)[source]

Return a converter that converts values found in given dictionary and keep others as is.

Warning

Unlike most converters, a None value is handled => It can be translated.

>>> translate({0: u'bad', 1: u'OK'})(0)
(u'bad', None)
>>> translate({0: u'bad', 1: u'OK'})(1)
(u'OK', None)
>>> translate({0: u'bad', 1: u'OK'})(2)
(2, None)
>>> translate({0: u'bad', 1: u'OK'})(u'three')
(u'three', None)
>>> translate({None: u'no problem', 0: u'bad', 1: u'OK'})(None)
(u'no problem', None)
biryani.baseconv.uniform_mapping(key_converter, value_converter, constructor=None, drop_none_keys=False, drop_none_values=False)[source]

Return a converter that applies a unique converter to each key and another unique converter to each value of a mapping.

>>> uniform_mapping(cleanup_line, input_to_int)({u'a': u'1', u'b': u'2'})
({u'a': 1, u'b': 2}, None)
>>> uniform_mapping(cleanup_line, input_to_int)({u'   answer   ': u'42'})
({u'answer': 42}, None)
>>> uniform_mapping(cleanup_line, pipe(test_isinstance(basestring), input_to_int))({u'a': u'1', u'b': u'2', 'c': 3})
({u'a': 1, 'c': 3, u'b': 2}, {'c': u"Value is not an instance of <type 'basestring'>"})
>>> uniform_mapping(cleanup_line, input_to_int)({})
({}, None)
>>> uniform_mapping(cleanup_line, input_to_int)({None: u'42'})
({None: 42}, None)
>>> uniform_mapping(cleanup_line, input_to_int, drop_none_keys = True)({None: u'42'})
({}, None)
>>> uniform_mapping(cleanup_line, input_to_int)(None)
(None, None)
biryani.baseconv.uniform_sequence(converter, constructor=<type 'list'>, drop_none_items=False)[source]

Return a converter that applies the same converter to each value of a list.

>>> uniform_sequence(input_to_int)([u'42'])
([42], None)
>>> uniform_sequence(input_to_int)([u'42', u'43'])
([42, 43], None)
>>> uniform_sequence(input_to_int)([u'42', u'43', u'Hello world!'])
([42, 43, u'Hello world!'], {2: u'Value must be an integer'})
>>> uniform_sequence(input_to_int)([None, None])
([None, None], None)
>>> uniform_sequence(input_to_int, drop_none_items = True)([None, None])
([], None)
>>> uniform_sequence(input_to_int)([u'42', None, u'43'])
([42, None, 43], None)
>>> uniform_sequence(input_to_int, drop_none_items = True)([u'42', None, u'43'])
([42, 43], None)
>>> uniform_sequence(input_to_int)([u'42', u'43', u'Hello world!'])
([42, 43, u'Hello world!'], {2: u'Value must be an integer'})
>>> uniform_sequence(input_to_int, constructor = set)(set([u'42', u'43']))
(set([42, 43]), None)

biryani.babelconv

Babel related Converters

See http://babel.edgewall.org/

biryani.babelconv.input_to_lang(*args, **kwargs)

Convert a string to a language code.

>>> input_to_lang(u'fr')
(u'fr', None)
>>> input_to_lang(u'fr_FR')
(u'fr_FR', None)
>>> input_to_lang(u'   fr_FR   ')
(u'fr_FR', None)
>>> input_to_lang(u'fr-FR')
(u'fr-FR', u'Invalid value')
>>> input_to_lang(u'francais')
(u'francais', u'Invalid value')
>>> input_to_lang(u'   ')
(None, None)
>>> input_to_lang(None)
(None, None)
biryani.babelconv.str_to_lang(value, state=None)[source]

Convert a clean string to a language code.

Note

For a converter that doesn’t require a clean string, see input_to_lang().

>>> str_to_lang(u'fr')
(u'fr', None)
>>> str_to_lang(u'fr_FR')
(u'fr_FR', None)
>>> str_to_lang(u'fr-FR')
(u'fr-FR', u'Invalid value')
>>> str_to_lang(u'francais')
(u'francais', u'Invalid value')
>>> str_to_lang(None)
(None, None)

biryani.base64conv

Base64 Related Converters

biryani.base64conv.base64_to_bytes(value, state=None)[source]

Decode data from a base64 encoding.

>>> base64_to_bytes(u'SGVsbG8gV29ybGQ=')
('Hello World', None)
>>> base64_to_bytes(u'SGVsbG8gV29ybGQ')
(u'SGVsbG8gV29ybGQ', u'Invalid base64 string')
>>> base64_to_bytes(u'Hello World')
(u'Hello World', u'Invalid base64 string')
>>> base64_to_bytes(u'')
('', None)
>>> base64_to_bytes(None)
(None, None)
biryani.base64conv.bytes_to_base64(value, state=None)[source]

Converts a string or bytes to a base64 encoding.

>>> bytes_to_base64('Hello World')
(u'SGVsbG8gV29ybGQ=', None)
>>> bytes_to_base64(u'Hello World')
(u'SGVsbG8gV29ybGQ=', None)
>>> bytes_to_base64(u'')
(u'', None)
>>> bytes_to_base64(None)
(None, None)
biryani.base64conv.make_base64url_to_bytes(add_padding=False)[source]

Return a converter that decodes data from an URL-safe base64 encoding.

Note

To handle values without padding “=”, set add_padding to True.

>>> make_base64url_to_bytes()(u'SGVsbG8gV29ybGQ=')
('Hello World', None)
>>> make_base64url_to_bytes(add_padding = True)(u'SGVsbG8gV29ybGQ')
('Hello World', None)
>>> make_base64url_to_bytes(add_padding = True)(u'SGVsbG8gV29ybGQ=')
('Hello World', None)
>>> make_base64url_to_bytes()(u'SGVsbG8gV29ybGQ')
(u'SGVsbG8gV29ybGQ', u'Invalid base64url string')
>>> make_base64url_to_bytes()(u'Hello World')
(u'Hello World', u'Invalid base64url string')
>>> make_base64url_to_bytes()(u'')
('', None)
>>> make_base64url_to_bytes()(None)
(None, None)
biryani.base64conv.make_bytes_to_base64url(remove_padding=False)[source]

Return a converter that converts a string or bytes to an URL-safe base64 encoding.

Note

To remove trailing (non URL-safe) “=”, set remove_padding to True.

>>> make_bytes_to_base64url()('Hello World')
(u'SGVsbG8gV29ybGQ=', None)
>>> make_bytes_to_base64url()(u'Hello World')
(u'SGVsbG8gV29ybGQ=', None)
>>> make_bytes_to_base64url(remove_padding = True)(u'Hello World')
(u'SGVsbG8gV29ybGQ', None)
>>> make_bytes_to_base64url()(u'')
(u'', None)
>>> make_bytes_to_base64url()(None)
(None, None)

biryani.bsonconv

MongoDB BSON related Converters

See http://api.mongodb.org/python/current/api/bson/index.html

biryani.bsonconv.anything_to_object_id(value, state=None)

Convert any compatible Python data to a BSON ObjectId.

>>> anything_to_object_id(u'4e333f53ff42e928000007d8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> anything_to_object_id('4e333f53ff42e928000007d8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> anything_to_object_id(u'4E333F53FF42E928000007D8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> anything_to_object_id(u'   4e333f53ff42e928000007d8   ')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> from bson.objectid import ObjectId
>>> anything_to_object_id(ObjectId('4e333f53ff42e928000007d8'))
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> anything_to_object_id(u"ObjectId('4e333f53ff42e928000007d8')")
(u"ObjectId('4e333f53ff42e928000007d8')", u'Invalid value')
>>> anything_to_object_id(u'  ')
(None, None)
>>> anything_to_object_id(None)
(None, None)
biryani.bsonconv.bson_to_json(value, state=None)

Convert a BSON value to JSON.

A MongoDB document can’t have an item with a key containing a ”.”. So they are escaped with “%”.

>>> bson_to_json({'a': 1, 'b': [2, 3], 'c%2ed': {'e': 4}})
({'a': 1, 'c.d': {'e': 4}, 'b': [2, 3]}, None)
>>> bson_to_json({})
({}, None)
>>> bson_to_json(None)
(None, None)
biryani.bsonconv.input_to_object_id(*args, **kwargs)

Convert a string to a BSON ObjectId.

Note

For a converter that doesn’t fail when input data is already an ObjectId, use anything_to_object_id().

>>> input_to_object_id(u'4e333f53ff42e928000007d8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> input_to_object_id('4e333f53ff42e928000007d8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> input_to_object_id(u'4E333F53FF42E928000007D8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> input_to_object_id(u'   4e333f53ff42e928000007d8   ')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> from bson.objectid import ObjectId
>>> input_to_object_id(ObjectId('4e333f53ff42e928000007d8'))
Traceback (most recent call last):
AttributeError:
>>> input_to_object_id(u"ObjectId('4e333f53ff42e928000007d8')")
(u"ObjectId('4e333f53ff42e928000007d8')", u'Invalid value')
>>> input_to_object_id(u'  ')
(None, None)
>>> input_to_object_id(None)
(None, None)
Traceback (most recent call last):
AttributeError:
biryani.bsonconv.input_to_object_id_str(*args, **kwargs)

Convert a string to a BSON ObjectId string.

>>> input_to_object_id_str(u'4e333f53ff42e928000007d8')
(u'4e333f53ff42e928000007d8', None)
>>> input_to_object_id_str('4e333f53ff42e928000007d8')
('4e333f53ff42e928000007d8', None)
>>> input_to_object_id_str(u'4E333F53FF42E928000007D8')
(u'4e333f53ff42e928000007d8', None)
>>> input_to_object_id_str(u'   4e333f53ff42e928000007d8   ')
(u'4e333f53ff42e928000007d8', None)
>>> from bson.objectid import ObjectId
>>> input_to_object_id_str(ObjectId('4e333f53ff42e928000007d8'))
Traceback (most recent call last):
AttributeError:
>>> input_to_object_id_str(u"ObjectId('4e333f53ff42e928000007d8')")
(u"ObjectId('4e333f53ff42e928000007d8')", u'Invalid value')
>>> input_to_object_id_str(u'  ')
(None, None)
>>> input_to_object_id_str(None)
(None, None)
Traceback (most recent call last):
AttributeError:
biryani.bsonconv.json_to_bson(value, state=None)

Convert a JSON value to BSON.

A MongoDB document can’t have an item with a key containing a ”.”. So they are escaped with “%”.

>>> json_to_bson({'a': 1, 'b': [2, 3], 'c.d': {'e': 4}})
({'a': 1, 'b': [2, 3], 'c%2ed': {'e': 4}}, None)
>>> json_to_bson({})
({}, None)
>>> json_to_bson(None)
(None, None)
biryani.bsonconv.object_id_to_str(value, state=None)[source]

Convert a BSON ObjectId to unicode.

Note

To ensure that input value is an ObjectId, first use biryani.baseconv.test_isinstance().

>>> from bson.objectid import ObjectId
>>> object_id_to_str(ObjectId('4e333f53ff42e928000007d8'))
(u'4e333f53ff42e928000007d8', None)
>>> object_id_to_str(u'4e333f53ff42e928000007d8')
(u'4e333f53ff42e928000007d8', None)
>>> from biryani import baseconv as conv
>>> conv.pipe(conv.test_isinstance(ObjectId), object_id_to_str)(ObjectId('4e333f53ff42e928000007d8'))
(u'4e333f53ff42e928000007d8', None)
>>> conv.pipe(conv.test_isinstance(ObjectId), object_id_to_str)(u'4e333f53ff42e928000007d8')
(u'4e333f53ff42e928000007d8', u"Value is not an instance of <class 'bson.objectid.ObjectId'>")
>>> object_id_to_str(None)
(None, None)
biryani.bsonconv.str_to_object_id(*args, **kwargs)

Convert a clean string to a BSON ObjectId.

Note

For a converter that doesn’t require a clean string, see input_to_object_id().

Note

For a converter that doesn’t fail when input data is already an ObjectId, use anything_to_object_id().

>>> str_to_object_id(u'4e333f53ff42e928000007d8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> str_to_object_id('4e333f53ff42e928000007d8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> str_to_object_id(u'4E333F53FF42E928000007D8')
(ObjectId('4e333f53ff42e928000007d8'), None)
>>> from bson.objectid import ObjectId
>>> str_to_object_id(ObjectId('4e333f53ff42e928000007d8'))
Traceback (most recent call last):
AttributeError:
>>> str_to_object_id(u"ObjectId('4e333f53ff42e928000007d8')")
(u"ObjectId('4e333f53ff42e928000007d8')", u'Invalid value')
>>> str_to_object_id(None)
(None, None)
Traceback (most recent call last):
AttributeError:
biryani.bsonconv.str_to_object_id_str(value, state=None)[source]

Convert a clean string to a BSON ObjectId string.

Note

For a converter that doesn’t require a clean string, see input_to_object_id_str().

>>> str_to_object_id_str(u'4e333f53ff42e928000007d8')
(u'4e333f53ff42e928000007d8', None)
>>> str_to_object_id_str('4e333f53ff42e928000007d8')
('4e333f53ff42e928000007d8', None)
>>> str_to_object_id_str(u'4E333F53FF42E928000007D8')
(u'4e333f53ff42e928000007d8', None)
>>> from bson.objectid import ObjectId
>>> str_to_object_id_str(ObjectId('4e333f53ff42e928000007d8'))
Traceback (most recent call last):
AttributeError:
>>> str_to_object_id_str(u"ObjectId('4e333f53ff42e928000007d8')")
(u"ObjectId('4e333f53ff42e928000007d8')", u'Invalid value')
>>> str_to_object_id_str(None)
(None, None)
Traceback (most recent call last):
AttributeError:

biryani.creditcardconv

Converters for credit card types, numbers and expiration dates

Note

The idea of this module and its algorithms have been borrowed from FormEncode.

Sample usage:

>>> import pprint
>>> from biryani import baseconv, creditcardconv, custom_conv, states
...
>>> conv = custom_conv(baseconv, creditcardconv)
>>> N_ = lambda message: message
...
>>> def validate_credit_card(value, state = None):
...     import datetime
...
...     if value is None:
...         return None, None
...     if state is None:
...         state = states.default_state
...     errors = {}
...     today = datetime.date.today()
...     converted_value, error = conv.struct(
...         dict(
...             credit_card_type = conv.pipe(conv.input_to_credit_card_type, conv.not_none),
...             expiration_month = conv.pipe(
...                 conv.input_to_int,
...                 conv.test_between(1, 12, error = N_(u'Invalid expiration month')),
...                 conv.not_none,
...                 ),
...             expiration_year = conv.pipe(
...                 conv.input_to_int,
...                 conv.test_greater_or_equal(today.year, error = N_(u'Invalid expiration year')),
...                 conv.not_none,
...                 ),
...             ),
...         default = conv.noop,
...         )(value, state = state)
...     if error is not None:
...         errors.update(error)
...     if 'expiration_month' not in errors and 'expiration_year' not in errors:
...         expiration_year = converted_value['expiration_year']
...         expiration_month = converted_value['expiration_month'] + 1
...         if expiration_month > 12:
...             expiration_month = 1
...             expiration_year += 1
...         if datetime.date(expiration_year, expiration_month, 1) <= today:
...             errors['expiration_month'] = state._(u'Invalid expiration date')
...     if 'credit_card_type' in errors:
...         return converted_value, errors
...     credit_card_type = converted_value['credit_card_type']
...     converted_value, error = conv.struct(
...         dict(
...             credit_card_number = conv.pipe(
...                 conv.make_input_to_credit_card_number(credit_card_type),
...                 conv.not_none,
...                 ),
...             credit_card_security_code = conv.pipe(
...                 conv.make_input_to_credit_card_security_code(credit_card_type),
...                 conv.not_none,
...                 ),
...             ),
...         default = conv.noop,
...         )(converted_value, state = state)
...     if error is not None:
...         errors.update(error)
...     return converted_value, errors or None
>>> pprint.pprint(validate_credit_card(dict(
...     credit_card_type = u'Visa',
...     credit_card_number = u'4111 1111 1111 1111',
...     credit_card_security_code = u'123',
...     expiration_month = u'12',
...     expiration_year = u'2021',
...     )))
({'credit_card_number': u'4111111111111111',
  'credit_card_security_code': 123,
  'credit_card_type': u'visa',
  'expiration_month': 12,
  'expiration_year': 2021},
 None)
>>> pprint.pprint(validate_credit_card(dict(
...     credit_card_type = u'Visa',
...     credit_card_number = u'4111-1111-1111-1112',
...     credit_card_security_code = u'123',
...     expiration_month = u'12',
...     expiration_year = u'2021',
...     )))
({'credit_card_number': u'4111111111111112',
  'credit_card_security_code': 123,
  'credit_card_type': u'visa',
  'expiration_month': 12,
  'expiration_year': 2021},
 {'credit_card_number': u'Invalid credit card number (wrong checksum)'})
>>> pprint.pprint(validate_credit_card(dict(
...     credit_card_type = u'Visa',
...     credit_card_number = u'4111_1111_1111',
...     credit_card_security_code = u'1234',
...     expiration_month = u'7',
...     expiration_year = u'2011',
...     )))
({'credit_card_number': u'411111111111',
  'credit_card_security_code': u'1234',
  'credit_card_type': u'visa',
  'expiration_month': 7,
  'expiration_year': 2011},
 {'credit_card_number': u'Wrong number of digits in credit card number',
  'credit_card_security_code': u'Invalid security code for credit card',
  'expiration_year': u'Invalid expiration year'})
biryani.creditcardconv.input_to_credit_card_type(*args, **kwargs)
biryani.creditcardconv.make_input_to_credit_card_number(type)[source]

Return a converter that converts a string to a credit card number for a given credit card type.

>>> make_input_to_credit_card_number(u'visa')(u'4111111111111111')
(u'4111111111111111', None)
>>> make_input_to_credit_card_number(u'visa')(u'   4111 1111-1111.,1111   ')
(u'4111111111111111', None)
>>> make_input_to_credit_card_number(u'visa')(u'411111111111111')
(u'411111111111111', u'Wrong number of digits in credit card number')
>>> make_input_to_credit_card_number(u'visa')(u'4111111111111112')
(u'4111111111111112', u'Invalid credit card number (wrong checksum)')
>>> make_input_to_credit_card_number(u'visa')(u'5111111111111111')
(u'5111111111111111', u'Invalid credit card number (unknown prefix)')
>>> make_input_to_credit_card_number(u'visa')(u'')
(None, None)
>>> make_input_to_credit_card_number(u'visa')(u'   ')
(None, None)
>>> make_input_to_credit_card_number(u'visa')(None)
(None, None)
biryani.creditcardconv.make_input_to_credit_card_security_code(type)[source]

Return a converter that converts a string to a security code for a given type of credit card.

biryani.creditcardconv.make_str_to_credit_card_number(type)[source]

Return a converter that converts a clean string to a credit card number of a given type.

Note

For a converter that doesn’t require a clean string, see make_input_to_credit_card_number().

>>> make_str_to_credit_card_number(u'visa')(u'4111111111111111')
(u'4111111111111111', None)
>>> make_str_to_credit_card_number(u'visa')(u'   4111 1111-1111.,1111   ')
(u'4111111111111111', None)
>>> make_str_to_credit_card_number(u'visa')(u'411111111111111')
(u'411111111111111', u'Wrong number of digits in credit card number')
>>> make_str_to_credit_card_number(u'visa')(u'4111111111111112')
(u'4111111111111112', u'Invalid credit card number (wrong checksum)')
>>> make_str_to_credit_card_number(u'visa')(u'5111111111111111')
(u'5111111111111111', u'Invalid credit card number (unknown prefix)')
>>> make_str_to_credit_card_number(u'visa')(u'')
(u'', u'Credit card number must contain digits')
>>> make_str_to_credit_card_number(u'visa')(u'   ')
(u'', u'Credit card number must contain digits')
>>> make_str_to_credit_card_number(u'visa')(None)
(None, None)

biryani.datetimeconv

Date and Time Related Converters

Note

Date & time converters are not in biryani.baseconv, because some of them depend from external libraries (isodate & pytz).

biryani.datetimeconv.date_to_datetime(value, state=None)[source]

Convert a date object to a datetime.

>>> import datetime
>>> date_to_datetime(datetime.date(2012, 3, 4))
(datetime.datetime(2012, 3, 4, 0, 0), None)
>>> date_to_datetime(datetime.datetime(2012, 3, 4, 5, 6, 7))
(datetime.datetime(2012, 3, 4, 0, 0), None)
>>> date_to_datetime(None)
(None, None)
biryani.datetimeconv.date_to_iso8601_str(value, state=None)[source]

Convert a date to a string using ISO 8601 format.

>>> date_to_iso8601_str(datetime.date(2012, 3, 4))
(u'2012-03-04', None)
>>> date_to_iso8601_str(datetime.datetime(2012, 3, 4, 5, 6, 7))
(u'2012-03-04', None)
>>> date_to_iso8601_str(None)
(None, None)
biryani.datetimeconv.date_to_timestamp(value, state=None)[source]

Convert a datetime to a JavaScript timestamp.

>>> date_to_timestamp(datetime.date(2012, 3, 4))
(1330819200000, None)
>>> date_to_timestamp(datetime.datetime(2012, 3, 4, 5, 6, 7))
(1330837567000, None)
>>> date_to_timestamp(None)
(None, None)
biryani.datetimeconv.datetime_to_date(value, state=None)[source]

Convert a datetime object to a date.

>>> datetime_to_date(datetime.datetime(2012, 3, 4, 5, 6, 7))
(datetime.date(2012, 3, 4), None)
>>> datetime_to_date(datetime.date(2012, 3, 4))
Traceback (most recent call last):
AttributeError:
>>> datetime_to_date(None)
(None, None)
Traceback (most recent call last):
AttributeError:
biryani.datetimeconv.datetime_to_iso8601_str(value, state=None)[source]

Convert a datetime to a string using ISO 8601 format.

>>> datetime_to_iso8601_str(datetime.datetime(2012, 3, 4, 5, 6, 7))
(u'2012-03-04 05:06:07', None)
>>> datetime_to_iso8601_str(datetime.date(2012, 3, 4))
(u'2012-03-04 00:00:00', None)
>>> datetime_to_iso8601_str(None)
(None, None)
biryani.datetimeconv.datetime_to_timestamp(value, state=None)[source]

Convert a datetime to a JavaScript timestamp.

>>> datetime_to_timestamp(datetime.datetime(2012, 3, 4, 5, 6, 7))
(1330837567000, None)
>>> datetime_to_timestamp(datetime.date(2012, 3, 4))
(1330819200000, None)
>>> datetime_to_timestamp(None)
(None, None)
biryani.datetimeconv.iso8601_input_to_date(*args, **kwargs)

Convert a string in ISO 8601 format to a date.

>>> iso8601_input_to_date(u'2012-03-04')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'20120304')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'2012-03-04 05:06:07')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'2012-03-04T05:06:07')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'2012-03-04 05:06:07+01:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'2012-03-04 05:06:07-02:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'2012-03-04 05:06:07 +01:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'2012-03-04 05:06:07 -02:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'20120304 05:06:07')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'   2012-03-04   ')
(datetime.date(2012, 3, 4), None)
>>> iso8601_input_to_date(u'today')
(u'today', u'Value must be a date in ISO 8601 format')
>>> iso8601_input_to_date(u'   ')
(None, None)
>>> iso8601_input_to_date(None)
(None, None)
biryani.datetimeconv.iso8601_input_to_datetime(*args, **kwargs)

Convert a string in ISO 8601 format to a datetime.

>>> iso8601_input_to_datetime(u'2012-03-04')
(datetime.datetime(2012, 3, 4, 0, 0), None)
>>> iso8601_input_to_datetime(u'20120304')
(datetime.datetime(2012, 3, 4, 0, 0), None)
>>> iso8601_input_to_datetime(u'2012-03-04 05:06:07')
(datetime.datetime(2012, 3, 4, 5, 6, 7), None)
>>> iso8601_input_to_datetime(u'2012-03-04T05:06:07')
(datetime.datetime(2012, 3, 4, 5, 6, 7), None)
>>> iso8601_input_to_datetime(u'2012-03-04 05:06:07+01:00')
(datetime.datetime(2012, 3, 4, 4, 6, 7), None)
>>> iso8601_input_to_datetime(u'2012-03-04 05:06:07-02:00')
(datetime.datetime(2012, 3, 4, 7, 6, 7), None)
>>> iso8601_input_to_datetime(u'2012-03-04 05:06:07 +01:00')
(datetime.datetime(2012, 3, 4, 4, 6, 7), None)
>>> iso8601_input_to_datetime(u'2012-03-04 05:06:07 -02:00')
(datetime.datetime(2012, 3, 4, 7, 6, 7), None)
>>> iso8601_input_to_datetime(u'20120304 05:06:07')
(datetime.datetime(2012, 3, 4, 5, 6, 7), None)
>>> iso8601_input_to_datetime(u'   2012-03-04 05:06:07   ')
(datetime.datetime(2012, 3, 4, 5, 6, 7), None)
>>> iso8601_input_to_datetime(u'now')
(u'now', u'Value must be a date-time in ISO 8601 format')
>>> iso8601_input_to_datetime(u'   ')
(None, None)
>>> iso8601_input_to_datetime(None)
(None, None)
biryani.datetimeconv.iso8601_input_to_time(*args, **kwargs)

Convert a string in ISO 8601 format to a time.

>>> iso8601_input_to_time(u'05:06:07')
(datetime.time(5, 6, 7), None)
>>> iso8601_input_to_time(u'T05:06:07')
(datetime.time(5, 6, 7), None)
>>> iso8601_input_to_time(u'05:06:07+01:00')
(datetime.time(4, 6, 7), None)
>>> iso8601_input_to_time(u'05:06:07-02:00')
(datetime.time(7, 6, 7), None)
>>> iso8601_input_to_time(u'05:06:07 +01:00')
(datetime.time(4, 6, 7), None)
>>> iso8601_input_to_time(u'05:06:07 -02:00')
(datetime.time(7, 6, 7), None)
>>> iso8601_input_to_time(u'05:06:07')
(datetime.time(5, 6, 7), None)
>>> iso8601_input_to_time(u'   05:06:07   ')
(datetime.time(5, 6, 7), None)
>>> iso8601_input_to_time(u'now')
(u'now', u'Value must be a time in ISO 8601 format')
>>> iso8601_input_to_time(u'   ')
(None, None)
>>> iso8601_input_to_time(None)
(None, None)
biryani.datetimeconv.iso8601_str_to_date(value, state=None)[source]

Convert a clean string in ISO 8601 format to a date.

Note

For a converter that doesn’t require a clean string, see iso8601_input_to_date().

>>> iso8601_str_to_date(u'2012-03-04')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'20120304')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'2012-03-04 05:06:07')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'2012-03-04T05:06:07')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'2012-03-04 05:06:07+01:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'2012-03-04 05:06:07-02:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'2012-03-04 05:06:07 +01:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'2012-03-04 05:06:07 -02:00')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'20120304 05:06:07')
(datetime.date(2012, 3, 4), None)
>>> iso8601_str_to_date(u'today')
(u'today', u'Value must be a date in ISO 8601 format')
>>> iso8601_str_to_date(u'')
(u'', u'Value must be a date in ISO 8601 format')
>>> iso8601_str_to_date(None)
(None, None)
biryani.datetimeconv.iso8601_str_to_datetime(value, state=None)[source]

Convert a clean string in ISO 8601 format to a datetime.

Note

For a converter that doesn’t require a clean string, see iso8601_input_to_datetime().

>>> iso8601_str_to_datetime(u'2012-03-04')
(datetime.datetime(2012, 3, 4, 0, 0), None)
>>> iso8601_str_to_datetime(u'20120304')
(datetime.datetime(2012, 3, 4, 0, 0), None)
>>> iso8601_str_to_datetime(u'2012-03-04 05:06:07')
(datetime.datetime(2012, 3, 4, 5, 6, 7), None)
>>> iso8601_str_to_datetime(u'2012-03-04T05:06:07')
(datetime.datetime(2012, 3, 4, 5, 6, 7), None)
>>> iso8601_str_to_datetime(u'2012-03-04 05:06:07+01:00')
(datetime.datetime(2012, 3, 4, 4, 6, 7), None)
>>> iso8601_str_to_datetime(u'2012-03-04 05:06:07-02:00')
(datetime.datetime(2012, 3, 4, 7, 6, 7), None)
>>> iso8601_str_to_datetime(u'2012-03-04 05:06:07 +01:00')
(datetime.datetime(2012, 3, 4, 4, 6, 7), None)
>>> iso8601_str_to_datetime(u'2012-03-04 05:06:07 -02:00')
(datetime.datetime(2012, 3, 4, 7, 6, 7), None)
>>> iso8601_str_to_datetime(u'20120304 05:06:07')
(datetime.datetime(2012, 3, 4, 5, 6, 7), None)
>>> iso8601_str_to_datetime(u'now')
(u'now', u'Value must be a date-time in ISO 8601 format')
>>> iso8601_str_to_datetime(u'')
(u'', u'Value must be a date-time in ISO 8601 format')
>>> iso8601_str_to_datetime(None)
(None, None)
biryani.datetimeconv.iso8601_str_to_time(value, state=None)[source]

Convert a clean string in ISO 8601 format to a time.

Note

For a converter that doesn’t require a clean string, see iso8601_input_to_time().

>>> iso8601_str_to_time(u'05:06:07')
(datetime.time(5, 6, 7), None)
>>> iso8601_str_to_time(u'T05:06:07')
(datetime.time(5, 6, 7), None)
>>> iso8601_str_to_time(u'05:06:07+01:00')
(datetime.time(4, 6, 7), None)
>>> iso8601_str_to_time(u'05:06:07-02:00')
(datetime.time(7, 6, 7), None)
>>> iso8601_str_to_time(u'05:06:07 +01:00')
(datetime.time(4, 6, 7), None)
>>> iso8601_str_to_time(u'05:06:07 -02:00')
(datetime.time(7, 6, 7), None)
>>> iso8601_str_to_time(u'05:06:07')
(datetime.time(5, 6, 7), None)
>>> iso8601_str_to_time(u'now')
(u'now', u'Value must be a time in ISO 8601 format')
>>> iso8601_str_to_time(u'')
(u'', u'Value must be a time in ISO 8601 format')
>>> iso8601_str_to_time(None)
(None, None)
biryani.datetimeconv.set_datetime_tzinfo(tzinfo=None)[source]

Return a converter that sets or clears the field tzinfo of a datetime.

>>> import datetime, pytz
>>> set_datetime_tzinfo()(datetime.datetime(2011, 1, 2, 3, 4, 5))
(datetime.datetime(2011, 1, 2, 3, 4, 5), None)
>>> datetime.datetime(2011, 1, 2, 3, 4, 5, tzinfo = pytz.utc)
datetime.datetime(2011, 1, 2, 3, 4, 5, tzinfo=<UTC>)
>>> set_datetime_tzinfo()(datetime.datetime(2011, 1, 2, 3, 4, 5, tzinfo = pytz.utc))
(datetime.datetime(2011, 1, 2, 3, 4, 5), None)
>>> set_datetime_tzinfo(pytz.utc)(datetime.datetime(2011, 1, 2, 3, 4, 5))
(datetime.datetime(2011, 1, 2, 3, 4, 5, tzinfo=<UTC>), None)
biryani.datetimeconv.time_to_iso8601_str(value, state=None)[source]

Convert a time to a string using ISO 8601 format.

>>> time_to_iso8601_str(datetime.time(5, 6, 7))
(u'05:06:07', None)
>>> time_to_iso8601_str(None)
(None, None)
biryani.datetimeconv.timestamp_to_date(value, state=None)[source]

Convert a JavaScript timestamp to a date.

>>> timestamp_to_date(123456789.123)
(datetime.date(1970, 1, 2), None)
>>> timestamp_to_date(u'123456789.123')
Traceback (most recent call last):
TypeError:
>>> pipe(input_to_float, timestamp_to_date)(u'123456789.123')
(datetime.date(1970, 1, 2), None)
>>> timestamp_to_date(None)
(None, None)
Traceback (most recent call last):
TypeError:
biryani.datetimeconv.timestamp_to_datetime(value, state=None)[source]

Convert a JavaScript timestamp to a datetime.

Note

Since a timestamp has no timezone, the generated datetime has no tzinfo attribute. Use set_datetime_tzinfo() to add one.

>>> timestamp_to_datetime(123456789.123)
(datetime.datetime(1970, 1, 2, 11, 17, 36, 789123), None)
>>> import pytz
>>> pipe(timestamp_to_datetime, set_datetime_tzinfo(pytz.utc))(123456789.123)
(datetime.datetime(1970, 1, 2, 11, 17, 36, 789123, tzinfo=<UTC>), None)
>>> timestamp_to_datetime(u'123456789.123')
Traceback (most recent call last):
TypeError:
>>> pipe(input_to_float, timestamp_to_datetime)(u'123456789.123')
(datetime.datetime(1970, 1, 2, 11, 17, 36, 789123), None)
>>> timestamp_to_datetime(None)
(None, None)
Traceback (most recent call last):
TypeError:

biryani.jsonconv

JSON Related Converters

biryani.jsonconv.make_input_to_json(*args, **kwargs)[source]

Return a converter that decodes a string to a JSON data.

>>> make_input_to_json()(u'{"a": 1, "b": [2, "three"]}')
({u'a': 1, u'b': [2, u'three']}, None)
>>> make_input_to_json()(u'null')
(None, None)
>>> make_input_to_json()(u'Hello World')
(u'Hello World', u'Invalid JSON')
>>> make_input_to_json()(u'{"a": 1, "b":')
(u'{"a": 1, "b":', u'Invalid JSON')
>>> make_input_to_json()(u'')
(None, None)
>>> make_input_to_json()(None)
(None, None)
biryani.jsonconv.make_json_to_str(*args, **kwargs)[source]

Return a converter that encodes a JSON data to a string.

>>> make_json_to_str()({u'a': 1, u'b': [2, u'three']})
(u'{"a": 1, "b": [2, "three"]}', None)
>>> make_json_to_str()(u'Hello World')
(u'"Hello World"', None)
>>> make_json_to_str(ensure_ascii = False, indent = 2, sort_keys = True)({u'a': 1, u'b': [2, u'three']})
(u'{\n  "a": 1, \n  "b": [\n    2, \n    "three"\n  ]\n}', None)
>>> make_json_to_str()(set([1, 2, 3]))
(set([1, 2, 3]), u'Invalid JSON')
>>> make_json_to_str()(u'')
(u'""', None)
>>> make_json_to_str()(None)
(None, None)
biryani.jsonconv.make_str_to_json(*args, **kwargs)[source]

Return a converter that decodes a clean string to a JSON data.

Note

For a converter that doesn’t require a clean string, see make_input_to_json().

>>> make_str_to_json()(u'{"a": 1, "b": [2, "three"]}')
({u'a': 1, u'b': [2, u'three']}, None)
>>> make_str_to_json()(u'null')
(None, None)
>>> make_str_to_json()(u'Hello World')
(u'Hello World', u'Invalid JSON')
>>> make_str_to_json()(u'{"a": 1, "b":')
(u'{"a": 1, "b":', u'Invalid JSON')
>>> make_str_to_json()(u'')
(u'', u'Invalid JSON')
>>> make_str_to_json()(None)
(None, None)

biryani.jwkconv

Converters for JSON Web Keys (JWK)

biryani.jwkconv.json_to_json_web_key(*args, **kwargs)

Verify that given JSON is a valid JSON Web Key object.

A JWK Key Object is a JSON object that represents a single public key.

biryani.jwkconv.json_to_json_web_key_set(*args, **kwargs)

Verify that given JSON is a valid JSON Web Key.

>>> from pprint import pprint
>>> pprint(json_to_json_web_key_set({'jwk': [{
...     'alg': u'EC',
...     'crv': u'P-256',
...     'kid': u'1',
...     'use': u'enc',
...     'x': u'MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4',
...     'y': u'4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM',
...     }]}))
({'jwk': [{'alg': u'EC',
           'crv': u'P-256',
           'kid': u'1',
           'use': u'enc',
           'x': u'MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4',
           'y': u'4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM'}]},
 None)
>>> from biryani.jsonconv import make_input_to_json
>>> pprint(conv.pipe(make_input_to_json(), json_to_json_web_key_set)('''
... {"jwk":
...   [
...     {"alg":"EC",
...      "crv":"P-256",
...      "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
...      "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
...      "use":"enc",
...      "kid":"1"},
...     {"alg":"RSA",
...      "mod": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
...      "exp":"AQAB",
...      "kid":"2011-04-29"}
...   ]
... }
... '''))
({'jwk': [{'alg': u'EC',
           'crv': u'P-256',
           'kid': u'1',
           'use': u'enc',
           'x': u'MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4',
           'y': u'4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM'},
          {'alg': u'RSA',
           'exp': u'AQAB',
           'kid': u'2011-04-29',
           'mod': u'0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw',
           'use': None}]},
 None)

biryani.jwtconv

Converters for JSON Web Tokens (JWT)

cf http://tools.ietf.org/html/draft-jones-json-web-token

biryani.jwtconv.decode_json_web_token(token, state=None)[source]

Decode a JSON Web Token, without converting payload to JSON claims, nor verifying its content.

biryani.jwtconv.decode_json_web_token_claims(decoded_token, state=None)[source]
biryani.jwtconv.decoded_json_web_token_to_json(value, state=None)
biryani.jwtconv.decrypt_json_web_token(private_key=None, require_encrypted_token=False, shared_secret=None)[source]

Return a converter that decrypts a JSON Web Token and returns a non crypted JSON Web Token.

>>> from Crypto.PublicKey import RSA
>>> from Crypto.Util import number
>>> # Mike Jones Test 1
>>> plaintext_bytes_list = [78, 111, 119, 32, 105, 115, 32, 116, 104, 101, 32, 116, 105, 109, 101, 32,
...    102, 111, 114, 32, 97, 108, 108, 32, 103, 111, 111, 100, 32, 109, 101, 110,
...    32, 116, 111, 32, 99, 111, 109, 101, 32, 116, 111, 32, 116, 104, 101, 32,
...    97, 105, 100, 32, 111, 102, 32, 116, 104, 101, 105, 114, 32, 99, 111, 117,
...    110, 116, 114, 121, 46]
>>> plaintext = ''.join(chr(byte) for byte in plaintext_bytes_list)
>>> jwt = check(make_payload_to_json_web_token())(plaintext)
>>> jwt
'eyJhbGciOiJub25lIn0.Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBtZW4gdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku.'
>>> cmk_bytes_list = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206,
...     107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207]
>>> cmk = ''.join(chr(byte) for byte in cmk_bytes_list)
>>> iv_bytes_list = [3, 22, 60, 12, 43, 67, 104, 105, 108, 108, 105, 99, 111, 116, 104, 101]
>>> iv = ''.join(chr(byte) for byte in iv_bytes_list)
>>> key_modulus_bytes_list = [177, 119, 33, 13, 164, 30, 108, 121, 207, 136, 107, 242, 12, 224, 19, 226,
...    198, 134, 17, 71, 173, 75, 42, 61, 48, 162, 206, 161, 97, 108, 185, 234,
...    226, 219, 118, 206, 118, 5, 169, 224, 60, 181, 90, 85, 51, 123, 6, 224,
...    4, 122, 29, 230, 151, 12, 244, 127, 121, 25, 4, 85, 220, 144, 215, 110,
...    130, 17, 68, 228, 129, 138, 7, 130, 231, 40, 212, 214, 17, 179, 28, 124,
...    151, 178, 207, 20, 14, 154, 222, 113, 176, 24, 198, 73, 211, 113, 9, 33,
...    178, 80, 13, 25, 21, 25, 153, 212, 206, 67, 154, 147, 70, 194, 192, 183,
...    160, 83, 98, 236, 175, 85, 23, 97, 75, 199, 177, 73, 145, 50, 253, 206,
...    32, 179, 254, 236, 190, 82, 73, 67, 129, 253, 252, 220, 108, 136, 138, 11,
...    192, 1, 36, 239, 228, 55, 81, 113, 17, 25, 140, 63, 239, 146, 3, 172,
...    96, 60, 227, 233, 64, 255, 224, 173, 225, 228, 229, 92, 112, 72, 99, 97,
...    26, 87, 187, 123, 46, 50, 90, 202, 117, 73, 10, 153, 47, 224, 178, 163,
...    77, 48, 46, 154, 33, 148, 34, 228, 33, 172, 216, 89, 46, 225, 127, 68,
...    146, 234, 30, 147, 54, 146, 5, 133, 45, 78, 254, 85, 55, 75, 213, 86,
...    194, 218, 215, 163, 189, 194, 54, 6, 83, 36, 18, 153, 53, 7, 48, 89,
...    35, 66, 144, 7, 65, 154, 13, 97, 75, 55, 230, 132, 3, 13, 239, 71]
>>> key_modulus = ''.join(chr(byte) for byte in key_modulus_bytes_list)
>>> key_public_exponent_bytes_list = [1, 0, 1]
>>> key_public_exponent = ''.join(chr(byte) for byte in key_public_exponent_bytes_list)
>>> public_key = RSA.construct((number.bytes_to_long(key_modulus),
...     number.bytes_to_long(key_public_exponent)))
>>> public_key_as_encoded_str = public_key.exportKey()
>>> print public_key_as_encoded_str
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsXchDaQebHnPiGvyDOAT
4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1WlUzewbgBHod5pcM9H95GQRV3JDX
boIRROSBigeC5yjU1hGzHHyXss8UDprecbAYxknTcQkhslANGRUZmdTOQ5qTRsLA
t6BTYuyvVRdhS8exSZEy/c4gs/7svlJJQ4H9/NxsiIoLwAEk7+Q3UXERGYw/75ID
rGA84+lA/+Ct4eTlXHBIY2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF/
RJLqHpM2kgWFLU7+VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN+aEAw3v
RwIDAQAB
-----END PUBLIC KEY-----
>>> encrypted_key_bytes_list = [32, 242, 63, 207, 94, 246, 133, 37, 135, 48, 88, 4, 15, 193, 6, 244,
...     51, 58, 132, 133, 212, 255, 163, 90, 59, 80, 200, 152, 41, 244, 188, 215,
...     174, 160, 26, 188, 227, 180, 165, 234, 172, 63, 24, 116, 152, 28, 149, 16,
...     94, 213, 201, 171, 180, 191, 11, 21, 149, 172, 143, 54, 194, 58, 206, 201,
...     164, 28, 107, 155, 75, 101, 22, 92, 227, 144, 95, 40, 119, 170, 7, 36,
...     225, 40, 141, 186, 213, 7, 175, 16, 174, 122, 75, 32, 48, 193, 119, 202,
...     41, 152, 210, 190, 68, 57, 119, 4, 197, 74, 7, 242, 239, 170, 204, 73,
...     75, 213, 202, 113, 216, 18, 23, 66, 106, 208, 69, 244, 117, 147, 2, 37,
...     207, 199, 184, 96, 102, 44, 70, 212, 87, 143, 253, 0, 166, 59, 41, 115,
...     217, 80, 165, 87, 38, 5, 9, 184, 202, 68, 67, 176, 4, 87, 254, 166,
...     227, 88, 124, 238, 249, 75, 114, 205, 148, 149, 45, 78, 193, 134, 64, 189,
...     168, 76, 170, 76, 176, 72, 148, 77, 215, 159, 146, 55, 189, 213, 85, 253,
...     135, 200, 59, 247, 79, 37, 22, 200, 32, 110, 53, 123, 54, 39, 9, 178,
...     231, 238, 95, 25, 211, 143, 87, 220, 88, 138, 209, 13, 227, 72, 58, 102,
...     164, 136, 241, 14, 14, 45, 32, 77, 44, 244, 162, 239, 150, 248, 181, 138,
...     251, 116, 245, 205, 137, 78, 34, 34, 10, 6, 59, 4, 197, 2, 153, 251]
>>> encrypted_key = ''.join(chr(byte) for byte in encrypted_key_bytes_list)
>>> encryptor = encrypt_json_web_token(algorithm = 'RSA1_5', content_master_key = cmk,
...     encrypted_key = encrypted_key, initialization_vector = iv, integrity = 'HS256', method = 'A128CBC',
...     public_key_as_encoded_str = public_key_as_encoded_str)
>>> jwe = check(encryptor)(jwt)
>>> jwe
'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDIiwiaW50IjoiSFMyNTYiLCJpdiI6IkF4WThEQ3REYUdsc2JHbGpiM1JvWlEifQ.IPI_z172hSWHMFgED8EG9DM6hIXU_6NaO1DImCn0vNeuoBq847Sl6qw_GHSYHJUQXtXJq7S_CxWVrI82wjrOyaQca5tLZRZc45BfKHeqByThKI261QevEK56SyAwwXfKKZjSvkQ5dwTFSgfy76rMSUvVynHYEhdCatBF9HWTAiXPx7hgZixG1FeP_QCmOylz2VClVyYFCbjKREOwBFf-puNYfO75S3LNlJUtTsGGQL2oTKpMsEiUTdefkje91VX9h8g7908lFsggbjV7NicJsufuXxnTj1fcWIrRDeNIOmakiPEODi0gTSz0ou-W-LWK-3T1zYlOIiIKBjsExQKZ-w._Z_djlIoC4MDSCKireWS2beti4Q6iSG2UjFujQvdz-_PQdUcFNkOulegD6BgjgdFLjeB4HHOO7UHvP8PEDu0a0sA2a_-CI0w2YQQ2QQe35M.c41k4T4eAgCCt63m8ZNmiOinMciFFypOFpvid7i6D0k'
>>> key_private_exponent_bytes_list = [84, 80, 150, 58, 165, 235, 242, 123, 217, 55, 38, 154, 36, 181, 221, 156,
...    211, 215, 100, 164, 90, 88, 40, 228, 83, 148, 54, 122, 4, 16, 165, 48,
...    76, 194, 26, 107, 51, 53, 179, 165, 31, 18, 198, 173, 78, 61, 56, 97,
...    252, 158, 140, 80, 63, 25, 223, 156, 36, 203, 214, 252, 120, 67, 180, 167,
...    3, 82, 243, 25, 97, 214, 83, 133, 69, 16, 104, 54, 160, 200, 41, 83,
...    164, 187, 70, 153, 111, 234, 242, 158, 175, 28, 198, 48, 211, 45, 148, 58,
...    23, 62, 227, 74, 52, 117, 42, 90, 41, 249, 130, 154, 80, 119, 61, 26,
...    193, 40, 125, 10, 152, 174, 227, 225, 205, 32, 62, 66, 6, 163, 100, 99,
...    219, 19, 253, 25, 105, 80, 201, 29, 252, 157, 237, 69, 1, 80, 171, 167,
...    20, 196, 156, 109, 249, 88, 0, 3, 152, 38, 165, 72, 87, 6, 152, 71,
...    156, 214, 16, 71, 30, 82, 51, 103, 76, 218, 63, 9, 84, 163, 249, 91,
...    215, 44, 238, 85, 101, 240, 148, 1, 82, 224, 91, 135, 105, 127, 84, 171,
...    181, 152, 210, 183, 126, 24, 46, 196, 90, 173, 38, 245, 219, 186, 222, 27,
...    240, 212, 194, 15, 66, 135, 226, 178, 190, 52, 245, 74, 65, 224, 81, 100,
...    85, 25, 204, 165, 203, 187, 175, 84, 100, 82, 15, 11, 23, 202, 151, 107,
...    54, 41, 207, 3, 136, 229, 134, 131, 93, 139, 50, 182, 204, 93, 130, 89]
>>> key_private_exponent = ''.join(chr(byte) for byte in key_private_exponent_bytes_list)
>>> private_key = RSA.construct((number.bytes_to_long(key_modulus),
...     number.bytes_to_long(key_public_exponent), number.bytes_to_long(key_private_exponent)))
>>> private_key_as_encoded_str = private_key.exportKey()
>>> print private_key_as_encoded_str
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bO
dgWp4Dy1WlUzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8U
DprecbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy/c4gs/7s
vlJJQ4H9/NxsiIoLwAEk7+Q3UXERGYw/75IDrGA84+lA/+Ct4eTlXHBIY2EaV7t7
LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF/RJLqHpM2kgWFLU7+VTdL1VbC2tej
vcI2BlMkEpk1BzBZI0KQB0GaDWFLN+aEAw3vRwIDAQABAoIBAFRQljql6/J72Tcm
miS13ZzT12SkWlgo5FOUNnoEEKUwTMIaazM1s6UfEsatTj04YfyejFA/Gd+cJMvW
/HhDtKcDUvMZYdZThUUQaDagyClTpLtGmW/q8p6vHMYw0y2UOhc+40o0dSpaKfmC
mlB3PRrBKH0KmK7j4c0gPkIGo2Rj2xP9GWlQyR38ne1FAVCrpxTEnG35WAADmCal
SFcGmEec1hBHHlIzZ0zaPwlUo/lb1yzuVWXwlAFS4FuHaX9Uq7WY0rd+GC7EWq0m
9du63hvw1MIPQofisr409UpB4FFkVRnMpcu7r1RkUg8LF8qXazYpzwOI5YaDXYsy
tsxdglkCgYEAuKlCKvKv/ZJMVcdIs5vVSU/6cPtYI1ljWytExV/skstvRSNi9r66
jdd9+yBhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw+MVsN
+3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0CgYEA9gY2
w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68ik918hdDSE
9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X+xcPWlEPkrdoUKW60tgs1aNd
/Nnc9LEVVPMS390zbFxt8TN/biaBgelNgbC95sMCgYEAo/8V14SezckO6CNLKs/b
tPdFiO9/kC1DsuUTd2LAfIIVeMZ7jn1Gus/Ff7B7IVx3p5KuBGOVF8L+qifLb6nQ
nLysgHDh132NDioZkhH7mI7hPG+PYE/odApKdnqECHWw0J+F0JWnUd6D2B/1TvF9
mXA2Qx+iGYn8OVV1Bsmp6qUCgYEAw0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1l
mMSYhG4EcL6FWbX5h9yuvngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH/zKI+hwoRe
oP77cOdSL4AVcraHawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk+RR
3pEhnCsCgYBd9Pl1dGQ/4PlGika1bezRFWlnNnPxIHPWrnWRxBCKYr+lycWOUPk1
clEAVQXzLHVIigANNKdVH6h4PfI/mgcrzkQnYCaBv68CjX2Rv9r42T6P2DALQfT+
2vQxZSMnRNS2mCV8et5ZnWcjHV9kN1aEjVU/o8fDuia+fAaDbe190g==
-----END RSA PRIVATE KEY-----
>>> decryptor = decrypt_json_web_token(private_key = private_key_as_encoded_str)
>>> decrypted_jwt = check(decryptor)(jwe)
>>> decrypted_jwt
'eyJhbGciOiJub25lIn0.Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBtZW4gdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku.'
>>> decrypted_jwt == jwt
True
>>> decoded_jwt = check(decode_json_web_token)(decrypted_jwt)
>>> decoded_jwt['payload']
'Now is the time for all good men to come to the aid of their country.'
>>> decoded_jwt['payload'] == plaintext
True
>>> # Same test with random keys.
>>> encryptor = encrypt_json_web_token(algorithm = 'RSA1_5', integrity = 'HS256', method = 'A128CBC',
...     public_key_as_encoded_str = public_key_as_encoded_str)
>>> jwe = check(encryptor)(jwt)
>>> decryptor = decrypt_json_web_token(private_key = private_key_as_encoded_str)
>>> decrypted_jwt = check(decryptor)(jwe)
>>> decrypted_jwt
'eyJhbGciOiJub25lIn0.Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBtZW4gdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku.'
>>> decrypted_jwt == jwt
True
>>> # Mike Jones Test 2
>>> plaintext_bytes_list = [76, 105, 118, 101, 32, 108, 111, 110, 103, 32, 97, 110, 100, 32, 112, 114,
...     111, 115, 112, 101, 114, 46]
>>> plaintext = ''.join(chr(byte) for byte in plaintext_bytes_list)
>>> jwt = check(make_payload_to_json_web_token())(plaintext)
>>> cmk_bytes_list = [177, 161, 244, 128, 84, 143, 225, 115, 63, 180, 3, 255, 107, 154, 212, 246,
...     138, 7, 110, 91, 112, 46, 34, 105, 47, 130, 203, 46, 122, 234, 64, 252]
>>> cmk = ''.join(chr(byte) for byte in cmk_bytes_list)
>>> iv_bytes_list = [227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219]
>>> iv = ''.join(chr(byte) for byte in iv_bytes_list)
>>> key_modulus_bytes_list = [161, 168, 84, 34, 133, 176, 208, 173, 46, 176, 163, 110, 57, 30, 135, 227,
...     9, 31, 226, 128, 84, 92, 116, 241, 70, 248, 27, 227, 193, 62, 5, 91,
...     241, 145, 224, 205, 141, 176, 184, 133, 239, 43, 81, 103, 9, 161, 153, 157,
...     179, 104, 123, 51, 189, 34, 152, 69, 97, 69, 78, 93, 140, 131, 87, 182,
...     169, 101, 92, 142, 3, 22, 167, 8, 212, 56, 35, 79, 210, 222, 192, 208,
...     252, 49, 109, 138, 173, 253, 210, 166, 201, 63, 102, 74, 5, 158, 41, 90,
...     144, 108, 160, 79, 10, 89, 222, 231, 172, 31, 227, 197, 0, 19, 72, 81,
...     138, 78, 136, 221, 121, 118, 196, 17, 146, 10, 244, 188, 72, 113, 55, 221,
...     162, 217, 171, 27, 57, 233, 210, 101, 236, 154, 199, 56, 138, 239, 101, 48,
...     198, 186, 202, 160, 76, 111, 234, 71, 57, 183, 5, 211, 171, 136, 126, 64,
...     40, 75, 58, 89, 244, 254, 107, 84, 103, 7, 236, 69, 163, 18, 180, 251,
...     58, 153, 46, 151, 174, 12, 103, 197, 181, 161, 162, 55, 250, 235, 123, 110,
...     17, 11, 158, 24, 47, 133, 8, 199, 235, 107, 126, 130, 246, 73, 195, 20,
...     108, 202, 176, 214, 187, 45, 146, 182, 118, 54, 32, 200, 61, 201, 71, 243,
...     1, 255, 131, 84, 37, 111, 211, 168, 228, 45, 192, 118, 27, 197, 235, 232,
...     36, 10, 230, 248, 190, 82, 182, 140, 35, 204, 108, 190, 253, 186, 186, 27]
>>> key_modulus = ''.join(chr(byte) for byte in key_modulus_bytes_list)
>>> key_public_exponent_bytes_list = [1, 0, 1]
>>> key_public_exponent = ''.join(chr(byte) for byte in key_public_exponent_bytes_list)
>>> public_key = RSA.construct((number.bytes_to_long(key_modulus),
...     number.bytes_to_long(key_public_exponent)))
>>> public_key_as_encoded_str = public_key.exportKey()
>>> encrypted_key_bytes_list = [142, 252, 40, 202, 21, 177, 56, 198, 232, 7, 151, 49, 95, 169, 220, 2,
...     46, 214, 167, 116, 57, 20, 164, 109, 150, 98, 49, 223, 154, 95, 71, 209,
...     233, 17, 174, 142, 203, 232, 132, 167, 17, 42, 51, 125, 22, 221, 135, 17,
...     67, 197, 148, 246, 139, 145, 160, 238, 99, 119, 171, 95, 117, 202, 87, 251,
...     101, 254, 58, 215, 135, 195, 135, 103, 49, 119, 76, 46, 49, 198, 27, 31,
...     58, 44, 192, 222, 21, 16, 13, 216, 161, 179, 236, 65, 143, 38, 43, 218,
...     195, 76, 140, 243, 71, 243, 79, 124, 216, 208, 242, 171, 34, 245, 57, 154,
...     93, 76, 230, 204, 234, 82, 117, 248, 39, 13, 62, 60, 215, 8, 51, 248,
...     254, 47, 150, 36, 46, 27, 247, 98, 77, 56, 92, 44, 19, 39, 12, 77,
...     54, 101, 194, 126, 86, 0, 64, 239, 95, 211, 64, 26, 219, 93, 211, 36,
...     154, 250, 117, 177, 213, 232, 142, 184, 216, 92, 20, 248, 69, 175, 180, 71,
...     205, 221, 235, 224, 95, 113, 5, 33, 86, 18, 157, 61, 199, 8, 121, 0,
...     0, 135, 65, 67, 220, 164, 15, 230, 155, 71, 53, 64, 253, 209, 169, 255,
...     34, 64, 101, 7, 43, 102, 227, 83, 171, 52, 225, 119, 253, 182, 96, 195,
...     225, 34, 156, 211, 202, 7, 194, 255, 137, 59, 170, 172, 72, 234, 222, 203,
...     123, 249, 121, 254, 143, 173, 105, 65, 187, 189, 163, 64, 151, 145, 99, 17]
>>> encrypted_key = ''.join(chr(byte) for byte in encrypted_key_bytes_list)
>>> encryptor = encrypt_json_web_token(algorithm = 'RSA-OAEP', content_master_key = cmk,
...     encrypted_key = encrypted_key, initialization_vector = iv, method = 'A256GCM',
...     public_key_as_encoded_str = public_key_as_encoded_str)
>>> jwe = check(encryptor)(jwt)
>>> jwe
'eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJpdiI6IjQ4VjFfQUxiNlVTMDRVM2IifQ.jvwoyhWxOMboB5cxX6ncAi7Wp3Q5FKRtlmIx35pfR9HpEa6Oy-iEpxEqM30W3YcRQ8WU9ouRoO5jd6tfdcpX-2X-OteHw4dnMXdMLjHGGx86LMDeFRAN2KGz7EGPJivaw0yM80fzT3zY0PKrIvU5ml1M5szqUnX4Jw0-PNcIM_j-L5YkLhv3Yk04XCwTJwxNNmXCflYAQO9f00Aa213TJJr6dbHV6I642FwU-EWvtEfN3evgX3EFIVYSnT3HCHkAAIdBQ9ykD-abRzVA_dGp_yJAZQcrZuNTqzThd_22YMPhIpzTygfC_4k7qqxI6t7Le_l5_o-taUG7vaNAl5FjEQ._e21tGGhac_peEFkLXr2dMPUZiUkrw.YbZSeHCNDZBqAdzpROlyiw'
>>> key_private_exponent_bytes_list = [144, 183, 109, 34, 62, 134, 108, 57, 44, 252, 10, 66, 73, 54, 16, 181,
...     233, 92, 54, 219, 101, 42, 35, 178, 63, 51, 43, 92, 119, 136, 251, 41,
...     53, 23, 191, 164, 164, 60, 88, 227, 229, 152, 228, 213, 149, 228, 169, 237,
...     104, 71, 151, 75, 88, 252, 216, 77, 251, 231, 28, 97, 88, 193, 215, 202,
...     248, 216, 121, 195, 211, 245, 250, 112, 71, 243, 61, 129, 95, 39, 244, 122,
...     225, 217, 169, 211, 165, 48, 253, 220, 59, 122, 219, 42, 86, 223, 32, 236,
...     39, 48, 103, 78, 122, 216, 187, 88, 176, 89, 24, 1, 42, 177, 24, 99,
...     142, 170, 1, 146, 43, 3, 108, 64, 194, 121, 182, 95, 187, 134, 71, 88,
...     96, 134, 74, 131, 167, 69, 106, 143, 121, 27, 72, 44, 245, 95, 39, 194,
...     179, 175, 203, 122, 16, 112, 183, 17, 200, 202, 31, 17, 138, 156, 184, 210,
...     157, 184, 154, 131, 128, 110, 12, 85, 195, 122, 241, 79, 251, 229, 183, 117,
...     21, 123, 133, 142, 220, 153, 9, 59, 57, 105, 81, 255, 138, 77, 82, 54,
...     62, 216, 38, 249, 208, 17, 197, 49, 45, 19, 232, 157, 251, 131, 137, 175,
...     72, 126, 43, 229, 69, 179, 117, 82, 157, 213, 83, 35, 57, 210, 197, 252,
...     171, 143, 194, 11, 47, 163, 6, 253, 75, 252, 96, 11, 187, 84, 130, 210,
...     7, 121, 78, 91, 79, 57, 251, 138, 132, 220, 60, 224, 173, 56, 224, 201]
>>> key_private_exponent = ''.join(chr(byte) for byte in key_private_exponent_bytes_list)
>>> private_key = RSA.construct((number.bytes_to_long(key_modulus),
...     number.bytes_to_long(key_public_exponent), number.bytes_to_long(key_private_exponent)))
>>> private_key_as_encoded_str = private_key.exportKey()
>>> decryptor = decrypt_json_web_token(private_key = private_key_as_encoded_str)
>>> decrypted_jwt = check(decryptor)(jwe)
>>> decrypted_jwt == jwt
True
>>> decoded_jwt = check(decode_json_web_token)(decrypted_jwt)
>>> decoded_jwt['payload']
'Live long and prosper.'
>>> decoded_jwt['payload'] == plaintext
True
>>> # Mike Jones Test 3:  RSA-OAEP/AES-GSM
>>> jwe = 'eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJpdiI6Il9fNzlfUHY2LWZqMzl2WDAifQ.LX4rQictZUJSYrVH3-TmCeH08qlpMrbFpKhEBVyAFX6h4V3Xt6omuTyMmkeiMIR6gbkn9ww4A0xDRnRu2GuM-v30Ri6OHx04fP1l1osYRngALuzMplcreyFCErm5asXTghweg_oI2y6ffhgR8P0ONWSlv0Bg-y58nAiNMi9Z51P42sx1f2JknAhG_oJ2u4Dy-6xY3tWCS4hXolMt5NMZm1dUN56RKvGlp-nspa9mYONfV-CITnjA3zMVWGdpTF4SXNq0fK5gWM3CgxJEtuW1gk69q9k_zOAEqCph_urnx0T7_6ZaBa90nV3TvX0cC5bq75alEqGWkqJLwTMsEnAg-A.ykqmBHvu8Yhqf5jafmUKcgDY8kZ0vw._3cYrFHM7X640lLd_QoUKw'
>>> key_modulus_bytes_list = [152, 66, 27, 221, 242, 12, 205, 109, 3, 3, 73, 191, 7, 43, 214, 144,
...     254, 253, 173, 139, 211, 33, 139, 34, 95, 176, 106, 246, 5, 176, 94, 78,
...     150, 102, 87, 240, 113, 118, 40, 137, 1, 245, 201, 181, 133, 9, 175, 161,
...     119, 134, 19, 81, 38, 21, 100, 25, 214, 68, 37, 66, 189, 149, 75, 143,
...     148, 24, 249, 69, 38, 236, 119, 81, 118, 149, 244, 115, 242, 43, 3, 90,
...     107, 238, 42, 3, 9, 90, 173, 192, 72, 175, 165, 17, 77, 92, 175, 8,
...     22, 252, 201, 168, 30, 109, 167, 12, 23, 56, 114, 122, 217, 30, 241, 127,
...     233, 130, 119, 100, 190, 121, 77, 95, 106, 107, 109, 19, 5, 103, 110, 0,
...     208, 248, 166, 68, 213, 22, 203, 25, 50, 35, 207, 165, 188, 185, 62, 103,
...     164, 45, 172, 183, 49, 132, 72, 72, 159, 223, 180, 22, 157, 253, 197, 185,
...     77, 67, 236, 72, 99, 14, 155, 255, 100, 159, 208, 199, 50, 4, 232, 132,
...     147, 61, 84, 150, 56, 13, 109, 17, 6, 247, 76, 172, 122, 185, 142, 120,
...     207, 117, 90, 94, 96, 161, 216, 2, 221, 17, 89, 107, 229, 214, 154, 97,
...     2, 17, 14, 222, 116, 61, 249, 198, 194, 55, 187, 13, 243, 34, 151, 65,
...     197, 17, 145, 225, 124, 238, 155, 235, 84, 192, 107, 107, 118, 185, 67, 196,
...     4, 75, 15, 89, 140, 30, 169, 51, 94, 160, 20, 98, 153, 156, 216, 51]
>>> key_modulus = ''.join(chr(byte) for byte in key_modulus_bytes_list)
>>> key_public_exponent_bytes_list = [1, 0, 1]
>>> key_public_exponent = ''.join(chr(byte) for byte in key_public_exponent_bytes_list)
>>> key_private_exponent_bytes_list = [107, 210, 84, 253, 165, 77, 95, 164, 21, 0, 29, 23, 68, 50, 205, 45,
...     189, 5, 84, 2, 178, 175, 12, 98, 121, 52, 235, 105, 241, 185, 101, 239,
...     109, 30, 104, 164, 3, 21, 83, 187, 66, 66, 22, 103, 143, 32, 190, 217,
...     47, 85, 41, 20, 204, 77, 85, 167, 222, 78, 63, 188, 181, 152, 165, 251,
...     181, 58, 194, 59, 48, 71, 64, 111, 213, 244, 119, 58, 44, 130, 61, 75,
...     169, 38, 237, 101, 93, 24, 115, 246, 185, 2, 121, 120, 121, 58, 107, 80,
...     229, 70, 122, 95, 173, 188, 165, 17, 48, 216, 110, 105, 132, 156, 31, 21,
...     31, 253, 158, 35, 31, 167, 179, 29, 32, 181, 150, 118, 99, 219, 76, 207,
...     251, 137, 174, 83, 77, 177, 19, 244, 49, 154, 248, 255, 112, 107, 231, 233,
...     96, 24, 96, 218, 77, 28, 47, 208, 75, 221, 69, 210, 226, 175, 61, 65,
...     106, 13, 8, 127, 96, 188, 205, 210, 251, 101, 176, 46, 22, 245, 249, 13,
...     174, 22, 109, 117, 255, 141, 126, 39, 90, 231, 44, 51, 49, 54, 95, 99,
...     149, 61, 238, 4, 17, 48, 239, 76, 198, 16, 193, 252, 160, 213, 155, 98,
...     51, 21, 155, 203, 163, 238, 112, 23, 29, 231, 76, 141, 93, 115, 91, 83,
...     103, 66, 110, 227, 188, 231, 105, 78, 23, 172, 126, 196, 130, 181, 226, 214,
...     178, 46, 56, 1, 181, 180, 154, 182, 80, 186, 154, 158, 79, 15, 177, 65]
>>> key_private_exponent = ''.join(chr(byte) for byte in key_private_exponent_bytes_list)
>>> private_key = RSA.construct((number.bytes_to_long(key_modulus),
...     number.bytes_to_long(key_public_exponent), number.bytes_to_long(key_private_exponent)))
>>> private_key_as_encoded_str = private_key.exportKey()
>>> decryptor = decrypt_json_web_token(private_key = private_key_as_encoded_str)
>>> decrypted_jwt = check(decryptor)(jwe)
>>> decoded_jwt = check(decode_json_web_token)(decrypted_jwt)
>>> decoded_jwt['payload']
'What hath God wrought?'
biryani.jwtconv.derive_key(master_key, label, digest_size=None, key_size=None)[source]

Concatenation Key Derivation Function

This is a simplified version of the algorithm described in section “5.8.1 Concatenation Key Derivation Function (Approved Alternative 1)” of “Recommendation for Pair-Wise Key Establishment Schemes Using Discrete Logarithm Cryptography” (NIST SP 800-56 A). http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf

Note

key_size & digest_size are the length in bits (not bytes).

>>> # Mike Jones Tests
>>> cmk1_bytes_list = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206,
...     107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207]
>>> cmk1 = ''.join(chr(byte) for byte in cmk1_bytes_list)
>>> cek1 = derive_key(cmk1, 'Encryption', key_size = 256)
>>> cek1_bytes_list = [ord(c) for c in cek1]
>>> cek1_bytes_list
[249, 255, 87, 218, 224, 223, 221, 53, 204, 121, 166, 130, 195, 184, 50, 69, 11, 237, 202, 71, 10, 96, 59, 199, 140, 88, 126, 147, 146, 113, 222, 41]
>>> cik1 = derive_key(cmk1, 'Integrity', key_size = 256)
>>> cik1_bytes_list = [ord(c) for c in cik1]
>>> cik1_bytes_list
[218, 209, 130, 50, 169, 45, 70, 214, 29, 187, 123, 20, 3, 158, 111, 122, 182, 94, 57, 133, 245, 76, 97, 44, 193, 80, 81, 246, 115, 177, 225, 159]
>>> cmk2_bytes_list = [148, 116, 199, 126, 2, 117, 233, 76, 150, 149, 89, 193, 61, 34, 239, 226,
...     109, 71, 59, 160, 192, 140, 150, 235, 106, 204, 49, 176, 68, 119, 13, 34,
...     49, 19, 41, 69, 5, 20, 252, 145, 104, 129, 137, 138, 67, 23, 153, 83,
...     81, 234, 82, 247, 48, 211, 41, 130, 35, 124, 45, 156, 249, 7, 225, 168]
>>> cmk2 = ''.join(chr(byte) for byte in cmk2_bytes_list)
>>> cek2 = derive_key(cmk2, 'Encryption', key_size = 128)
>>> cek2_bytes_list = [ord(c) for c in cek2]
>>> cek2_bytes_list
[137, 5, 92, 9, 17, 47, 17, 86, 253, 235, 34, 247, 121, 78, 11, 144]
>>> cik2 = derive_key(cmk2, 'Integrity', key_size = 512)
>>> cik2_bytes_list = [ord(c) for c in cik2]
>>> cik2_bytes_list
[11, 179, 132, 177, 171, 24, 126, 19, 113, 1, 200, 102, 100, 74, 88, 149, 31, 41, 71, 57, 51, 179, 106, 242, 113, 211, 56, 56, 37, 198, 57, 17, 149, 209, 221, 113, 40, 191, 95, 252, 142, 254, 141, 230, 39, 113, 139, 84, 44, 156, 247, 47, 223, 101, 229, 180, 82, 231, 38, 96, 170, 119, 236, 81]
biryani.jwtconv.encrypt_json_web_token(algorithm=None, compression=None, content_master_key=None, encrypted_key=None, integrity=None, initialization_vector=None, json_web_key_url=None, key_derivation_function=None, key_id=None, method=None, public_key_as_encoded_str=None, public_key_as_json_web_key=None, shared_secret=None)[source]

Return a converter that encrypts a JSON Web Token.

Note

content_master_key, encrypted_key & initialization_vector parameters should be kept to None, except for testing.

>>> # Mike Jones Test 1
>>> from Crypto.PublicKey import RSA
>>> from Crypto.Util import number
>>> plaintext_bytes_list = [78, 111, 119, 32, 105, 115, 32, 116, 104, 101, 32, 116, 105, 109, 101, 32,
...    102, 111, 114, 32, 97, 108, 108, 32, 103, 111, 111, 100, 32, 109, 101, 110,
...    32, 116, 111, 32, 99, 111, 109, 101, 32, 116, 111, 32, 116, 104, 101, 32,
...    97, 105, 100, 32, 111, 102, 32, 116, 104, 101, 105, 114, 32, 99, 111, 117,
...    110, 116, 114, 121, 46]
>>> plaintext = ''.join(chr(byte) for byte in plaintext_bytes_list)
>>> jwt = check(make_payload_to_json_web_token())(plaintext)
>>> jwt
'eyJhbGciOiJub25lIn0.Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBtZW4gdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku.'
>>> cmk_bytes_list = [4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106, 206,
...     107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156, 44, 207]
>>> cmk = ''.join(chr(byte) for byte in cmk_bytes_list)
>>> iv_bytes_list = [3, 22, 60, 12, 43, 67, 104, 105, 108, 108, 105, 99, 111, 116, 104, 101]
>>> iv = ''.join(chr(byte) for byte in iv_bytes_list)
>>> key_modulus_bytes_list = [177, 119, 33, 13, 164, 30, 108, 121, 207, 136, 107, 242, 12, 224, 19, 226,
...    198, 134, 17, 71, 173, 75, 42, 61, 48, 162, 206, 161, 97, 108, 185, 234,
...    226, 219, 118, 206, 118, 5, 169, 224, 60, 181, 90, 85, 51, 123, 6, 224,
...    4, 122, 29, 230, 151, 12, 244, 127, 121, 25, 4, 85, 220, 144, 215, 110,
...    130, 17, 68, 228, 129, 138, 7, 130, 231, 40, 212, 214, 17, 179, 28, 124,
...    151, 178, 207, 20, 14, 154, 222, 113, 176, 24, 198, 73, 211, 113, 9, 33,
...    178, 80, 13, 25, 21, 25, 153, 212, 206, 67, 154, 147, 70, 194, 192, 183,
...    160, 83, 98, 236, 175, 85, 23, 97, 75, 199, 177, 73, 145, 50, 253, 206,
...    32, 179, 254, 236, 190, 82, 73, 67, 129, 253, 252, 220, 108, 136, 138, 11,
...    192, 1, 36, 239, 228, 55, 81, 113, 17, 25, 140, 63, 239, 146, 3, 172,
...    96, 60, 227, 233, 64, 255, 224, 173, 225, 228, 229, 92, 112, 72, 99, 97,
...    26, 87, 187, 123, 46, 50, 90, 202, 117, 73, 10, 153, 47, 224, 178, 163,
...    77, 48, 46, 154, 33, 148, 34, 228, 33, 172, 216, 89, 46, 225, 127, 68,
...    146, 234, 30, 147, 54, 146, 5, 133, 45, 78, 254, 85, 55, 75, 213, 86,
...    194, 218, 215, 163, 189, 194, 54, 6, 83, 36, 18, 153, 53, 7, 48, 89,
...    35, 66, 144, 7, 65, 154, 13, 97, 75, 55, 230, 132, 3, 13, 239, 71]
>>> key_modulus = ''.join(chr(byte) for byte in key_modulus_bytes_list)
>>> key_public_exponent_bytes_list = [1, 0, 1]
>>> key_public_exponent = ''.join(chr(byte) for byte in key_public_exponent_bytes_list)
>>> public_key = RSA.construct((number.bytes_to_long(key_modulus),
...     number.bytes_to_long(key_public_exponent)))
>>> public_key_as_encoded_str = public_key.exportKey()
>>> print public_key_as_encoded_str
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsXchDaQebHnPiGvyDOAT
4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1WlUzewbgBHod5pcM9H95GQRV3JDX
boIRROSBigeC5yjU1hGzHHyXss8UDprecbAYxknTcQkhslANGRUZmdTOQ5qTRsLA
t6BTYuyvVRdhS8exSZEy/c4gs/7svlJJQ4H9/NxsiIoLwAEk7+Q3UXERGYw/75ID
rGA84+lA/+Ct4eTlXHBIY2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF/
RJLqHpM2kgWFLU7+VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN+aEAw3v
RwIDAQAB
-----END PUBLIC KEY-----
>>> encrypted_key_bytes_list = [32, 242, 63, 207, 94, 246, 133, 37, 135, 48, 88, 4, 15, 193, 6, 244,
...     51, 58, 132, 133, 212, 255, 163, 90, 59, 80, 200, 152, 41, 244, 188, 215,
...     174, 160, 26, 188, 227, 180, 165, 234, 172, 63, 24, 116, 152, 28, 149, 16,
...     94, 213, 201, 171, 180, 191, 11, 21, 149, 172, 143, 54, 194, 58, 206, 201,
...     164, 28, 107, 155, 75, 101, 22, 92, 227, 144, 95, 40, 119, 170, 7, 36,
...     225, 40, 141, 186, 213, 7, 175, 16, 174, 122, 75, 32, 48, 193, 119, 202,
...     41, 152, 210, 190, 68, 57, 119, 4, 197, 74, 7, 242, 239, 170, 204, 73,
...     75, 213, 202, 113, 216, 18, 23, 66, 106, 208, 69, 244, 117, 147, 2, 37,
...     207, 199, 184, 96, 102, 44, 70, 212, 87, 143, 253, 0, 166, 59, 41, 115,
...     217, 80, 165, 87, 38, 5, 9, 184, 202, 68, 67, 176, 4, 87, 254, 166,
...     227, 88, 124, 238, 249, 75, 114, 205, 148, 149, 45, 78, 193, 134, 64, 189,
...     168, 76, 170, 76, 176, 72, 148, 77, 215, 159, 146, 55, 189, 213, 85, 253,
...     135, 200, 59, 247, 79, 37, 22, 200, 32, 110, 53, 123, 54, 39, 9, 178,
...     231, 238, 95, 25, 211, 143, 87, 220, 88, 138, 209, 13, 227, 72, 58, 102,
...     164, 136, 241, 14, 14, 45, 32, 77, 44, 244, 162, 239, 150, 248, 181, 138,
...     251, 116, 245, 205, 137, 78, 34, 34, 10, 6, 59, 4, 197, 2, 153, 251]
>>> encrypted_key = ''.join(chr(byte) for byte in encrypted_key_bytes_list)
>>> encryptor = encrypt_json_web_token(algorithm = 'RSA1_5', content_master_key = cmk,
...     encrypted_key = encrypted_key, initialization_vector = iv, integrity = 'HS256', method = 'A128CBC',
...     public_key_as_encoded_str = public_key_as_encoded_str)
>>> check(encryptor)(jwt)
'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDIiwiaW50IjoiSFMyNTYiLCJpdiI6IkF4WThEQ3REYUdsc2JHbGpiM1JvWlEifQ.IPI_z172hSWHMFgED8EG9DM6hIXU_6NaO1DImCn0vNeuoBq847Sl6qw_GHSYHJUQXtXJq7S_CxWVrI82wjrOyaQca5tLZRZc45BfKHeqByThKI261QevEK56SyAwwXfKKZjSvkQ5dwTFSgfy76rMSUvVynHYEhdCatBF9HWTAiXPx7hgZixG1FeP_QCmOylz2VClVyYFCbjKREOwBFf-puNYfO75S3LNlJUtTsGGQL2oTKpMsEiUTdefkje91VX9h8g7908lFsggbjV7NicJsufuXxnTj1fcWIrRDeNIOmakiPEODi0gTSz0ou-W-LWK-3T1zYlOIiIKBjsExQKZ-w._Z_djlIoC4MDSCKireWS2beti4Q6iSG2UjFujQvdz-_PQdUcFNkOulegD6BgjgdFLjeB4HHOO7UHvP8PEDu0a0sA2a_-CI0w2YQQ2QQe35M.c41k4T4eAgCCt63m8ZNmiOinMciFFypOFpvid7i6D0k'
>>> # Mike Jones Test 2
>>> plaintext_bytes_list = [76, 105, 118, 101, 32, 108, 111, 110, 103, 32, 97, 110, 100, 32, 112, 114,
...     111, 115, 112, 101, 114, 46]
>>> plaintext = ''.join(chr(byte) for byte in plaintext_bytes_list)
>>> jwt = check(make_payload_to_json_web_token())(plaintext)
>>> cmk_bytes_list = [177, 161, 244, 128, 84, 143, 225, 115, 63, 180, 3, 255, 107, 154, 212, 246,
...     138, 7, 110, 91, 112, 46, 34, 105, 47, 130, 203, 46, 122, 234, 64, 252]
>>> cmk = ''.join(chr(byte) for byte in cmk_bytes_list)
>>> iv_bytes_list = [227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219]
>>> iv = ''.join(chr(byte) for byte in iv_bytes_list)
>>> key_modulus_bytes_list = [161, 168, 84, 34, 133, 176, 208, 173, 46, 176, 163, 110, 57, 30, 135, 227,
...     9, 31, 226, 128, 84, 92, 116, 241, 70, 248, 27, 227, 193, 62, 5, 91,
...     241, 145, 224, 205, 141, 176, 184, 133, 239, 43, 81, 103, 9, 161, 153, 157,
...     179, 104, 123, 51, 189, 34, 152, 69, 97, 69, 78, 93, 140, 131, 87, 182,
...     169, 101, 92, 142, 3, 22, 167, 8, 212, 56, 35, 79, 210, 222, 192, 208,
...     252, 49, 109, 138, 173, 253, 210, 166, 201, 63, 102, 74, 5, 158, 41, 90,
...     144, 108, 160, 79, 10, 89, 222, 231, 172, 31, 227, 197, 0, 19, 72, 81,
...     138, 78, 136, 221, 121, 118, 196, 17, 146, 10, 244, 188, 72, 113, 55, 221,
...     162, 217, 171, 27, 57, 233, 210, 101, 236, 154, 199, 56, 138, 239, 101, 48,
...     198, 186, 202, 160, 76, 111, 234, 71, 57, 183, 5, 211, 171, 136, 126, 64,
...     40, 75, 58, 89, 244, 254, 107, 84, 103, 7, 236, 69, 163, 18, 180, 251,
...     58, 153, 46, 151, 174, 12, 103, 197, 181, 161, 162, 55, 250, 235, 123, 110,
...     17, 11, 158, 24, 47, 133, 8, 199, 235, 107, 126, 130, 246, 73, 195, 20,
...     108, 202, 176, 214, 187, 45, 146, 182, 118, 54, 32, 200, 61, 201, 71, 243,
...     1, 255, 131, 84, 37, 111, 211, 168, 228, 45, 192, 118, 27, 197, 235, 232,
...     36, 10, 230, 248, 190, 82, 182, 140, 35, 204, 108, 190, 253, 186, 186, 27]
>>> key_modulus = ''.join(chr(byte) for byte in key_modulus_bytes_list)
>>> key_public_exponent_bytes_list = [1, 0, 1]
>>> key_public_exponent = ''.join(chr(byte) for byte in key_public_exponent_bytes_list)
>>> public_key = RSA.construct((number.bytes_to_long(key_modulus),
...     number.bytes_to_long(key_public_exponent)))
>>> public_key_as_encoded_str = public_key.exportKey()
>>> encrypted_key_bytes_list = [142, 252, 40, 202, 21, 177, 56, 198, 232, 7, 151, 49, 95, 169, 220, 2,
...     46, 214, 167, 116, 57, 20, 164, 109, 150, 98, 49, 223, 154, 95, 71, 209,
...     233, 17, 174, 142, 203, 232, 132, 167, 17, 42, 51, 125, 22, 221, 135, 17,
...     67, 197, 148, 246, 139, 145, 160, 238, 99, 119, 171, 95, 117, 202, 87, 251,
...     101, 254, 58, 215, 135, 195, 135, 103, 49, 119, 76, 46, 49, 198, 27, 31,
...     58, 44, 192, 222, 21, 16, 13, 216, 161, 179, 236, 65, 143, 38, 43, 218,
...     195, 76, 140, 243, 71, 243, 79, 124, 216, 208, 242, 171, 34, 245, 57, 154,
...     93, 76, 230, 204, 234, 82, 117, 248, 39, 13, 62, 60, 215, 8, 51, 248,
...     254, 47, 150, 36, 46, 27, 247, 98, 77, 56, 92, 44, 19, 39, 12, 77,
...     54, 101, 194, 126, 86, 0, 64, 239, 95, 211, 64, 26, 219, 93, 211, 36,
...     154, 250, 117, 177, 213, 232, 142, 184, 216, 92, 20, 248, 69, 175, 180, 71,
...     205, 221, 235, 224, 95, 113, 5, 33, 86, 18, 157, 61, 199, 8, 121, 0,
...     0, 135, 65, 67, 220, 164, 15, 230, 155, 71, 53, 64, 253, 209, 169, 255,
...     34, 64, 101, 7, 43, 102, 227, 83, 171, 52, 225, 119, 253, 182, 96, 195,
...     225, 34, 156, 211, 202, 7, 194, 255, 137, 59, 170, 172, 72, 234, 222, 203,
...     123, 249, 121, 254, 143, 173, 105, 65, 187, 189, 163, 64, 151, 145, 99, 17]
>>> encrypted_key = ''.join(chr(byte) for byte in encrypted_key_bytes_list)
>>> encryptor = encrypt_json_web_token(algorithm = 'RSA-OAEP', content_master_key = cmk,
...     encrypted_key = encrypted_key, initialization_vector = iv, method = 'A256GCM',
...     public_key_as_encoded_str = public_key_as_encoded_str)
>>> check(encryptor)(jwt)
'eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJpdiI6IjQ4VjFfQUxiNlVTMDRVM2IifQ.jvwoyhWxOMboB5cxX6ncAi7Wp3Q5FKRtlmIx35pfR9HpEa6Oy-iEpxEqM30W3YcRQ8WU9ouRoO5jd6tfdcpX-2X-OteHw4dnMXdMLjHGGx86LMDeFRAN2KGz7EGPJivaw0yM80fzT3zY0PKrIvU5ml1M5szqUnX4Jw0-PNcIM_j-L5YkLhv3Yk04XCwTJwxNNmXCflYAQO9f00Aa213TJJr6dbHV6I642FwU-EWvtEfN3evgX3EFIVYSnT3HCHkAAIdBQ9ykD-abRzVA_dGp_yJAZQcrZuNTqzThd_22YMPhIpzTygfC_4k7qqxI6t7Le_l5_o-taUG7vaNAl5FjEQ._e21tGGhac_peEFkLXr2dMPUZiUkrw.YbZSeHCNDZBqAdzpROlyiw'
biryani.jwtconv.input_to_json_web_token(*args, **kwargs)
biryani.jwtconv.make_json_to_json_web_token(typ=None)[source]

Return a converter that wraps JSON data into an unsigned and unencrypted JSON web token.

biryani.jwtconv.make_payload_to_json_web_token(typ=None)[source]

Return a converter that wraps binary data into an unsigned and unencrypted JSON web token.

biryani.jwtconv.sign_json_web_token(algorithm=None, json_web_key_url=None, key_id=None, private_key=None, shared_secret=None)[source]
biryani.jwtconv.verify_decoded_json_web_token_signature(allowed_algorithms=None, public_key_as_encoded_str=None, public_key_as_json_web_key=None, shared_secret=None)[source]
biryani.jwtconv.verify_decoded_json_web_token_time()[source]

biryani.netconv

Network Related Converters

Note

Network converters are not in biryani.baseconv, because they use non-standard network libraries.

biryani.netconv.test_email()[source]

Try to ensure than a (already validated) email address really exists.

Warning

Like most converters, a None value is not tested.

>>> test_email()(u'info@easter-eggs.com')
(u'info@easter-eggs.com', None)
>>> test_email()(u'unknown-user@unknown-server.easter-eggs.com')
(u'unknown-user@unknown-server.easter-eggs.com', u'Domain "unknown-server.easter-eggs.com" doesn\'t exist')
>>> test_email()(u'unknown-user@easter-eggs.com')
(u'unknown-user@easter-eggs.com', None)
>>> test_email()(u'')
Traceback (most recent call last):
ValueError:
>>> pipe(
...     input_to_email,
...     test_email(),
...     )(u'')
(None, None)
>>> test_email()(None)
(None, None)
Traceback (most recent call last):
ValueError:
biryani.netconv.test_http_url(valid_status_codes=None)[source]

Return a converters that tries to ensure than a (already validated) URL really works.

Warning

Like most converters, a None value is not tested.

>>> test_http_url()(u'http://www.easter-eggs.com/')
(u'http://www.easter-eggs.com/', None)
>>> test_http_url()(u'http://www.comarquage.fr/unkown-page.html')
(u'http://www.comarquage.fr/unkown-page.html', u'The web server responded with a bad status code: 404 Not Found')
>>> test_http_url(valid_status_codes = [404])(u'http://www.comarquage.fr/unkown-page.html')
(u'http://www.comarquage.fr/unkown-page.html', None)
>>> test_http_url()(u'http://unknown-server.easter-eggs.com/')
(u'http://unknown-server.easter-eggs.com/', u'An error occured when trying to connect to the web server: <urlopen error [Errno -2] Name or service not known>')
>>> test_http_url()(u'')
Traceback (most recent call last):
ValueError:
>>> pipe(
...     make_input_to_url(),
...     test_http_url(),
...     )(u'')
(None, None)
>>> test_http_url()(None)
(None, None)
Traceback (most recent call last):
ValueError:

biryani.objectconv

Object Related Converters

biryani.objectconv.make_dict_to_object(cls)[source]

Return a converter that creates in instance of a class from a dictionary.

>>> class C(object):
...     pass
>>> make_dict_to_object(C)(dict(a = 1, b = 2))
(<C object at 0x...>, None)
>>> c = check(make_dict_to_object(C))(dict(a = 1, b = 2))
>>> c.a, c.b
(1, 2)
>>> make_dict_to_object(C)(None)
(None, None)
biryani.objectconv.object_to_clean_dict(value, state=None)

Convert an object’s instance to a dictionary, by extracting the attributes whose value differs from the ones defined in the object’s class.

Note

Use this converter instead of object_to_dict() when you want to remove defaut values from generated dictionary.

>>> class C(object):
...     a = 1
...     z = None
>>> c = C()
>>> object_to_clean_dict(c)
({}, None)
>>> c.a = 2
>>> object_to_clean_dict(c)
({'a': 2}, None)
>>> d = C()
>>> d.a = 2
>>> d.b = 3
>>> object_to_clean_dict(d)
({'a': 2, 'b': 3}, None)
>>> e = C()
>>> e.a = 1
>>> object_to_clean_dict(e)
({}, None)
>>> f = C()
>>> f.a = 1
>>> f.b = 2
>>> f.y = None
>>> f.z = None
>>> object_to_clean_dict(f)
({'y': None, 'b': 2}, None)
>>> object_to_clean_dict(None)
(None, None)
>>> object_to_clean_dict(42)
Traceback (most recent call last):
AttributeError:
Traceback (most recent call last):
AttributeError:
biryani.objectconv.object_to_dict(value, state=None)

Convert an object’s instance to a dictionary, by returning its __dict__ atribute.

Note

Use converter object_to_clean_dict() when you want to remove defaut values from generated dictionary.

>>> class C(object):
...     a = 1
>>> c = C()
>>> object_to_dict(c)
({}, None)
>>> c.a = 2
>>> object_to_dict(c)
({'a': 2}, None)
>>> d = C()
>>> d.a = 2
>>> d.b = 3
>>> object_to_dict(d)
({'a': 2, 'b': 3}, None)
>>> e = C()
>>> e.a = 1
>>> object_to_dict(e)
({'a': 1}, None)
>>> f = C()
>>> f.a = 1
>>> f.b = 2
>>> object_to_dict(f)
({'a': 1, 'b': 2}, None)
>>> object_to_dict(None)
(None, None)
>>> object_to_dict(42)
Traceback (most recent call last):
AttributeError:
Traceback (most recent call last):
AttributeError:

biryani.states

Contexts used by converters

class biryani.states.State[source]
biryani.states.default_state = biryani.states.default_state

Minimal context, usable with converters

biryani.uuidconv

UUID Related Converters

biryani.uuidconv.input_to_uuid(*args, **kwargs)

Convert a string to an UUID.

>>> input_to_uuid(u'12345678-9abc-def0-1234-56789abcdef0')
(UUID('12345678-9abc-def0-1234-56789abcdef0'), None)
>>> input_to_uuid(u'   12345678-9abc-def0-1234-56789abcdef0   ')
(UUID('12345678-9abc-def0-1234-56789abcdef0'), None)
>>> input_to_uuid(u'12345678 - 9abc - def0 - 1234 - 56789abcdef0')
(u'12345678 - 9abc - def0 - 1234 - 56789abcdef0', u'Invalid UUID')
>>> input_to_uuid(u'Hello World')
(u'Hello World', u'Invalid UUID')
>>> input_to_uuid(u'')
(None, None)
>>> input_to_uuid(None)
(None, None)
biryani.uuidconv.input_to_uuid_str(*args, **kwargs)

Verify that a string contains a valid UUID string.

>>> input_to_uuid_str(u'12345678-9abc-def0-1234-56789abcdef0')
(u'12345678-9abc-def0-1234-56789abcdef0', None)
>>> input_to_uuid_str(u'   12345678-9abc-def0-1234-56789abcdef0   ')
(u'12345678-9abc-def0-1234-56789abcdef0', None)
>>> input_to_uuid_str(u'12345678 - 9abc - def0 - 1234 - 56789abcdef0')
(u'12345678 - 9abc - def0 - 1234 - 56789abcdef0', u'Invalid UUID')
>>> input_to_uuid_str(u'Hello World')
(u'Hello World', u'Invalid UUID')
>>> input_to_uuid_str(u'')
(None, None)
>>> input_to_uuid_str(None)
(None, None)
biryani.uuidconv.str_to_uuid(*args, **kwargs)

Convert a clean string to an UUID.

Note

For a converter that doesn’t require a clean string, see input_to_uuid().

>>> str_to_uuid(u'12345678-9abc-def0-1234-56789abcdef0')
(UUID('12345678-9abc-def0-1234-56789abcdef0'), None)
>>> str_to_uuid(u'Hello World')
(u'Hello World', u'Invalid UUID')
>>> str_to_uuid(u'')
(u'', u'Invalid UUID')
>>> str_to_uuid(None)
(None, None)
biryani.uuidconv.str_to_uuid_str(value, state=None)

Verify that a clean string is a valid UUID string.

Note

For a converter that doesn’t require a clean string, see input_to_uuid_str().

>>> str_to_uuid_str(u'12345678-9abc-def0-1234-56789abcdef0')
(u'12345678-9abc-def0-1234-56789abcdef0', None)
>>> str_to_uuid_str(u'Hello World')
(u'Hello World', u'Invalid UUID')
>>> str_to_uuid_str(u'')
(u'', u'Invalid UUID')
>>> str_to_uuid_str(None)
(None, None)

biryani.webobconv

WebOb related Converters

See http://webob.org/

biryani.webobconv.multidict_get(key, default=None)[source]

Return a converter that retrieves the value of a MultiDict item.

Note

When several values exists for the same key, only the last one is returned.

>>> import webob
>>> req = webob.Request.blank('/?a=1&tag=hello&tag=World!&z=')
>>> multidict_get('a')(req.GET)
(u'1', None)
>>> multidict_get('a', default = 2)(req.GET)
(u'1', None)
>>> multidict_get('b')(req.GET)
(None, None)
>>> multidict_get('b', default = 2)(req.GET)
(2, None)
>>> multidict_get('z')(req.GET)
(u'', None)
>>> multidict_get('z', default = 3)(req.GET)
(u'', None)
>>> pipe(multidict_get('z'), cleanup_line, default(3))(req.GET)
(3, None)
>>> multidict_get('tag')(req.GET)
(u'World!', None)
>>> new_struct(dict(
...     a = multidict_get('a'),
...     b = multidict_get('b'),
...     ))(req.GET)
({'a': u'1', 'b': None}, None)
biryani.webobconv.multidict_getall(key)[source]

Return a converter that retrieves all values of a MultiDict item.

>>> import webob
>>> req = webob.Request.blank('/?a=1&tag=hello&tag=World!&z=')
>>> multidict_getall('a')(req.GET)
([u'1'], None)
>>> multidict_getall('b')(req.GET)
(None, None)
>>> multidict_getall('z')(req.GET)
([u''], None)
>>> multidict_getall('tag')(req.GET)
([u'hello', u'World!'], None)
>>> new_struct(dict(
...     b = multidict_getall('b'),
...     tags = multidict_getall('tag'),
...     ))(req.GET)
({'b': None, 'tags': [u'hello', u'World!']}, None)
biryani.webobconv.multidict_getone(key)[source]

Return a converter that retrieves one and only one value of a MultiDict item.

Note

When no value exists or several values exists for the same key, an exception is raised. Most of the times, this is not the desired behaviour, so use multidict_get() instead.

>>> import webob
>>> req = webob.Request.blank('/?a=1&tag=hello&tag=World!&z=')
>>> multidict_getone('a')(req.GET)
(u'1', None)
>>> multidict_getone('b')(req.GET)
Traceback (most recent call last):
KeyError:
>>> multidict_getone('')(req.GET)
Traceback (most recent call last):
KeyError:
>>> multidict_getone('tag')(req.GET)
Traceback (most recent call last):
KeyError:
Traceback (most recent call last):
KeyError:

String Functions

biryani.strings

Strings simplification functions

biryani.strings.deep_decode(value, encoding='utf-8')[source]

Convert recursively bytes strings embedded in Python data to unicode strings.

>>> deep_decode('Hello world!')
u'Hello world!'
>>> deep_decode(dict(a = 'b', c = ['d', 'e']))
{u'a': u'b', u'c': [u'd', u'e']}
>>> deep_decode(u'Hello world!')
u'Hello world!'
>>> deep_decode(42)
42
>>> print deep_decode(None)
None
biryani.strings.deep_encode(value, encoding='utf-8')[source]

Convert recursively unicode strings embedded in Python data to encoded strings.

>>> deep_encode(u'Hello world!')
'Hello world!'
>>> deep_encode({u'a': u'b', u'c': [u'd', u'e']})
{'a': 'b', 'c': ['d', 'e']}
>>> deep_encode('Hello world!')
'Hello world!'
>>> deep_encode(42)
42
>>> print deep_encode(None)
None
biryani.strings.lower(s)[source]

Convert a string to lower case.

Note

This method is equivalent to the lower() method of strings, but can be used when a function is expected, for example by the normalize() & slugify() functions.

>>> lower('Hello world!')
'hello world!'
>>> lower(u'Hello world!')
u'hello world!'
>>> print lower(None)
None
biryani.strings.normalize(s, encoding='utf-8', separator=u' ', transform=<function lower at 0x7f5d608c2a28>)[source]

Convert a string to its normal form using compatibility decomposition and removing combining characters.

>>> normalize(u'Hello world!')
u'hello world!'
>>> normalize(u'   Hello   world!   ')
u'hello world!'
>>> normalize('œil, forêt, ça, où...')
u'\u0153il, foret, ca, ou...'
>>> normalize('Hello world!')
u'hello world!'
>>> normalize(u'   ')
u''
>>> print normalize(None)
None
biryani.strings.slugify(s, encoding='utf-8', separator=u'-', transform=<function lower at 0x7f5d608c2a28>)[source]

Simplify a string, converting it to a lowercase ASCII subset.

>>> slugify(u'Hello world!')
u'hello-world'
>>> slugify(u'   Hello   world!   ')
u'hello-world'
>>> slugify('œil, forêt, ça, où...')
u'oeil-foret-ca-ou'
>>> slugify('Hello world!')
u'hello-world'
>>> print slugify(None)
None
biryani.strings.upper(s)[source]

Convert a string to upper case.

Note

This method is equivalent to the upper() method of strings, but can be used when a function is expected, for example by the normalize() & slugify() functions.

>>> upper('Hello world!')
'HELLO WORLD!'
>>> upper(u'Hello world!')
u'HELLO WORLD!'
>>> print upper(None)
None