Fields¶
As said earlier, fields are the most atomic part of the library. They are the building blocks for inidividual records.
Using Fields¶
A Field serves two purposes:
- validation of data
- automatic coercion to type
Validation is based on the type of field, so for instance while 123 is an
acceptable value for pybankreader.fields.IntegerField, ABC is
not.
You will use fields when creating a record (more on that later). To illustrate with an example:
class MyRecord(Record):
my_field = fields.IntegerField(required=True, length=10)
Notice that there are two parameters: required and length. Both are
mandatory, since it’s more expressive. Particularly IntegerField does not
have any other parameters, but for instance
pybankreader.fields.RegexField has another one (regex)
A field has one attribute called value, where the validated and already
coerced value resides.
Warning
The automatic coercion and validation has implications. For
instance, a string with whitespaces (like \t) is trimmed. Therefore,
if you have separator fields defined like this:
my_field = fields.CharField(length=1, required=True)
the load will fail, since empty string is coerced to None and therefore is
treated like failing the required flag. For separators, always use
required=False.
Fields available in the library:
Custom Fields¶
Creating a custom field is very easy. You extend from the abstract base class
pybankreader.fields.Field, where you would ordinarily override
the __init__ and _set_value methods.
To have an example, let’s implement a field that takes just hexa-decimal
numbers. Since this is basically just a regular expression, we use the
RegexField for this particular situation, even though we could do it
ourselves:
class HexField(RegexField):
def __init__(*args, **kwargs):
super(HexField, self).__init__(
"^#[0-9a-f]{6}$", *args, **kwargs
)
def _set_value(self, value):
try:
super(HexField, self)._set_value(value)
except ValidationError:
# Make the ValidationError more specific
msg = u"Value '{}' is not a hex number".format(
value, self._regex
)
raise ValidationError(self._field_name, msg)
# If this is not a required field, we don't have to continue. Value
# None is already set
if self._value is None:
return
# We coerce the value to something, like this imaginary class. We
# don't have to of course.
self._value = MyHexRepresentationClass(value)
As you can see, it’s basically all about those two methods. In __init__,
we just pass the regex to the superclass. And in _set_value, we’re wrapping
the ValidationError and coercing the data to some type we want the value to be.