Lazy Man’s Record Normalizer¶
normalazy
is an experimental, simple Python library which
defines a DSL for mapping and normalizing records to a standardized
format.
This documentation is quite poor at the moment, but the API is well documented and can be found below.
Installation¶
From PyPI (The Python Package Index):
pip install normalazy
or from GitHub:
pip install git+https://github.com/vst/normalazy.git
or from GitHub (the development version):
pip install git+https://github.com/vst/normalazy.git@develop
API Documentation¶
-
class
normalazy.
ChoiceKeyField
(*args, **kwargs)[source]¶ Defines a choice mapper for the index of the record provided.
>>> field = ChoiceKeyField(key="a", choices=dict(a=1, b=2)) >>> field.map(None, dict(a="a")).value 1 >>> field = ChoiceKeyField(key="a", choices=dict(a=1, b=2), func=lambda i, r, v: Decimal(str(v))) >>> field.map(None, dict(a="a")).value Decimal('1')
-
class
normalazy.
Field
(name=None, func=None, blank=True, null=True)[source]¶ Provides a concrete mapper field.
>>> field = Field() >>> field.map(None, dict()).value >>> field.map(None, dict()).status == Value.Status.Success True >>> field = Field(null=False) >>> field.map(None, dict()).value >>> field.map(None, dict()).status == Value.Status.Error True >>> field = Field(func=lambda i, r: r.get("a", None)) >>> field.map(None, dict(a="")).value '' >>> field.map(None, dict(a="")).status == Value.Status.Success True >>> field = Field(func=lambda i, r: r.get("a", None), blank=False) >>> field.map(None, dict(a="")).value '' >>> field.map(None, dict(a="")).status == Value.Status.Error True >>> field = Field(func=lambda i, r: r.get("a", None)) >>> field.map(None, dict()).value >>> field.map(None, dict(a=1)).value 1 >>> field.map(None, dict(a=1)).status == Value.Status.Success True
-
blank
¶ Indicates if the value is allowed to be blank.
Returns: Boolean indicating if the value is allowed to be blank.
-
func
¶ Returns the mapping function of the field.
Returns: The mapping function of the field.
-
map
(instance, record)[source]¶ Returns the value of for field as a Value instance.
Parameters: - instance – The instance for which the value will be retrieved.
- record – The raw record.
Returns: A Value instance.
-
name
¶ Returns the name of the field.
Returns: The name of the field.
-
null
¶ Indicates if the value is allowed to be null.
Returns: Boolean indicating if the value is allowed to be null.
-
-
class
normalazy.
KeyField
(key=None, cast=None, **kwargs)[source]¶ Provides a mapper field for a given key which belongs to the record. The record can be an object which has __getitem__ method or a simple object just with attribute access.
The method starts reading the source value using the key provided checking __getitem__ method (for iterables such as dict or list), then checks the attribute for simple object attribute access.
>>> field = KeyField(key="a") >>> field.map(None, dict(a="")).value '' >>> field.map(None, dict(a="")).status == Value.Status.Success True >>> field = KeyField(key="a", blank=False) >>> field.map(None, dict(a="")).value '' >>> field.map(None, dict(a="")).status == Value.Status.Error True >>> field = KeyField(key="a", func=lambda i, r, v: as_number(v)) >>> field.map(None, dict(a="12")).value Decimal('12') >>> field.map(None, dict(a="12")).status == Value.Status.Success True >>> field = KeyField(key="a", cast=as_number) >>> field.map(None, dict(a="12")).value Decimal('12') >>> field.map(None, dict(a="12")).status == Value.Status.Success True >>> class Student: ... def __init__(self, name): ... self.name = name >>> field = KeyField(key="name") >>> field.map(None, Student("Sinan")).value 'Sinan'
-
key
¶ Returns the key of for the field mapping.
-
-
class
normalazy.
Record
(record)[source]¶ Provides a record normalizer base class.
>>> class Test1Record(Record): ... a = KeyField() >>> record1 = Test1Record(dict(a=1)) >>> record1.a 1 >>> class Test2Record(Record): ... a = KeyField() ... b = ChoiceKeyField(choices={1: "Bir", 2: "Iki"}) >>> record2 = Test2Record(dict(a=1, b=2)) >>> record2.a 1 >>> record2.b 'Iki'
We can get the dictionary representation of records:
>>> record1.as_dict() OrderedDict([('a', 1)])
>>> record2.as_dict() OrderedDict([('a', 1), ('b', 'Iki')])
Or detailed:
>>> record1.as_dict(detailed=True) OrderedDict([('a', OrderedDict([('value', '1'), ('status', 1), ('message', None)]))])
>>> record2.as_dict(detailed=True) OrderedDict([('a', OrderedDict([('value', '1'), ('status', 1), ('message', None)])), ('b', OrderedDict([('value', 'Iki'), ('status', 1), ('message', None)]))])
We can also create a new record from an existing record or dictionary:
>>> class Test3Record(Record): ... a = KeyField() ... b = KeyField() >>> record3 = Test3Record.new(record2) >>> record3.a 1 >>> record3.b 'Iki' >>> record3.a == record2.a True >>> record3.b == record2.b True
With dictionary:
>>> record4 = Test3Record.new({"a": 1, "b": "Iki"}) >>> record4.a 1 >>> record4.b 'Iki' >>> record4.a == record2.a True >>> record4.b == record2.b True
Or even override some fields:
>>> record5 = Test3Record.new(record3, b="Bir") >>> record5.a 1 >>> record5.b 'Bir'
-
as_dict
(detailed=False)[source]¶ Provides a JSON representation of the record instance.
Parameters: detailed – Indicates if we need detailed result, ie. with status and message for each field. Returns: A JSON representation of the record instance.
-
getval
(name)[source]¶ Returns the value slot identified by the
name
.Parameters: name – The name of the value slot. Returns: The value slot, ie. the boxed value instance of class Value
.
-
hasval
(name)[source]¶ Indicates if we have a value slot called
name
.Parameters: name – The name of the value slot. Returns: True
if we have a value slot calledname
,False
otherwise.
-
classmethod
new
(record, **kwargs)[source]¶ Creates a new record from the provided record or dictionary and overriding values from the provided additional named arguments.
Parameters: - record – The record or dictionary to be copied from.
- kwargs – Named arguments to override.
Returns: New record.
-
setval
(name, value, status=None, message=None, **kwargs)[source]¶ Sets a value to the value slot.
Parameters: - name – The name of the value slot.
- value – The value to be set (Either a Python value or a
Value
instance.) - status – The status of the value slot if any.
- message – The message of the value slot if any.
- kwargs – Additional named values as payload to value.
Returns: The
Value
instance set.
-
val_blank
(name)[source]¶ Indicates if the value is blank.
Parameters: name – The name of the value slot. Returns: Boolean indicating if the value is blank.
-
val_error
(name)[source]¶ Indicates if the value is error.
Parameters: name – The name of the value slot. Returns: Boolean indicating if the value is error.
-
val_none
(name)[source]¶ Indicates if the value is None.
Parameters: name – The name of the value slot. Returns: Boolean indicating if the value is None.
-
val_some
(name)[source]¶ Indicates if the value is something other than None or blank.
Parameters: name – The name of the value slot. Returns: Boolean indicating if the value is something other than None or blank.
-
-
class
normalazy.
Value
(value=None, message=None, status=None, **kwargs)[source]¶ Defines an immutable [sic.] boxed value with message, status and extra data as payload if required.
>>> value = Value(value=42, message=None, status=Value.Status.Success, extras="41 + 1") >>> value.value 42 >>> value.message >>> value.status == Value.Status.Success True >>> value.extras '41 + 1' >>> value = Value.success(42, date="2015-01-01") >>> value.value 42 >>> value.status == Value.Status.Success True >>> value.date '2015-01-01' >>> value = Value.warning(value="fortytwo", message="Failed to convert to integer.", date="2015-01-01") >>> value.value 'fortytwo' >>> value.status == Value.Status.Warning True >>> value.date '2015-01-01' >>> value.message 'Failed to convert to integer.' >>> value = Value.error(message="Failed to compute the value.", date="2015-01-01") >>> value.value >>> value.status == Value.Status.Error True >>> value.date '2015-01-01' >>> value.message 'Failed to compute the value.'
-
class
Status
[source]¶ Defines an enumeration for value status.
-
Error
= 3¶ Indicates that value could not be mapped successfully.
-
Success
= 1¶ Indicates that value is mapped successfully.
-
Warning
= 2¶ Indicates that value is mapped successfully with warnings.
-
-
classmethod
Value.
error
(value=None, message=None, **kwargs)[source]¶ Provides a convenience constructor for Values instances with errors.
Parameters: - value – The value of the Value instance to be constructed.
- message – The message, if any.
- kwargs – Extra payload for the value.
Returns: A Value instance with errors.
-
classmethod
Value.
success
(value=None, message=None, **kwargs)[source]¶ Provides a convenience constructor for successful Value instances.
Parameters: - value – The value of the Value instance to be constructed.
- message – The message, if any.
- kwargs – Extra payload for the value.
Returns: A successful Value instance.
-
classmethod
Value.
warning
(value=None, message=None, **kwargs)[source]¶ Provides a convenience constructor for Values instances with warnings.
Parameters: - value – The value of the Value instance to be constructed.
- message – The message, if any.
- kwargs – Extra payload for the value.
Returns: A Value instance with warnings.
-
class
-
normalazy.
as_boolean
(x, predicate=None)[source]¶ Converts the value to a boolean value.
Parameters: - x – The value to be converted to a boolean value.
- predicate – The predicate function if required.
Returns: Boolean
>>> as_boolean(None) False >>> as_boolean("") False >>> as_boolean(" ") True >>> as_boolean(1) True >>> as_boolean(0) False >>> as_boolean("1") True >>> as_boolean("0") True >>> as_boolean("1", predicate=lambda x: int(x) != 0) True >>> as_boolean("0", predicate=lambda x: int(x) != 0) False >>> as_boolean("1", predicate=int) True >>> as_boolean("0", predicate=int) False >>> as_boolean("1", int) True >>> as_boolean("0", int) False
-
normalazy.
as_date
(x, fmt=None)[source]¶ Converts the value to a date value.
Parameters: - x – The value to be converted to a date value.
- fmt – The format of the date string.
Returns: A datetime.date instance.
>>> as_date(None) >>> as_date('') '' >>> as_date("2015-01-01") datetime.date(2015, 1, 1) >>> as_date("Date: 2015-01-01", "Date: %Y-%m-%d") datetime.date(2015, 1, 1) >>> as_date("Date: 2015-01-01", fmt="Date: %Y-%m-%d") datetime.date(2015, 1, 1)
-
normalazy.
as_datetime
(x, fmt=None)[source]¶ Converts the value to a datetime value.
Parameters: - x – The value to be converted to a datetime value.
- fmt – The format of the date/time string.
Returns: A datetime.date instance.
>>> as_datetime(None) >>> as_datetime("") '' >>> as_datetime("2015-01-01 00:00:00") datetime.datetime(2015, 1, 1, 0, 0) >>> as_datetime("2015-01-01T00:00:00", "%Y-%m-%dT%H:%M:%S") datetime.datetime(2015, 1, 1, 0, 0) >>> as_datetime("2015-01-01T00:00:00", fmt="%Y-%m-%dT%H:%M:%S") datetime.datetime(2015, 1, 1, 0, 0)
-
normalazy.
as_factor
(x)[source]¶ Converts the value to a factor string.
Parameters: x – Value. Returns: Trimmed, up-cased string value. >>> as_factor(None) >>> as_factor("") '' >>> as_factor("a") 'A' >>> as_factor(" a ") 'A'
-
normalazy.
as_number
(x)[source]¶ Converts the value to a decimal value.
Parameters: x – The value to be converted to a decimal value. Returns: A Decimal instance. >>> as_number(None) >>> as_number(1) Decimal('1') >>> as_number("1") Decimal('1') >>> as_number(" 1 ") Decimal('1')
-
normalazy.
as_string
(x)[source]¶ Converts the value to a trimmed string.
Parameters: x – Value. Returns: Trimmed string value. >>> as_string(None) >>> as_string("") '' >>> as_string("a") 'a' >>> as_string(" a ") 'a'
-
normalazy.
identity
(x)[source]¶ Defines an identity function.
Parameters: x – value Returns: value >>> identity(None) >>> identity(1) 1