csvpath 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. csvpath/__init__.py +1 -0
  2. csvpath/csvpath.py +368 -0
  3. csvpath/matching/__init__.py +1 -0
  4. csvpath/matching/expression_encoder.py +108 -0
  5. csvpath/matching/expression_math.py +123 -0
  6. csvpath/matching/expression_utility.py +29 -0
  7. csvpath/matching/functions/above.py +36 -0
  8. csvpath/matching/functions/add.py +24 -0
  9. csvpath/matching/functions/below.py +36 -0
  10. csvpath/matching/functions/concat.py +25 -0
  11. csvpath/matching/functions/count.py +44 -0
  12. csvpath/matching/functions/count_lines.py +12 -0
  13. csvpath/matching/functions/count_scans.py +13 -0
  14. csvpath/matching/functions/divide.py +30 -0
  15. csvpath/matching/functions/end.py +18 -0
  16. csvpath/matching/functions/every.py +33 -0
  17. csvpath/matching/functions/first.py +46 -0
  18. csvpath/matching/functions/function.py +31 -0
  19. csvpath/matching/functions/function_factory.py +114 -0
  20. csvpath/matching/functions/inf.py +38 -0
  21. csvpath/matching/functions/is_instance.py +95 -0
  22. csvpath/matching/functions/length.py +33 -0
  23. csvpath/matching/functions/lower.py +21 -0
  24. csvpath/matching/functions/minf.py +167 -0
  25. csvpath/matching/functions/multiply.py +27 -0
  26. csvpath/matching/functions/no.py +10 -0
  27. csvpath/matching/functions/notf.py +26 -0
  28. csvpath/matching/functions/now.py +33 -0
  29. csvpath/matching/functions/orf.py +28 -0
  30. csvpath/matching/functions/percent.py +29 -0
  31. csvpath/matching/functions/random.py +33 -0
  32. csvpath/matching/functions/regex.py +38 -0
  33. csvpath/matching/functions/subtract.py +28 -0
  34. csvpath/matching/functions/tally.py +36 -0
  35. csvpath/matching/functions/upper.py +21 -0
  36. csvpath/matching/matcher.py +215 -0
  37. csvpath/matching/matching_lexer.py +66 -0
  38. csvpath/matching/parser.out +1287 -0
  39. csvpath/matching/parsetab.py +1427 -0
  40. csvpath/matching/productions/equality.py +158 -0
  41. csvpath/matching/productions/expression.py +16 -0
  42. csvpath/matching/productions/header.py +30 -0
  43. csvpath/matching/productions/matchable.py +41 -0
  44. csvpath/matching/productions/term.py +11 -0
  45. csvpath/matching/productions/variable.py +15 -0
  46. csvpath/parser_utility.py +39 -0
  47. csvpath/scanning/__init__.py +1 -0
  48. csvpath/scanning/parser.out +1 -0
  49. csvpath/scanning/parsetab.py +231 -0
  50. csvpath/scanning/scanner.py +165 -0
  51. csvpath/scanning/scanning_lexer.py +47 -0
  52. csvpath-0.0.2.dist-info/METADATA +184 -0
  53. csvpath-0.0.2.dist-info/RECORD +54 -0
  54. csvpath-0.0.2.dist-info/WHEEL +4 -0
