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.