fmtr.tools 1.2.6__py3-none-any.whl → 1.2.7__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.
Potentially problematic release.
This version of fmtr.tools might be problematic. Click here for more details.
- fmtr/tools/pattern_tools.py +124 -67
- fmtr/tools/version +1 -1
- {fmtr_tools-1.2.6.dist-info → fmtr_tools-1.2.7.dist-info}/METADATA +44 -44
- {fmtr_tools-1.2.6.dist-info → fmtr_tools-1.2.7.dist-info}/RECORD +8 -8
- {fmtr_tools-1.2.6.dist-info → fmtr_tools-1.2.7.dist-info}/WHEEL +0 -0
- {fmtr_tools-1.2.6.dist-info → fmtr_tools-1.2.7.dist-info}/entry_points.txt +0 -0
- {fmtr_tools-1.2.6.dist-info → fmtr_tools-1.2.7.dist-info}/licenses/LICENSE +0 -0
- {fmtr_tools-1.2.6.dist-info → fmtr_tools-1.2.7.dist-info}/top_level.txt +0 -0
fmtr/tools/pattern_tools.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import regex as re
|
|
2
|
-
from dataclasses import dataclass
|
|
2
|
+
from dataclasses import dataclass, asdict
|
|
3
3
|
from functools import cached_property
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import List, Any
|
|
5
5
|
|
|
6
6
|
from fmtr.tools.logging_tools import logger
|
|
7
|
+
from fmtr.tools.string_tools import join
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class RewriteCircularLoopError(Exception):
|
|
@@ -14,59 +15,101 @@ class RewriteCircularLoopError(Exception):
|
|
|
14
15
|
"""
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
MASK_GROUP = '(?:{pattern})'
|
|
19
|
+
MASK_NAMED = r"(?P<{key}>{pattern})"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def alt(*patterns):
|
|
23
|
+
patterns = sorted(patterns, key=len, reverse=True)
|
|
24
|
+
pattern = '|'.join(patterns)
|
|
25
|
+
pattern = MASK_GROUP.format(pattern=pattern)
|
|
26
|
+
return pattern
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
17
33
|
@dataclass
|
|
18
|
-
class
|
|
19
|
-
|
|
20
|
-
Represents a single rule for pattern matching and target string replacement.
|
|
34
|
+
class Key:
|
|
35
|
+
RECORD_SEP = '␞'
|
|
21
36
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
The `target` allows rewriting the identified matches with a formatted string.
|
|
25
|
-
It provides properties for generating a unique identifier for use as a regex group name and compiling the provided pattern into a regular expression object.
|
|
37
|
+
def flatten(self, data):
|
|
38
|
+
"""
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
Flatten/serialise dictionary data
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
pairs = [f'{value}' for key, value in data.items()]
|
|
44
|
+
string = self.RECORD_SEP.join(pairs)
|
|
45
|
+
return string
|
|
30
46
|
|
|
31
47
|
@cached_property
|
|
32
|
-
def
|
|
48
|
+
def pattern(self):
|
|
33
49
|
"""
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
50
|
+
|
|
51
|
+
Serialise to pattern
|
|
52
|
+
|
|
37
53
|
"""
|
|
38
|
-
|
|
54
|
+
data = {key: MASK_NAMED.format(key=key, pattern=value) for key, value in asdict(self).items()}
|
|
55
|
+
pattern = self.flatten(data)
|
|
56
|
+
return pattern
|
|
39
57
|
|
|
40
58
|
@cached_property
|
|
41
59
|
def rx(self):
|
|
42
60
|
"""
|
|
43
61
|
|
|
44
|
-
|
|
62
|
+
Compile to Regular Expression
|
|
45
63
|
|
|
46
64
|
"""
|
|
47
65
|
return re.compile(self.pattern)
|
|
48
66
|
|
|
49
|
-
|
|
67
|
+
@cached_property
|
|
68
|
+
def string(self):
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
Serialise to string
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
string = self.flatten(asdict(self))
|
|
75
|
+
return string
|
|
76
|
+
|
|
77
|
+
def transform(self, match: re.Match):
|
|
50
78
|
"""
|
|
51
79
|
|
|
52
|
-
|
|
80
|
+
Transform match object into a new object of the same type.
|
|
53
81
|
|
|
54
82
|
"""
|
|
55
|
-
|
|
56
|
-
|
|
83
|
+
groupdict = match.groupdict()
|
|
84
|
+
data = {key: value.format(**groupdict) for key, value in asdict(self).items()}
|
|
85
|
+
obj = self.__class__(**data)
|
|
86
|
+
return obj
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass
|
|
90
|
+
class Item:
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
Key-value pair
|
|
57
94
|
|
|
95
|
+
"""
|
|
96
|
+
key: Key
|
|
97
|
+
value: Key
|
|
58
98
|
|
|
59
99
|
@dataclass
|
|
60
|
-
class
|
|
100
|
+
class Mapper:
|
|
61
101
|
"""
|
|
62
102
|
|
|
63
|
-
|
|
103
|
+
Pattern-based, dictionary-like mapper.
|
|
64
104
|
Compiles a single regex pattern from a list of rules, and determines which rule matched.
|
|
65
|
-
It supports initialization from structured rule data, execution of a single
|
|
66
|
-
recursive
|
|
105
|
+
It supports initialization from structured rule data, execution of a single lookup pass, and
|
|
106
|
+
recursive lookups until a stable state is reached.
|
|
67
107
|
|
|
68
108
|
"""
|
|
69
|
-
|
|
109
|
+
PREFIX_GROUP = '__'
|
|
110
|
+
items: List[Item]
|
|
111
|
+
default: Any = None
|
|
112
|
+
is_recursive: bool = False
|
|
70
113
|
|
|
71
114
|
@cached_property
|
|
72
115
|
def pattern(self):
|
|
@@ -75,71 +118,90 @@ class Rewriter:
|
|
|
75
118
|
Provides a dynamically generated regex pattern based on the rules provided.
|
|
76
119
|
|
|
77
120
|
"""
|
|
78
|
-
patterns = [
|
|
79
|
-
|
|
80
|
-
|
|
121
|
+
patterns = [
|
|
122
|
+
MASK_NAMED.format(key=f'{self.PREFIX_GROUP}{i}', pattern=item.key.pattern)
|
|
123
|
+
for i, item in enumerate(self.items)
|
|
124
|
+
]
|
|
125
|
+
pattern = alt(*patterns)
|
|
81
126
|
return pattern
|
|
82
127
|
|
|
83
128
|
@cached_property
|
|
84
|
-
def
|
|
129
|
+
def rx(self):
|
|
85
130
|
"""
|
|
86
131
|
|
|
87
|
-
|
|
132
|
+
Regex object.
|
|
133
|
+
|
|
88
134
|
"""
|
|
135
|
+
return re.compile(self.pattern)
|
|
89
136
|
|
|
90
|
-
|
|
137
|
+
def get_default(self, key: Key):
|
|
138
|
+
if self.is_recursive:
|
|
139
|
+
return key
|
|
140
|
+
else:
|
|
141
|
+
return self.default
|
|
91
142
|
|
|
92
|
-
|
|
93
|
-
def rx(self):
|
|
143
|
+
def get(self, key: Key) -> Key:
|
|
94
144
|
"""
|
|
95
145
|
|
|
96
|
-
|
|
146
|
+
Use recursive or single lookup pass, depending on whether recursive lookups have been specified.
|
|
97
147
|
|
|
98
148
|
"""
|
|
99
|
-
|
|
149
|
+
if self.is_recursive:
|
|
150
|
+
return self.get_recursive(key)
|
|
151
|
+
else:
|
|
152
|
+
return self.get_one(key)
|
|
100
153
|
|
|
101
|
-
def
|
|
154
|
+
def get_one(self, key: Key):
|
|
102
155
|
"""
|
|
103
156
|
|
|
104
|
-
Single
|
|
105
|
-
|
|
157
|
+
Single lookup pass.
|
|
158
|
+
Lookup the source string based on the matching rule.
|
|
106
159
|
|
|
107
160
|
"""
|
|
108
161
|
|
|
109
|
-
match = self.rx.fullmatch(
|
|
162
|
+
match = self.rx.fullmatch(key.string)
|
|
110
163
|
|
|
111
164
|
if not match:
|
|
112
|
-
|
|
165
|
+
value = self.get_default(key)
|
|
166
|
+
logger.debug(f'No match for {key=}.')
|
|
167
|
+
else:
|
|
168
|
+
|
|
169
|
+
match_ids = {name: v for name, v in match.groupdict().items() if v}
|
|
170
|
+
rule_ids = {
|
|
171
|
+
int(id.removeprefix(self.PREFIX_GROUP))
|
|
172
|
+
for id in match_ids.keys() if id.startswith(self.PREFIX_GROUP)
|
|
173
|
+
}
|
|
113
174
|
|
|
114
|
-
|
|
115
|
-
|
|
175
|
+
if len(rule_ids) != 1:
|
|
176
|
+
msg = f'Multiple group matches: {rule_ids}'
|
|
177
|
+
raise ValueError(msg)
|
|
116
178
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
raise ValueError(msg)
|
|
179
|
+
rule_id = next(iter(rule_ids))
|
|
180
|
+
rule = self.items[rule_id]
|
|
120
181
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
182
|
+
if isinstance(rule.value, Key):
|
|
183
|
+
value = rule.value.transform(match)
|
|
184
|
+
else:
|
|
185
|
+
value = rule.value
|
|
124
186
|
|
|
125
|
-
|
|
187
|
+
logger.debug(f'Matched using {rule_id=}: {key=} → {value=}')
|
|
126
188
|
|
|
127
|
-
return
|
|
189
|
+
return value
|
|
128
190
|
|
|
129
|
-
def
|
|
191
|
+
def get_recursive(self, key: Key) -> Key:
|
|
130
192
|
"""
|
|
131
193
|
|
|
132
|
-
|
|
194
|
+
Lookup the provided text by continuously applying lookup rules until no changes are made
|
|
133
195
|
or a circular loop is detected.
|
|
134
196
|
|
|
135
197
|
"""
|
|
136
198
|
history = []
|
|
137
|
-
previous =
|
|
199
|
+
previous = key
|
|
138
200
|
|
|
139
201
|
def get_history_str():
|
|
140
|
-
return '
|
|
202
|
+
return join(history, sep=' → ')
|
|
141
203
|
|
|
142
|
-
with logger.span(f'
|
|
204
|
+
with logger.span(f'Matching {key=}...'):
|
|
143
205
|
while True:
|
|
144
206
|
if previous in history:
|
|
145
207
|
history.append(previous)
|
|
@@ -150,7 +212,7 @@ class Rewriter:
|
|
|
150
212
|
|
|
151
213
|
new = previous
|
|
152
214
|
|
|
153
|
-
new = self.
|
|
215
|
+
new = self.get_one(new)
|
|
154
216
|
|
|
155
217
|
if new == previous:
|
|
156
218
|
break
|
|
@@ -158,18 +220,13 @@ class Rewriter:
|
|
|
158
220
|
previous = new
|
|
159
221
|
|
|
160
222
|
if len(history) == 1:
|
|
161
|
-
history_str = 'No
|
|
223
|
+
history_str = 'No matching performed.'
|
|
162
224
|
else:
|
|
163
225
|
history_str = get_history_str()
|
|
164
|
-
logger.debug(f'Finished
|
|
226
|
+
logger.debug(f'Finished matching: {history_str}')
|
|
165
227
|
|
|
166
228
|
return previous
|
|
167
229
|
|
|
168
|
-
@classmethod
|
|
169
|
-
def from_data(cls, data):
|
|
170
|
-
rules = [Rewrite(*pair) for pair in data.items()]
|
|
171
|
-
self = cls(rules=rules)
|
|
172
|
-
return self
|
|
173
|
-
|
|
174
|
-
|
|
175
230
|
|
|
231
|
+
if __name__ == '__main__':
|
|
232
|
+
...
|
fmtr/tools/version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.2.
|
|
1
|
+
1.2.7
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmtr.tools
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.7
|
|
4
4
|
Summary: Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML
|
|
5
5
|
Home-page: https://github.com/fmtr/tools
|
|
6
6
|
Author: Frontmatter
|
|
@@ -130,60 +130,60 @@ Requires-Dist: logfire[httpx]; extra == "http"
|
|
|
130
130
|
Provides-Extra: setup
|
|
131
131
|
Requires-Dist: setuptools; extra == "setup"
|
|
132
132
|
Provides-Extra: all
|
|
133
|
-
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
134
|
-
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
135
|
-
Requires-Dist: html2text; extra == "all"
|
|
136
|
-
Requires-Dist: distributed; extra == "all"
|
|
137
|
-
Requires-Dist: tabulate; extra == "all"
|
|
138
|
-
Requires-Dist: pydantic; extra == "all"
|
|
139
|
-
Requires-Dist: openpyxl; extra == "all"
|
|
140
|
-
Requires-Dist: httpx; extra == "all"
|
|
141
|
-
Requires-Dist: tokenizers; extra == "all"
|
|
142
|
-
Requires-Dist: fastapi; extra == "all"
|
|
143
|
-
Requires-Dist: logfire; extra == "all"
|
|
144
|
-
Requires-Dist: ollama; extra == "all"
|
|
145
|
-
Requires-Dist: flet[all]; extra == "all"
|
|
146
|
-
Requires-Dist: flet-webview; extra == "all"
|
|
147
|
-
Requires-Dist: flet-video; extra == "all"
|
|
148
133
|
Requires-Dist: torchvision; extra == "all"
|
|
149
|
-
Requires-Dist: httpx_retries; extra == "all"
|
|
150
|
-
Requires-Dist: tinynetrc; extra == "all"
|
|
151
134
|
Requires-Dist: docker; extra == "all"
|
|
152
|
-
Requires-Dist:
|
|
153
|
-
Requires-Dist:
|
|
154
|
-
Requires-Dist:
|
|
135
|
+
Requires-Dist: yamlscript; extra == "all"
|
|
136
|
+
Requires-Dist: google-auth; extra == "all"
|
|
137
|
+
Requires-Dist: pydevd-pycharm; extra == "all"
|
|
138
|
+
Requires-Dist: html2text; extra == "all"
|
|
139
|
+
Requires-Dist: dask[bag]; extra == "all"
|
|
140
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
141
|
+
Requires-Dist: json_repair; extra == "all"
|
|
142
|
+
Requires-Dist: pyyaml; extra == "all"
|
|
143
|
+
Requires-Dist: dnspython[doh]; extra == "all"
|
|
144
|
+
Requires-Dist: contexttimer; extra == "all"
|
|
155
145
|
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
156
|
-
Requires-Dist:
|
|
157
|
-
Requires-Dist: sentence_transformers; extra == "all"
|
|
158
|
-
Requires-Dist: semver; extra == "all"
|
|
146
|
+
Requires-Dist: filetype; extra == "all"
|
|
159
147
|
Requires-Dist: Unidecode; extra == "all"
|
|
160
|
-
Requires-Dist:
|
|
161
|
-
Requires-Dist:
|
|
162
|
-
Requires-Dist:
|
|
148
|
+
Requires-Dist: pymupdf4llm; extra == "all"
|
|
149
|
+
Requires-Dist: flet-webview; extra == "all"
|
|
150
|
+
Requires-Dist: httpx_retries; extra == "all"
|
|
151
|
+
Requires-Dist: sentence_transformers; extra == "all"
|
|
152
|
+
Requires-Dist: tokenizers; extra == "all"
|
|
153
|
+
Requires-Dist: bokeh; extra == "all"
|
|
154
|
+
Requires-Dist: openpyxl; extra == "all"
|
|
155
|
+
Requires-Dist: appdirs; extra == "all"
|
|
163
156
|
Requires-Dist: openai; extra == "all"
|
|
157
|
+
Requires-Dist: sre_yield; extra == "all"
|
|
158
|
+
Requires-Dist: huggingface_hub; extra == "all"
|
|
159
|
+
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
160
|
+
Requires-Dist: fastapi; extra == "all"
|
|
161
|
+
Requires-Dist: deepmerge; extra == "all"
|
|
162
|
+
Requires-Dist: tabulate; extra == "all"
|
|
163
|
+
Requires-Dist: pydantic-settings; extra == "all"
|
|
164
164
|
Requires-Dist: pymupdf; extra == "all"
|
|
165
|
-
Requires-Dist:
|
|
166
|
-
Requires-Dist:
|
|
167
|
-
Requires-Dist: contexttimer; extra == "all"
|
|
168
|
-
Requires-Dist: json_repair; extra == "all"
|
|
165
|
+
Requires-Dist: distributed; extra == "all"
|
|
166
|
+
Requires-Dist: faker; extra == "all"
|
|
169
167
|
Requires-Dist: peft; extra == "all"
|
|
168
|
+
Requires-Dist: flet[all]; extra == "all"
|
|
169
|
+
Requires-Dist: httpx; extra == "all"
|
|
170
|
+
Requires-Dist: semver; extra == "all"
|
|
171
|
+
Requires-Dist: tinynetrc; extra == "all"
|
|
172
|
+
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
173
|
+
Requires-Dist: logfire; extra == "all"
|
|
170
174
|
Requires-Dist: google-api-python-client; extra == "all"
|
|
171
|
-
Requires-Dist:
|
|
172
|
-
Requires-Dist:
|
|
173
|
-
Requires-Dist:
|
|
174
|
-
Requires-Dist: pyyaml; extra == "all"
|
|
175
|
-
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
176
|
-
Requires-Dist: appdirs; extra == "all"
|
|
177
|
-
Requires-Dist: huggingface_hub; extra == "all"
|
|
175
|
+
Requires-Dist: pydantic; extra == "all"
|
|
176
|
+
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
177
|
+
Requires-Dist: ollama; extra == "all"
|
|
178
178
|
Requires-Dist: pandas; extra == "all"
|
|
179
179
|
Requires-Dist: diskcache; extra == "all"
|
|
180
180
|
Requires-Dist: logfire[httpx]; extra == "all"
|
|
181
|
-
Requires-Dist:
|
|
182
|
-
Requires-Dist:
|
|
183
|
-
Requires-Dist:
|
|
184
|
-
Requires-Dist:
|
|
185
|
-
Requires-Dist:
|
|
186
|
-
Requires-Dist:
|
|
181
|
+
Requires-Dist: regex; extra == "all"
|
|
182
|
+
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
183
|
+
Requires-Dist: pytest-cov; extra == "all"
|
|
184
|
+
Requires-Dist: setuptools; extra == "all"
|
|
185
|
+
Requires-Dist: torchaudio; extra == "all"
|
|
186
|
+
Requires-Dist: flet-video; extra == "all"
|
|
187
187
|
Dynamic: author
|
|
188
188
|
Dynamic: author-email
|
|
189
189
|
Dynamic: description
|
|
@@ -30,7 +30,7 @@ fmtr/tools/netrc_tools.py,sha256=PpNpz_mWlQi6VHGromKwFfTyLpHUXsd4LY6-OKLCbeI,376
|
|
|
30
30
|
fmtr/tools/openai_tools.py,sha256=6SUgejgzUzmlKKct2_ePXntvMegu3FJgfk9x7aqtqYc,742
|
|
31
31
|
fmtr/tools/packaging_tools.py,sha256=FlgOTnDRHZWQL2iR-wucTsyGEHRE-MlddKL30MPmUqE,253
|
|
32
32
|
fmtr/tools/parallel_tools.py,sha256=QEb_gN1StkxsqYaH4HSjiJX8Y3gpb2uKNsOzG4uFpaM,3071
|
|
33
|
-
fmtr/tools/pattern_tools.py,sha256=
|
|
33
|
+
fmtr/tools/pattern_tools.py,sha256=GzdhKt-nIHuKCGI9y3aGUaD5k9thbqbA9UXJoPPIcIY,5328
|
|
34
34
|
fmtr/tools/pdf_tools.py,sha256=xvv9B84uAF81rFJRnXhSsxYuP42vY9ZdPVFrSMVe8G8,4069
|
|
35
35
|
fmtr/tools/platform_tools.py,sha256=7p69CmAHe_sF68Fx9uVhns1k5EewTHTWgUYzkl6ZQKA,308
|
|
36
36
|
fmtr/tools/process_tools.py,sha256=Ysh5Dk2QFBhXQerArjKdt7xZd3JrN5Ho02AaOjH0Nnw,1425
|
|
@@ -44,7 +44,7 @@ fmtr/tools/tabular_tools.py,sha256=tpIpZzYku1HcJrHZJL6BC39LmN3WUWVhFbK2N7nDVmE,1
|
|
|
44
44
|
fmtr/tools/tokenization_tools.py,sha256=me-IBzSLyNYejLybwjO9CNB6Mj2NYfKPaOVThXyaGNg,4268
|
|
45
45
|
fmtr/tools/tools.py,sha256=CAsApa1YwVdNE6H66Vjivs_mXYvOas3rh7fPELAnTpk,795
|
|
46
46
|
fmtr/tools/unicode_tools.py,sha256=yS_9wpu8ogNoiIL7s1G_8bETFFO_YQlo4LNPv1NLDeY,52
|
|
47
|
-
fmtr/tools/version,sha256=
|
|
47
|
+
fmtr/tools/version,sha256=5xFfItk8jmF4J6XXD2GJpvj_7M8dldsmM0Uqpe1aihs,5
|
|
48
48
|
fmtr/tools/version_tools.py,sha256=yNs_CGqWpqE4jbK9wsPIi14peJVXYbhIcMqHAFOw3yE,1480
|
|
49
49
|
fmtr/tools/yaml_tools.py,sha256=9kuYChqJelWQIjGlSnK4iDdOWWH06P0gp9jIcRrC3UI,1903
|
|
50
50
|
fmtr/tools/ai_tools/__init__.py,sha256=JZrLuOFNV1A3wvJgonxOgz_4WS-7MfCuowGWA5uYCjs,372
|
|
@@ -73,9 +73,9 @@ fmtr/tools/tests/test_environment.py,sha256=iHaiMQfECYZPkPKwfuIZV9uHuWe3aE-p_dN_
|
|
|
73
73
|
fmtr/tools/tests/test_json.py,sha256=IeSP4ziPvRcmS8kq7k9tHonC9rN5YYq9GSNT2ul6Msk,287
|
|
74
74
|
fmtr/tools/tests/test_path.py,sha256=AkZQa6_8BQ-VaCyL_J-iKmdf2ZaM-xFYR37Kun3k4_g,2188
|
|
75
75
|
fmtr/tools/tests/test_yaml.py,sha256=jc0TwwKu9eC0LvFGNMERdgBue591xwLxYXFbtsRwXVM,287
|
|
76
|
-
fmtr_tools-1.2.
|
|
77
|
-
fmtr_tools-1.2.
|
|
78
|
-
fmtr_tools-1.2.
|
|
79
|
-
fmtr_tools-1.2.
|
|
80
|
-
fmtr_tools-1.2.
|
|
81
|
-
fmtr_tools-1.2.
|
|
76
|
+
fmtr_tools-1.2.7.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
|
|
77
|
+
fmtr_tools-1.2.7.dist-info/METADATA,sha256=3bmhaXPzz8Yt1zSVrOBrOU2i2kvwIwObkBpcP1rfRwE,16025
|
|
78
|
+
fmtr_tools-1.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
79
|
+
fmtr_tools-1.2.7.dist-info/entry_points.txt,sha256=fSQrDGNctdQXbUxpMWYVfVQ0mhZMDyaEDG3D3a0zOSc,278
|
|
80
|
+
fmtr_tools-1.2.7.dist-info/top_level.txt,sha256=LXem9xCgNOD72tE2gRKESdiQTL902mfFkwWb6-dlwEE,5
|
|
81
|
+
fmtr_tools-1.2.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|