pyaccuwage/pyaccuwage/model.py

95 lines
3.1 KiB
Python

from .fields import Field, TextField, ValidationError
import copy
import collections
class Model(object):
record_identifier = ' '
required = False
target_size = 512
def __init__(self):
for (key, value) in list(self.__class__.__dict__.items()):
if isinstance(value, Field):
# GRAB THE FIELD INSTANCE FROM THE CLASS DEFINITION
# AND MAKE A LOCAL COPY FOR THIS RECORD'S INSTANCE,
# OTHERWISE WE'LL END UP WITH VALUES BEING SHARED
# ACROSS RECORDS.
src_field = self.__class__.__dict__[key]
if not src_field.name:
setattr(src_field, 'name', key)
setattr(src_field, 'parent_name', self.__class__.__name__)
self.__dict__[key] = copy.copy(src_field)
def __setattr__(self, key, value):
if hasattr(self, key) and isinstance(getattr(self, key), Field):
getattr(self, key).value = value
else:
# MAYBE THIS SHOULD RAISE A PROPERTY ERROR?
self.__dict__[key] = value
def get_fields(self):
identifier = TextField("record_identifier", max_length=len(self.record_identifier), creation_counter=-1)
identifier.value = self.record_identifier
fields = [identifier]
for key in list(self.__class__.__dict__.keys()):
attr = getattr(self, key)
if isinstance(attr, Field):
fields.append(attr)
return fields
def get_sorted_fields(self):
fields = self.get_fields()
fields.sort(key=lambda x: x.creation_counter)
return fields
def validate(self):
for f in self.get_fields():
f.validate()
try:
custom_validator = getattr(self, 'validate_' + f.name)
except AttributeError:
continue
if isinstance(custom_validator, collections.Callable):
custom_validator(f)
def output(self):
result = b''.join([field.get_data() for field in self.get_sorted_fields()])
if hasattr(self, 'record_length') and len(result) != self.record_length:
raise ValidationError("Record result length not equal to %d bytes (%d)" % (self.record_length, len(result)))
return result
def read(self, fp):
# Skip the first record, since that's an identifier
for field in self.get_sorted_fields()[1:]:
field.read(fp)
def toJSON(self):
return {
'__class__': self.__class__.__name__,
'fields': self.get_sorted_fields()
}
def fromJSON(self, o):
fields = o['fields']
for f in fields:
target = self.__dict__[f.name]
if (target.required != f.required
or target.max_length != f.max_length):
print("Warning: value mismatch on import")
target._value = f._value
#print (self.__dict__[f.name].name == f.name)
#self.__dict__[f.name].name == f.name
#self.__dict__[f.name].max_length == f.max_length
return self