@@ -0,0 +1,158 @@
1
+ from typing import Any, List
2
+ from csvpath.matching.productions.variable import Variable
3
+ from csvpath.matching.productions.matchable import Matchable
4
+ from csvpath.matching.productions.header import Header
5
+ from csvpath.matching.productions.term import Term
6
+ from csvpath.matching.functions.function import Function
7
+
8
+
9
+ class Equality(Matchable):
10
+ def __init__(self, matcher):
11
+ super().__init__(matcher)
12
+ self.op: str = (
13
+ "=" # we assume = but if a function or other containing production
14
+ )
15
+ # wants to check we might have a different op
16
+
17
+ @property
18
+ def left(self):
19
+ return self.children[0]
20
+
21
+ @left.setter
22
+ def left(self, o):
23
+ if not self.children:
24
+ self.children = [None, None]
25
+ while len(self.children) < 2:
26
+ self.children.append(None)
27
+ else:
28
+ self.children[0] = o
29
+
30
+ @property
31
+ def right(self):
32
+ return self.children[1]
33
+
34
+ @right.setter
35
+ def right(self, o):
36
+ if not self.children:
37
+ self.children = [None, None]
38
+ while len(self.children) < 2:
39
+ self.children.append(None)
40
+ self.children[1] = o
41
+
42
+ def other_child(self, o):
43
+ if self.left == o:
44
+ return (self.right, 1)
45
+ elif self.right == o:
46
+ return (self.left, 0)
47
+ else:
48
+ return None
49
+
50
+ def is_terminal(self, o):
51
+ return (
52
+ isinstance(o, Variable)
53
+ or isinstance(o, Term)
54
+ or isinstance(o, Header)
55
+ or isinstance(o, Function)
56
+ or o is None
57
+ )
58
+
59
+ def both_terminal(self):
60
+ return self.is_terminal(self.left) and self.is_terminal(self.right)
61
+
62
+ def commas_to_list(self) -> List[Any]:
63
+ ls = []
64
+ self._to_list(ls, self)
65
+ return ls
66
+
67
+ def _to_list(self, ls: List, p):
68
+ if isinstance(p, Equality) and p.op == ",":
69
+ self._to_list(ls, p.left)
70
+ self._to_list(ls, p.right)
71
+ else:
72
+ ls.append(p)
73
+
74
+ def set_left(self, left):
75
+ self.left = left
76
+ if self.left:
77
+ self.add_child(self.left)
78
+
79
+ def set_right(self, right):
80
+ self.right = right
81
+ if self.right:
82
+ self.add_child(self.right)
83
+
84
+ def set_operation(self, op):
85
+ self.op = op
86
+
87
+ # ------------------
88
+
89
+ def mathic(self):
90
+ return self.op != ","
91
+
92
+ def perform_math(self):
93
+ if self.op == "," or self.op == "=":
94
+ return
95
+ else:
96
+ if isinstance(self.left, Equality):
97
+ pass
98
+ # self.left.perform_math()
99
+ if isinstance(self.right, Equality) and self.mathic():
100
+ pass
101
+ # self.right.perform_math()
102
+ self.left.value = self.math(self.left.to_value(), self.right.to_value())
103
+ if isinstance(self.left, Variable):
104
+ v = self.left.value
105
+ self.matcher.set_variable(self.left.name, value=v)
106
+
107
+ self.value = None
108
+ self.to_value()
109
+
110
+ def math(self, lv, rv):
111
+ if self.op == "-":
112
+ return lv - rv
113
+ elif self.op == "+":
114
+ return lv + rv
115
+ elif self.op == "*":
116
+ return lv * rv
117
+ elif self.op == "/":
118
+ return lv / rv
119
+ else:
120
+ raise Exception(f"unknown op: {self.op}")
121
+
122
+ # ------------------
123
+
124
+ def __str__(self) -> str:
125
+ return f"""{self.__class__}: {self.left}={self.right}"""
126
+
127
+ def matches(self, *, skip=[]) -> bool:
128
+ if self in skip:
129
+ return True
130
+ if not self.left or not self.right:
131
+ return False
132
+ if not self.value:
133
+ b = None
134
+ if isinstance(self.left, Variable):
135
+ v = self.right.to_value(skip=skip)
136
+ self.matcher.set_variable(self.left.name, value=v)
137
+ b = True
138
+ else:
139
+ left = self.left.to_value(skip=skip)
140
+ right = self.right.to_value(skip=skip)
141
+ if left.__class__ == right.__class__:
142
+ b = self.left.to_value(skip=skip) == self.right.to_value(skip=skip)
143
+ elif (left.__class__ == str and right.__class__ == int) or (
144
+ right.__class__ == str and left.__class__ == int
145
+ ):
146
+ b = f"{left}" == f"{right}"
147
+ else:
148
+ b = f"{left}" == f"{right}"
149
+ self.value = b
150
+ return self.value
151
+
152
+ def to_value(self, *, skip=[]) -> Any:
153
+ if self.value is None:
154
+ if self.mathic():
155
+ pass
156
+ # self.perform_math()
157
+ self.value = self.matches(skip=skip)
158
+ return self.value
@@ -0,0 +1,16 @@
1
+ from csvpath.matching.productions.matchable import Matchable
2
+
3
+
4
+ class Expression(Matchable):
5
+ def matches(self, *, skip=[]) -> bool:
6
+ if not skip:
7
+ skip = []
8
+ if self in skip:
9
+ return True
10
+ if not self.value:
11
+ ret = True
12
+ for i, child in enumerate(self.children):
13
+ if not child.matches(skip=skip):
14
+ ret = False
15
+ self.value = ret
16
+ return self.value
@@ -0,0 +1,30 @@
1
+ from typing import Any
2
+ from csvpath.matching.productions.matchable import Matchable
3
+
4
+
5
+ class Header(Matchable):
6
+ def __str__(self) -> str:
7
+ return f"""{self.__class__}: {self.name} """
8
+
9
+ def to_value(self, *, skip=[]) -> Any:
10
+ if self in skip:
11
+ return True
12
+ if isinstance(self.name, int):
13
+ if self.name >= len(self.matcher.line):
14
+ return None
15
+ else:
16
+ return self.matcher.line[self.name]
17
+ else:
18
+ n = self.matcher.header_index(self.name)
19
+ # print(f"Header.to_value: n: {n}, a {n.__class__}")
20
+ if n is None:
21
+ # print(f"Header.to_value: no such header {self.name}")
22
+ return None
23
+ # print(f"Header: header index: {self.name} = {n}, line: {self.matcher.line}")
24
+ ret = None
25
+ if self.matcher.line and len(self.matcher.line) > n:
26
+ ret = self.matcher.line[n]
27
+ return ret
28
+
29
+ def matches(self, *, skip=[]) -> bool:
30
+ return not self.to_value(skip=skip) is None
@@ -0,0 +1,41 @@
1
+ from typing import Any, Self
2
+ from csvpath.matching.expression_utility import ExpressionUtility
3
+
4
+
5
+ class Matchable:
6
+ def __init__(self, matcher, *, value: Any = None, name: str = None):
7
+ self.parent = None
8
+ self.children = []
9
+ self.matcher = matcher
10
+ self.value = value
11
+ self.name = name
12
+ self._id: str = None
13
+ if self.name and self.name.__class__ == str:
14
+ self.name = self.name.strip()
15
+
16
+ def __str__(self) -> str:
17
+ return f"""{self.__class__}"""
18
+
19
+ def matches(self, *, skip=[]) -> bool:
20
+ return True # leave this for now for testing
21
+
22
+ def to_value(self, *, skip=[]) -> Any:
23
+ return None
24
+
25
+ def index_of_child(self, o) -> int:
26
+ return self.children.index(o)
27
+
28
+ def set_parent(self, parent: Self) -> None:
29
+ self.parent = parent
30
+
31
+ def add_child(self, child: Self) -> None:
32
+ if child:
33
+ child.set_parent(self)
34
+ if child not in self.children:
35
+ self.children.append(child)
36
+
37
+ def get_id(self, child: Self = None) -> str:
38
+ if not self._id:
39
+ thing = self if not child else child
40
+ self._id = ExpressionUtility.get_id(thing=thing)
41
+ return self._id
@@ -0,0 +1,11 @@
1
+ from typing import Any
2
+ from csvpath.matching.productions.matchable import Matchable
3
+
4
+
5
+ class Term(Matchable):
6
+ def __str__(self) -> str:
7
+ return f"""{self.__class__}: {self.value} """
8
+
9
+ def to_value(self, *, skip=[]) -> Any:
10
+ v = self.value
11
+ return v
@@ -0,0 +1,15 @@
1
+ from typing import Any
2
+ from csvpath.matching.productions.matchable import Matchable
3
+
4
+
5
+ class Variable(Matchable):
6
+ def __str__(self) -> str:
7
+ return f"""{self.__class__}: {self.name}"""
8
+
9
+ def matches(self, *, skip=[]) -> bool:
10
+ return self.value is not None
11
+
12
+ def to_value(self, *, skip=[]) -> Any:
13
+ if not self.value:
14
+ self.value = self.matcher.get_variable(self.name)
15
+ return self.value
@@ -0,0 +1,39 @@
1
+ from ply.yacc import YaccProduction
2
+
3
+
4
+ class ParserUtility:
5
+ def __init__(self, quiet=True):
6
+ self._quiet = quiet
7
+
8
+ def error(self, parser, p: YaccProduction) -> None:
9
+ if self._quiet and False:
10
+ return
11
+ # print(f"ParserUtility.error: {p}")
12
+ if p:
13
+ print(
14
+ f"syntax error at token {p.type}, line {p.lineno}, position {p.lexpos}"
15
+ )
16
+ print(f"unexpected token: {p.value}")
17
+ stack = parser.symstack
18
+ print(f"symbol stack: {stack}")
19
+ else:
20
+ print("syntax error at EOF")
21
+
22
+ def print_production(
23
+ self, p: YaccProduction, label: str = None, override=True
24
+ ) -> None:
25
+ if self._quiet and not override:
26
+ return
27
+ if label:
28
+ label = f" at {label}"
29
+ print(f"production array{label} is:")
30
+ for _ in p:
31
+ print(f"\t{_} \t-> {_.__class__}")
32
+
33
+ @classmethod
34
+ def enumerate_p(self, message, p, quiet=True):
35
+ if quiet:
36
+ return
37
+ print(f"Enumerate {p}: {message}:")
38
+ for i, _ in enumerate(p):
39
+ print(f" p[{i}]: {_}")
@@ -0,0 +1 @@
1
+
@@ -0,0 +1 @@
1
+ Created by PLY version 3.11 (http://www.dabeaz.com/ply)
@@ -0,0 +1,231 @@
1
+ # parsetab.py
2
+ # This file is automatically generated. Do not edit.
3
+ # pylint: disable=W,C,R
4
+ _tabversion = "3.10"
5
+
6
+ _lr_method = "LALR"
7
+
8
+ _lr_signature = "pathALL_LINES ANY FILENAME LEFT_BRACKET MINUS NAME NUMBER PLUS RIGHT_BRACKET ROOTroot : ROOT filenamefilename : FILENAMEpath : root LEFT_BRACKET expression RIGHT_BRACKETexpression : expression PLUS term\n | expression MINUS term\n | termterm : NUMBER\n | NUMBER ALL_LINES\n | ALL_LINES"
9
+
10
+ _lr_action_items = {
11
+ "ROOT": (
12
+ [
13
+ 0,
14
+ ],
15
+ [
16
+ 3,
17
+ ],
18
+ ),
19
+ "$end": (
20
+ [
21
+ 1,
22
+ 11,
23
+ ],
24
+ [
25
+ 0,
26
+ -3,
27
+ ],
28
+ ),
29
+ "LEFT_BRACKET": (
30
+ [
31
+ 2,
32
+ 5,
33
+ 6,
34
+ ],
35
+ [
36
+ 4,
37
+ -1,
38
+ -2,
39
+ ],
40
+ ),
41
+ "FILENAME": (
42
+ [
43
+ 3,
44
+ ],
45
+ [
46
+ 6,
47
+ ],
48
+ ),
49
+ "NUMBER": (
50
+ [
51
+ 4,
52
+ 12,
53
+ 13,
54
+ ],
55
+ [
56
+ 9,
57
+ 9,
58
+ 9,
59
+ ],
60
+ ),
61
+ "ALL_LINES": (
62
+ [
63
+ 4,
64
+ 9,
65
+ 12,
66
+ 13,
67
+ ],
68
+ [
69
+ 10,
70
+ 14,
71
+ 10,
72
+ 10,
73
+ ],
74
+ ),
75
+ "RIGHT_BRACKET": (
76
+ [
77
+ 7,
78
+ 8,
79
+ 9,
80
+ 10,
81
+ 14,
82
+ 15,
83
+ 16,
84
+ ],
85
+ [
86
+ 11,
87
+ -6,
88
+ -7,
89
+ -9,
90
+ -8,
91
+ -4,
92
+ -5,
93
+ ],
94
+ ),
95
+ "PLUS": (
96
+ [
97
+ 7,
98
+ 8,
99
+ 9,
100
+ 10,
101
+ 14,
102
+ 15,
103
+ 16,
104
+ ],
105
+ [
106
+ 12,
107
+ -6,
108
+ -7,
109
+ -9,
110
+ -8,
111
+ -4,
112
+ -5,
113
+ ],
114
+ ),
115
+ "MINUS": (
116
+ [
117
+ 7,
118
+ 8,
119
+ 9,
120
+ 10,
121
+ 14,
122
+ 15,
123
+ 16,
124
+ ],
125
+ [
126
+ 13,
127
+ -6,
128
+ -7,
129
+ -9,
130
+ -8,
131
+ -4,
132
+ -5,
133
+ ],
134
+ ),
135
+ }
136
+
137
+ _lr_action = {}
138
+ for _k, _v in _lr_action_items.items():
139
+ for _x, _y in zip(_v[0], _v[1]):
140
+ if not _x in _lr_action:
141
+ _lr_action[_x] = {}
142
+ _lr_action[_x][_k] = _y
143
+ del _lr_action_items
144
+
145
+ _lr_goto_items = {
146
+ "path": (
147
+ [
148
+ 0,
149
+ ],
150
+ [
151
+ 1,
152
+ ],
153
+ ),
154
+ "root": (
155
+ [
156
+ 0,
157
+ ],
158
+ [
159
+ 2,
160
+ ],
161
+ ),
162
+ "filename": (
163
+ [
164
+ 3,
165
+ ],
166
+ [
167
+ 5,
168
+ ],
169
+ ),
170
+ "expression": (
171
+ [
172
+ 4,
173
+ ],
174
+ [
175
+ 7,
176
+ ],
177
+ ),
178
+ "term": (
179
+ [
180
+ 4,
181
+ 12,
182
+ 13,
183
+ ],
184
+ [
185
+ 8,
186
+ 15,
187
+ 16,
188
+ ],
189
+ ),
190
+ }
191
+
192
+ _lr_goto = {}
193
+ for _k, _v in _lr_goto_items.items():
194
+ for _x, _y in zip(_v[0], _v[1]):
195
+ if not _x in _lr_goto:
196
+ _lr_goto[_x] = {}
197
+ _lr_goto[_x][_k] = _y
198
+ del _lr_goto_items
199
+ _lr_productions = [
200
+ ("S' -> path", "S'", 1, None, None, None),
201
+ ("root -> ROOT filename", "root", 2, "p_root", "scanner.py", 64),
202
+ ("filename -> FILENAME", "filename", 1, "p_filename", "scanner.py", 67),
203
+ (
204
+ "path -> root LEFT_BRACKET expression RIGHT_BRACKET",
205
+ "path",
206
+ 4,
207
+ "p_path",
208
+ "scanner.py",
209
+ 71,
210
+ ),
211
+ (
212
+ "expression -> expression PLUS term",
213
+ "expression",
214
+ 3,
215
+ "p_expression",
216
+ "scanner.py",
217
+ 77,
218
+ ),
219
+ (
220
+ "expression -> expression MINUS term",
221
+ "expression",
222
+ 3,
223
+ "p_expression",
224
+ "scanner.py",
225
+ 78,
226
+ ),
227
+ ("expression -> term", "expression", 1, "p_expression", "scanner.py", 79),
228
+ ("term -> NUMBER", "term", 1, "p_term", "scanner.py", 90),
229
+ ("term -> NUMBER ALL_LINES", "term", 2, "p_term", "scanner.py", 91),
230
+ ("term -> ALL_LINES", "term", 1, "p_term", "scanner.py", 92),
231
+ ]