xotl.tools.values
– coercers (or checkers) for value types¶
Some generic coercers (or checkers) for value types.
This module coercion function are not related in any way to deprecated old python feature, are similar to a combination of object mold/check:
- Mold - Fit values to expected conventions.
- Check - These functions must return nil [1] special value to specify that expected fit is not possible.
[1] | We don’t use Python classic NotImplemented special value in order to obtain False if the value is not coerced (nil). |
A custom coercer could be created with closures, for an example see
create_int_range_coerce()
.
This module uses Unset value to define absent -not being specified- arguments.
Also contains sub-modules to obtain, convert and check values of common types.
New in version 1.7.0.
-
class
xotl.tools.values.
MetaCoercer
[source]¶ Meta-class for
coercer
.This meta-class allows that several objects are considered valid instances of
coercer
:- Functions decorated with
coercer
(used with its decorator facet). - Instances of any sub-class of
custom
. - Instances of
coercer
itself.
See the class declaration (
coercer
) for more information.- Functions decorated with
-
class
xotl.tools.values.
coercer
[source]¶ Special coercer class.
This class has several facets:
Pure type-checkers when a type or tuple of types are received as argument. See
istype
for more information.Return equivalent coercer from some special values:
- Any true value -> identity_coerce
- Any false or empty value -> void_coerce
A decorator for functions; when a function is given, decorate it to become a coercer. The mark itself is not enough, functions intended to be coercers must fulfills the protocol (not to produce exception and return nil on fails). For example:
>>> @coercer ... def age_coerce(arg): ... res = int_coerce(arg) ... return res if t(res) and 0 < arg <= 120 else nil # TODO: Change next, don't use isinstance >>> isinstance(age_coerce, coercer) True
-
xotl.tools.values.
coercer_name
(arg, join=None)[source]¶ Get the name of a coercer.
Parameters: - arg – Coercer to get the name. Also processes collections (tuple, list, or set) of coercers. Any other value is considered invalid and raises an exception.
- join –
When a collection is used; if this argument is None a collection of names is returned, if not None then is used to join the items in a resulting string.
For example:
>>> coercer_name((int_coerce, float_coerce)) ('int', 'float') >>> coercer_name((int_coerce, float_coerce), join='-') 'int-float'
To obtain pretty-print tuples, use something like:
>>> coercer_name((int_coerce, float_coerce), ... join=lambda arg: '(%s)' % ', '.join(arg))
This function not only works with coercers, all objects that fulfill needed protocol to get names will also be valid.
-
class
xotl.tools.values.
combo
(*coercers)[source]¶ Represent a zip composition of several inner coercers.
An instance of this class is constructed from a sequence of coercers and the its purpose is coerce a sequence of values. Return a sequence [2] where each item contains the i-th element from applying the i-th coercer to the i-th value from argument sequence:
coercers -> (coercer-1, coercer-2, ... ) values -> (value-1, value-2, ... ) combo(coercers)(values) -> (coercer-1(value-1), coercer-2(value-2), ...)
If any value is coerced invalid, the function returns nil and the combo’s instance variable scope receives the duple
(failed-value, failed-coercer)
.The returned sequence is truncated in length to the length of the shortest sequence (coercers or arguments).
If no coercer is given, all sequences are coerced as empty.
[2] The returned sequence is of the same type as the argument sequence if possible.
-
class
xotl.tools.values.
compose
(*args, **kwargs)[source]¶ Returns the composition of several inner coercers.
compose(f1, ... fn)
is equivalent to f1(…(fn(arg))…)``.If no coercer is given return
identity_coerce()
.Could be considered an “AND” operator with some light differences because the nature of coercers: ordering the coercers is important when some can modify (adapt) original values.
If no value results in coercers, a default coercer could be given as a keyword argument; identity_coerce is assumed if missing.
-
xotl.tools.values.
create_int_range_coerce
(min, max)[source]¶ Create a coercer to check integers between a range.
-
xotl.tools.values.
create_unique_member_coerce
(coerce, container)[source]¶ Useful to wrap member coercers when coercing containers.
Resulting coercer check that a member must be unique (not repeated) after it’s coerced.
For example:
>>> from xotl.tools.values import (mapping, create_unique_member_coerce, ... int_coerce, float_coerce) >>> sample = {'1': 1, 2.0: '3', 1.0 + 0j: '4.1'} >>> dc = mapping(int_coerce, float_coerce) >>> dc(dict(sample)) {1: 1.0, 2: 3.0} >>> dc = mapping(create_unique_member_coerce(int_coerce), float_coerce) >>> dc(dict(sample)) nil
-
class
xotl.tools.values.
custom
(*args, **kwargs)[source]¶ Base class for any custom coercer.
The field inner stores an internal data used for the custom coercer; could be a callable, an inner coercer, or a tuple of inner checkers if more than one is needed, …
The field scope stores the exit (not regular) condition: the value that fails or -if needed- a tuple with (exit-value, exit-coercer) or (error-value, error). The exit condition is not always a failure, for example in
some
it is the one that is valid among other inner coercers. To understand better this think on (AND, OR) operators a chain of ANDs exits with the first failure and a chains of ORs exits with the first success.All custom coercers are callable (must redefine
__call__()
) receiving one argument that must be coerced. For example:>>> def foobar(*args): ... coerce = pargs(int_coerce) ... return coerce(args)
This class has two protected fields (_str_join and _repr_join) that are used to call
coercer_name()
in__str__()
and__repr__()
special methods.
-
xotl.tools.values.
float_coerce
(arg)[source]¶ Check if arg is a valid float.
Other types are checked (string, int, complex).
-
xotl.tools.values.
full_identifier_coerce
(arg)[source]¶ Check if arg is a valid dotted Python identifier.
See
identifier_coerce()
for what “validity” means.
-
xotl.tools.values.
identifier_coerce
(arg)[source]¶ Check if arg is a valid Python identifier.
Note
Only Python 2’s version of valid identifier. This means that some Python 3 valid identifiers are not considered valid. This helps to keep things working the same in Python 2 and 3.
-
xotl.tools.values.
int_coerce
(arg)[source]¶ Check if arg is a valid integer.
Other types are checked (string, float, complex).
-
class
xotl.tools.values.
istype
(*args, **kwargs)[source]¶ Pure type-checker.
It’s constructed from an argument valid for
types_tuple_coerce()
coercer.For example:
>>> int_coerce = istype(int) >>> int_coerce(1) 1 >>> int_coerce('1') nil >>> number_coerce = istype((int, float, complex)) >>> number_coerce(1.25) 1.25 >>> number_coerce('1.25') nil
-
class
xotl.tools.values.
iterable
(member_coerce, outer_coerce=True)[source]¶ Create a inner coercer that coerces an iterable member a member.
See constructor for more information.
Return a list, or the same type of source iterable argument if possible.
For example:
>>> from xotl.tools.values import (iterable, int_coerce, ... create_unique_member_coerce) >>> sample = {'1', 1, '1.0'} >>> sc = iterable(int_coerce) >>> sc(set(sample)) == {1} True
See
mapping
for more details of this problem. The equivalent safe example is:>>> member_coerce = create_unique_member_coerce(int_coerce, sample) >>> sc = iterable(member_coerce) >>> sc(set(sample)) nil
when executed coerces arg (an iterable) member a member using member_coercer. If any member coercion fails, the full execution also fails.
There are three types of results when an instance is executed: (1) iterables that are coerced without modifications, (2) the modified ones but conserving its type, and (3) those that are returned in a list.
-
class
xotl.tools.values.
logical
(*args, **kwds)[source]¶ Represent Common Lisp two special values t and nil.
Include redefinition of
__call__()
to check values with special semantic:- When called as
t(arg)
, check if arg is not nil returning a logical true: the same argument if arg is nil or a true boolean value, else return t. That means that False or 0 are valid true values for Common Lisp but not for Python. - When called as
nil(arg)
, check if arg is nil returning t or nil if not.
Constructor could receive a valid name (‘nil’ or ‘t’) or any other
boolean
instance.- When called as
-
class
xotl.tools.values.
mapping
(*args, **kwargs)[source]¶ Create a coercer to check dictionaries.
Receives two coercers, one for keys and one for values.
For example:
>>> from xotl.tools.values import (mapping, int_coerce, float_coerce, ... create_unique_member_coerce) >>> sample = {'1': 1, 2.0: '3', 1.0 + 0j: '4.1'} >>> dc = mapping(int_coerce, float_coerce) >>> dc(dict(sample)) == {1: 1.0, 2: 3.0} True
When coercing containers it’s probable that members become repeated after coercing them. This could be not desirable (mainly in sets and dictionaries). In those cases use
create_unique_member_coerce()
to wrap member coercer. For example:>>> key_coerce = create_unique_member_coerce(int_coerce, sample) >>> dc = mapping(key_coerce, float_coerce) >>> dc(dict(sample)) nil
Above problem is because it’s the same integer (same hash) coerced versions of
'1'
and1.0+0j
.This problem of objects of different types that have the same hash is a problem to use a example as below:
>>> {1: int, 1.0: float, 1+0j: complex} == {1: complex} True
-
xotl.tools.values.
names_coerce
(arg)[source]¶ Check arg as a tuple of valid object names (identifiers).
If only one string is given, is returned as the only member of the resulting tuple.
-
xotl.tools.values.
number_coerce
(arg)[source]¶ Check if arg is a valid number (integer or float).
Types that are checked (string, int, float, complex).
-
class
xotl.tools.values.
pargs
(arg_coerce)[source]¶ Create a inner coercer that check variable argument passing.
Created coercer closure must always receives an argument that is an valid iterable with all members coerced properly with the argument of this outer creator function.
If the inner closure argument has only a member and this one is not properly coerced but it’s an iterabled with all members that coerced well, this member will be the assumed iterable instead the original argument.
In the following example:
>>> from xotl.tools.values import (iterable, int_coerce) >>> def foobar(*args): ... coerce = iterable(int_coerce) ... return coerce(args) >>> args = (1, 2.0, '3.0') >>> foobar(*args) (1, 2, 3) >>> foobar(args) nil
An example using
pargs
>>> from xotl.tools.values import (pargs, int_coerce) >>> def foobar(*args): ... # Below, "coercer" receives the returned "inner" ... coerce = pargs(int_coerce) ... return coerce(args) >>> args = (1, 2.0, '3.0') >>> foobar(*args) (1, 2, 3) >>> foobar(args) (1, 2, 3)
The second form is an example of the real utility of this coercer closure: if by error a sequence is passed as it to a function that expect a variable number of argument, this coercer fixes it.
Instance variable scope stores the last processed invalid argument.
When executed, usually arg is a tuple received by a function as
*args
form.When executed, returns a tuple, or the same type of source iterable argument if possible.
See
xotl.tools.params
for a more specialized and full function arguments conformer.See
combo
for a combined coercer that validate each member with a separate member coercer.
-
class
xotl.tools.values.
safe
(func)[source]¶ Uses a function (or callable) in a safe way.
Receives a coercer that expects only one argument and returns another value.
If the returned value is a
boolean
(maybe the coercer is a predicate), it’s converted to alogical
instance.The wrapped coercer is called in a safe way (inside try/except); if an exception is raised the coercer returns
nil
and the error is saved in the instance attributescope
.
-
xotl.tools.values.
sized_coerce
(arg)[source]¶ Return a valid sized iterable from arg.
If arg is iterable but not sized, is converted to a list. For example:
>>> sized_coerce(i for i in range(1, 10, 2)) [1, 3, 5, 7, 9] >>> s = {1, 2, 3} >>> sized_coerce(s) is s True
-
class
xotl.tools.values.
some
(*args, **kwargs)[source]¶ Represent OR composition of several inner coercers.
compose(f1, ... fn)
is equivalent to f1(arg) or f2(arg) … fn(arg)`` in the sense “the first not nil”.If no coercer is given return
void_coerce()
.
-
class
xotl.tools.values.
typecast
(*args, **kwargs)[source]¶ A type-caster.
It’s constructed from an argument valid for
types_tuple_coerce()
coercer. Similar toistype
but try to convert the value if needed.For example:
>>> int_cast = typecast(int) >>> int_cast('1') 1 >>> int_cast('1x') nil
-
xotl.tools.values.
types_tuple_coerce
(arg)[source]¶ Check if arg is valid for isinstance or issubclass 2nd argument.
Type checkers are any class, a type or tuple of types. For example:
>>> types_tuple_coerce(object) == (object,) True >>> types_tuple_coerce((int, float)) == (int, float) true >>> types_tuple_coerce('not-a-type') is nil True
See type_coerce for more information.
Contents: