diff --git a/README.md b/README.md index e553e57..92caa06 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Eina d'importació de CCH - `F1` - `F5D` - `INFPA` +- `MCILQH` - `MEDIDAS` - `MHCIL` - `P1` diff --git a/cchloader/adapters/mcilqh.py b/cchloader/adapters/mcilqh.py new file mode 100644 index 0000000..623843a --- /dev/null +++ b/cchloader/adapters/mcilqh.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +from cchloader.adapters import CchAdapter +from cchloader.models.mcilqh import McilQhSchema +from marshmallow import Schema, fields, pre_load + + +class McilQhBaseAdapter(Schema): + """ MCILQH Adapter + """ + + @pre_load + def fix_numbers(self, data): + for attr, field in self.fields.items(): + if isinstance(field, (fields.Integer, fields.Float)): + if not data.get(attr): + data[attr] = None + return data + + @pre_load + def fix_ae(self, data): + ae = int(data.get('ae', 0)) + if ae < 0: + data['ae'] = 0 + + @pre_load + def fix_season(self, data): + valid_values = [0, 1] + season = data.get('season') + if season and season.isdigit() and season in map(str, valid_values): + data['season'] = int(season) + else: + data['season'] = None + + +class McilQhAdapter(McilQhBaseAdapter, CchAdapter, McilQhSchema): + pass diff --git a/cchloader/models/mcilqh.py b/cchloader/models/mcilqh.py new file mode 100644 index 0000000..a4b6864 --- /dev/null +++ b/cchloader/models/mcilqh.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# -*- encoding: utf-8 -*- +from __future__ import absolute_import + +from marshmallow import Schema, fields +from marshmallow.validate import OneOf + + +class McilQhSchema(Schema): + cil = fields.String(position=0, required=True) + year = fields.Integer(position=1, required=True) + month = fields.Integer(position=2, required=True) + day = fields.Integer(position=3, required=True) + hour = fields.Integer(position=4, required=True) + minute = fields.Integer(position=5, required=True) + season = fields.Integer(position=6, validate=OneOf([0, 1])) + ae = fields.Float(position=7, allow_none=True) + ai = fields.Float(position=8, allow_none=True) + r1 = fields.Float(position=9, allow_none=True) + r2 = fields.Float(position=10, allow_none=True) + r3 = fields.Float(position=11, allow_none=True) + r4 = fields.Float(position=12, allow_none=True) + type_measure = fields.String(position=13, validate=OneOf(['R', 'E', 'L', 'M'])) + + +McilQhSchema() diff --git a/cchloader/parsers/__init__.py b/cchloader/parsers/__init__.py index c6f17ab..1789af2 100644 --- a/cchloader/parsers/__init__.py +++ b/cchloader/parsers/__init__.py @@ -12,6 +12,7 @@ from cchloader.parsers.p2 import P2 from cchloader.parsers.p2d import P2D from cchloader.parsers.rf5d import Rf5d +from cchloader.parsers.mcilqh import McilQh from cchloader.parsers.mhcil import Mhcil from cchloader.parsers.medidas import Medidas from cchloader.parsers.reganecu import Reganecu diff --git a/cchloader/parsers/mcilqh.py b/cchloader/parsers/mcilqh.py new file mode 100644 index 0000000..f3c04cb --- /dev/null +++ b/cchloader/parsers/mcilqh.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +from cchloader import logger +from cchloader.utils import build_dict +from cchloader.adapters.mcilqh import McilQhAdapter +from cchloader.models.mcilqh import McilQhSchema +from cchloader.parsers.parser import Parser, register +import six +if six.PY3: + unicode = str + + +class McilQh(Parser): + + patterns = ['^MCILQH_'] + encoding = "iso-8859-15" + delimiter = ';' + + def __init__(self, strict=False): + self.adapter = McilQhAdapter(strict=strict) + self.schema = McilQhSchema(strict=strict) + self.fields = [] + self.headers = [] + for f in sorted(self.schema.fields, key=lambda f: self.schema.fields[f].metadata['position']): + field = self.schema.fields[f] + self.fields.append((f, field.metadata)) + self.headers.append(f) + + def parse_line(self, line): + slinia = tuple(unicode(line.decode(self.encoding)).split(self.delimiter)) + slinia = list(map(lambda s: s.strip(), slinia)) + parsed = {'mcilqh': {}, 'orig': line} + data = build_dict(self.headers, slinia) + result, errors = self.adapter.load(data) + if errors: + logger.error(errors) + parsed['mcilqh'] = result + return parsed, errors + + +register(McilQh) diff --git a/spec/test_parsers_spec.py b/spec/test_parsers_spec.py index b3782e0..1333c41 100644 --- a/spec/test_parsers_spec.py +++ b/spec/test_parsers_spec.py @@ -8,6 +8,7 @@ from cchloader.parsers.a5d import A5d from cchloader.parsers.b5d import B5d from cchloader.parsers.rf5d import Rf5d +from cchloader.parsers.mcilqh import McilQh from cchloader.parsers.mhcil import Mhcil from cchloader.parsers.medidas import Medidas from cchloader.parsers.corbagen import CorbaGen @@ -68,6 +69,9 @@ self.infpa_filenames = [ 'INFPA_H3_1234_P2_202401.0.bz2' # Documented ] + self.mcilqh_filenames = [ + 'MCILQH_20240501_demo' # Documented + ] with it('test to get F1 parser'): for filename in self.f1_filenames: @@ -234,3 +238,14 @@ def test_raise_error(): expect(test_raise_error).to(raise_error( ParserNotFoundException)) + + with it('test to get MCILQH parser'): + for filename in self.mcilqh_filenames: + expect(get_parser(filename)).to(equal(McilQh)) + with it('MCILQH parser fits file format'): + with CchFile('spec/curve_files/MCILQH_20240501_demo') as cch_file: + for line in cch_file: + expected_mcilqh = 'ES0044444444444444441F001;2024;05;01;00;15;0;0;0;0;0;0;0;R;\n' + result_mcilqh = line['orig'] + assert result_mcilqh == expected_mcilqh + break