file_parser.py 3.38 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# Copyright 2018 Markus Scheidgen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an"AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import os
import logging
import pint
from typing import Any, Dict


class FileParser:
    '''
    Base class for parsers. The parse method implemented here simply sets the parsed
    quantities as attributes of the class. The parse method specific to a file type
    should be implemented in the corresponding child class. The parsed quantities are
    stored in results. One can access a quantity by using the get method.

    Arguments:
        mainfile: the file to be parsed
        logger: optional logger
    '''
    def __init__(self, mainfile: str, logger=None):
        self._mainfile: str = os.path.abspath(mainfile) if mainfile else mainfile
        self.logger = logger if logger else logging
        self._results: Dict[str, Any] = None
        # a key is necessary for xml parsers, where parsing is done dynamically
        self._key: str = None
        self._kwargs: Dict[str, Any] = None
        self._file_handler: Any = None

    @property
    def results(self):
        if self._results is None:
            self._results = dict()
        if self._key not in self._results:
            self.parse(self._key, **self._kwargs)

        return self._results

    @property
    def maindir(self):
        return os.path.dirname(self._mainfile)

    @property
    def mainfile(self):
        if self._mainfile is None:
            return

        if not os.path.isfile(self._mainfile):
            return
        return self._mainfile

    @mainfile.setter
    def mainfile(self, val):
        self._results = None
        self._file_handler = None
        self._mainfile = os.path.abspath(val) if val is not None else val

    def get(self, key: str, default: Any = None, unit: str = None, **kwargs):
        '''
        Returns the parsed result for quantity with name key. If quantity is not in
        results default will be returned. A pint unit can be provided which is attached
        to the returned value.
        '''
        self._key = key
        self._kwargs = kwargs
        val = self.results.get(key, None)
        if val is None:
            val = default

        if val is None:
            return

        if unit is not None:
            if isinstance(unit, pint.Quantity):
                val = val * unit

            elif isinstance(val, pint.Quantity):
                val = val.to(unit)

            else:
                val = pint.Quantity(val, unit)

        return val

    def __getitem__(self, key):
        if isinstance(key, str):
            return self.get(key)
        elif isinstance(key, int):
            return self[int]

    def parse(self, quantity_key: str = None):
        '''
        Sets quantities in result as class attributes.
        '''
        for key, val in self._results.items():
            try:
                setattr(self, key, val)
            except Exception:
                pass
        return self