• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

timcera / pyslice / 12340932278

15 Dec 2024 05:42PM CUT coverage: 45.447%. Remained the same
12340932278

Pull #4

github

web-flow
Merge d90cfa984 into 2ffee6f33
Pull Request #4: build(deps): bump actions/setup-python from 4 to 5

529 of 1164 relevant lines covered (45.45%)

2.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.62
/src/pyslice/pyslice_lib/PySPG/ParamParser.py
1
"""
2
:::~ Author: Claudio Juan Tessone <tessonec@imedea.uib.es> (c) 2002-2005
3

4
Distributed According to GNU Generic Purpose License (GPL)
5
Please visit http://www.gnu.org
6
"""
7

8
# :::~ Important: for constants and functions already defined
9
import copy
5✔
10
import sys
5✔
11

12
from . import ParamIterators
5✔
13

14

15
class ParamParser:
5✔
16
    """
17
    Initialized with a list of strings, each one containing commands.
18
    Each line will have a syntax as follows
19
    (iterator_type) (variable_name) [bounds]
20
    (iterator_type) can be one of the following characters
21
    '+' '-' '*' '/'  => all of them expect bounds given by [min_value]
22
                        [max_value] [step]
23
    '.'              => punctual iterator, (bounds) is in fact a (BLANK
24
                        separated) list with all the possible values
25
    ':'              => defines a CONSTANT (i.e. not iterable object)
26
    '#'              => repetition operator
27
    """
28

29
    # :::~ This variable specifies the list separator used while parsing
30
    # "param.dat"
31
    separator = " "
5✔
32

33
    # :::~ A dictionary with all the possible iterators
34
    iterator_types_dict = {
5✔
35
        "+": ParamIterators.ItOperatorPlus,
36
        "-": ParamIterators.ItOperatorMinus,
37
        "*": ParamIterators.ItOperatorProduct,
38
        "/": ParamIterators.ItOperatorDivision,
39
        "**": ParamIterators.ItOperatorPower,
40
        ":": ParamIterators.ItConstant,
41
        ".": ParamIterators.ItPunctual,
42
        "#": ParamIterators.ItRepetition,
43
    }
44

45
    # :::~ a list with an alternative order if your binary does not read
46
    # a free-style input file alternative_order = []
47
    # :::~ a list with all the varying entities (i.e. those not CONSTANT)
48
    # isvariable = []
49
    def __init__(self, lsLines):
5✔
50
        """
51
        lsLines is a list of commands understood by this class.
52
        """
53
        self.entities = []
5✔
54
        self.iterator_list = []
5✔
55
        self.variables_list = []
5✔
56
        self.actual_values = {}
5✔
57
        self.__parse(lsLines)
5✔
58

59
        self.reversed = copy.copy(self.iterator_list)
5✔
60
        self.reversed.reverse()
5✔
61
        self.reset()
5✔
62

63
    def __get_iteration_and_command(self, cadena):
5✔
64
        """
65
        returns the iteration type of a command. The iteration type is defined
66
        as the set of non alphanumeric characters at the beginning of the line
67
        """
68
        last_char = 0
5✔
69
        while not cadena[last_char].isalnum():
5✔
70
            last_char += 1
5✔
71
        return cadena[:last_char], cadena[last_char:]
5✔
72

73
    def __parse(self, ls):
5✔
74
        """
75
        internal function that parses the input
76
        """
77
        for sit in ls:
5✔
78
            # strips trailing and leading blanks
79
            # iteration type
80
            it_type, str_rest = self.__get_iteration_and_command(sit.strip())
5✔
81
            new_iterator = self.iterator_types_dict[it_type]()
5✔
82
            new_iterator.set_command(str_rest, self.separator)
5✔
83
            self.iterator_list.append(new_iterator)
5✔
84

85
        self.variables_list = [
5✔
86
            i_iter for i_iter in self.iterator_list if i_iter.is_variable()
87
        ]
88
        self.entities = [i_iter.get_varname() for i_iter in self.iterator_list]
5✔
89

90
    def __next__(self):
5✔
91
        """
92
        next() iterates over the possible values raising a StopIteration when
93
        the possible values are exhausted
94
        """
95
        if self.is_reset:
5✔
96
            self.is_reset = False
5✔
97
            return self.actual_values
5✔
98

99
        for i_iter in self.reversed:
5✔
100
            last_iterated = i_iter
