mirror of
https://gitlab.com/datalifeit/python-retrofix
synced 2023-12-14 06:13:03 +01:00
136 lines
4.6 KiB
Python
Executable file
136 lines
4.6 KiB
Python
Executable file
##############################################################################
|
|
#
|
|
# Copyright (C) 2011-2013 NaN Projectes de Programari Lliure, S.L.
|
|
# http://www.NaN-tic.com
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
##############################################################################
|
|
|
|
|
|
from .fields import Field
|
|
from .exception import RetrofixException, raise_assert_error
|
|
|
|
BLANK = ' '
|
|
|
|
# Record structures:
|
|
# * Initial position starting at 1 (instead of 0)
|
|
# * Length
|
|
# * Field name
|
|
# * Field type
|
|
|
|
class Record(object):
|
|
def __init__(self, structure):
|
|
"""
|
|
Creates a Record object using a structure.
|
|
|
|
Only fields defined in the structure will be allowed.
|
|
"""
|
|
self._structure = structure
|
|
self._fields = {}
|
|
self._values = {}
|
|
keys = set()
|
|
for line in self._structure:
|
|
size = line[1]
|
|
name = line[2]
|
|
field = line[3]
|
|
if not isinstance(field, Field):
|
|
field = field()
|
|
field._size = size
|
|
field._name = name
|
|
raise_assert_error(name not in keys, 'Duplicate field name "%s".' % name)
|
|
keys.add(name)
|
|
self._fields[name] = field
|
|
|
|
def get_for_file(self, name):
|
|
return self._fields[name].get_for_file(self._values.get(name))
|
|
|
|
def set_from_file(self, name, value):
|
|
self._values[name] = self._fields[name].set_from_file(value)
|
|
|
|
def __getattr__(self, name):
|
|
raise_assert_error(name in self._fields, 'Field "%s" does not exist.' % name)
|
|
return self._fields[name].get(self._values.get(name))
|
|
|
|
def __setattr__(self, name, value):
|
|
if name.startswith('_'):
|
|
return super(Record, self).__setattr__(name, value)
|
|
raise_assert_error(name in self._fields, 'Field "%s" does not exist.' % name)
|
|
self._values[name] = self._fields[name].set(value)
|
|
|
|
def load(self, line, first_position=1):
|
|
for field in self._structure:
|
|
start = field[0] - first_position
|
|
end = start + field[1]
|
|
key = field[2]
|
|
value = line[start:end]
|
|
self.set_from_file(key, value)
|
|
|
|
@staticmethod
|
|
def extract(line, structure, first_position=1):
|
|
record = Record(structure)
|
|
record.load(line, first_position=first_position)
|
|
return record
|
|
|
|
@staticmethod
|
|
def valid(line, structure, first_position=1):
|
|
record = Record(structure)
|
|
try:
|
|
record.load(line, first_position=first_position)
|
|
return True
|
|
except (AssertionError, RetrofixException):
|
|
return False
|
|
|
|
def write(self, first_position=1):
|
|
current_position = 0
|
|
text = ''
|
|
for field in self._structure:
|
|
start = field[0] - first_position
|
|
length = field[1]
|
|
name = field[2]
|
|
|
|
value = self.get_for_file(name)
|
|
|
|
raise_assert_error(len(value) == length, (
|
|
'Field "%s" should be of size "%d" '
|
|
'but got "%d" on record "%s".' % (name, length, len(value),
|
|
str(self))))
|
|
raise_assert_error(start >= current_position, (
|
|
'Error writing field "%s". '
|
|
'Start: %d, Current Position: %d' % (name, start,
|
|
current_position)))
|
|
text += BLANK * (start - current_position)
|
|
text += value
|
|
current_position = len(text)
|
|
return text
|
|
|
|
def __repr__(self):
|
|
return repr(self._values)
|
|
|
|
def __str__(self):
|
|
return str(self._values)
|
|
|
|
def __eq__(self, other):
|
|
if self._structure != other._structure:
|
|
return False
|
|
for field in self._fields.keys():
|
|
if self.get_for_file(field) != other.get_for_file(field):
|
|
return False
|
|
return True
|
|
|
|
def write(records, separator='\r\n'):
|
|
data = ''
|
|
for record in records:
|
|
data += record.write() + separator
|
|
return data
|