5✔
101
            varname = i_iter.get_varname()
5✔
102
            try:
5✔
103
                self.actual_values[varname] = next(i_iter)
5✔
104

105
                break
5✔
106
            except StopIteration as e:
5✔
107
                self.actual_values[varname] = i_iter.reset()
5✔
108

109
                if last_iterated == self.iterator_list[0]:
5✔
110
                    raise StopIteration from e
5✔
111

112
        return self.actual_values
5✔
113

114
    # 1
115
    def reset(self):
5✔
116
        """
117
        This function resets the iterator to its starting point
118
        """
119
        for i_iter in self.iterator_list:
5✔
120
            i_iter.reset()
5✔
121
            self.actual_values[i_iter.get_varname()] = i_iter.get_value()
5✔
122
        self.is_reset = True
5✔
123

124
    def __iter__(self):
5✔
125
        return self
5✔
126

127
    def __str__(self):
5✔
128
        """
129
        defines how the actual value of the parameter set is printed out.
130
        A good candidate to be overwritten in inheriting classes.
131
        """
132
        thisstr = (
×
133
            "\n".join(
134
                [
135
                    f"{k}{self.separator}{self.actual_values[k]}"
136
                    for k in self.entities
137
                    if k
138
                ]
139
            )
140
            + "\n"
141
        )
142
        # :::~ replaces structures of the kind {var} by var-value, very useful
143
        # for generation of multiple output files.
144
        for i_iter in self.iterator_list:
×
145
            varname = i_iter.get_varname()
×
146
            thisstr = thisstr.replace(
×
147
                f"{varname}", f"{varname}-{self.actual_values[varname]}"
148
            )
149

150
        return thisstr
×
151

152
    def value_of(self, varn):
5✔
153
        """
154
        returns the actual value of the variable 'varn'
155
        """
156
        try:
×
157
            return self.actual_values[varn]
×
158
        except ValueError:
×
159
            sys.stderr.write(
×
160
                f"""'{varn}' not found among entities
161
"""
162
            )
163
            sys.exit()
×
164

165
    def set_order(self, new_order):
5✔
166
        """
167
        sets a new order for the output.
168
        May be a subset of the variables, but it can not be a superset
169
        useful if your program only reads a fixed input file
170
        """
171
        try:
×
172
            for i in new_order:
×
173
                [k.get_varname() for k in self.iterator_list].index(i)
×
174
        except ValueError:
×
175
            sys.stderr.write(
×
176
                f"""error! {i} not found among entities
177
entities = {self.entities}"""
178
            )
179
            sys.exit()
×
180
        self.entities = new_order
×
181

182
    # 1
183
    def directory_tree(self, limit=-1):
5✔
184
        """
185
        returns the directory path conducting to the actual values of the
186
        parameter set.  by default (limit=-1) the directory tree is extended to
187
        all the variables list except for the last variable.
188

189
        By setting limit to something else, you change the amount of variables
190
        kept left from the directory generation. (i.e. limit=-2, will leave out
191
        of the directory path the last two variables)
192

193
        """
194

195
        import os.path
5✔
196

197
        thepath = os.path.curdir + os.path.sep
5✔
198

199
        for i_iter in self.variables_list[:limit]:
5✔
200
            thepath += f"{i_iter.get_varname()}-{self.actual_values[i_iter.get_varname()]}{os.path.sep}"
5✔
201

202
        return thepath
5✔
203

204
    # 1
205
    def output_tree(self, limit=-1):
5✔
206
        """
207
        returns the output from limit given the actual values of the parameter set.
208
        by default (limit=-1) the output will only print the last variable value.
209
        By setting limit to something else, you change the amount of variables printed
210
        (i.e. limit=-2, will print the value of the last two variables)
211
        """
212
        return "".join(
×
213
            f"{self.actual_values[i_iter.get_varname()]}{self.separator}"
214
            for i_iter in self.variables_list[limit:]
215
        )
216

217

218
#
219
#
220
if __name__ == "__main__":
5✔
221
    # command=[":a 0","*c 2 6 3",":filename {c}.dat","+d 5 9 4","#2",":end"]
222
    #  command=["*c 2 18 3"]
223
    command = [":a 0", "*c 2 6 3", ":filename {c}.dat", "+d 5 9 4", ":end"]
×
224
    #
225
    print(command)
×
226
    pp = ParamParser(command)
×
227
    for i in pp:
×
228
        print(pp)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc