fmtr.tools 1.3.2__py3-none-any.whl → 1.3.3__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/dns_tools/proxy.py +5 -6
- fmtr/tools/pattern_tools.py +44 -44
- fmtr/tools/version +1 -1
- {fmtr_tools-1.3.2.dist-info → fmtr_tools-1.3.3.dist-info}/METADATA +43 -43
- {fmtr_tools-1.3.2.dist-info → fmtr_tools-1.3.3.dist-info}/RECORD +9 -9
- {fmtr_tools-1.3.2.dist-info → fmtr_tools-1.3.3.dist-info}/WHEEL +0 -0
- {fmtr_tools-1.3.2.dist-info → fmtr_tools-1.3.3.dist-info}/entry_points.txt +0 -0
- {fmtr_tools-1.3.2.dist-info → fmtr_tools-1.3.3.dist-info}/licenses/LICENSE +0 -0
- {fmtr_tools-1.3.2.dist-info → fmtr_tools-1.3.3.dist-info}/top_level.txt +0 -0
fmtr/tools/dns_tools/proxy.py
CHANGED
|
@@ -41,7 +41,7 @@ class Proxy(server.Plain):
|
|
|
41
41
|
|
|
42
42
|
request = exchange.request
|
|
43
43
|
|
|
44
|
-
with logger.span(f'Handling request
|
|
44
|
+
with logger.span(f'Handling request {request.message.id=} {request.question=} {exchange.client=}...'):
|
|
45
45
|
|
|
46
46
|
if not request.is_valid:
|
|
47
47
|
raise ValueError(f'Only one question per request is supported. Got {len(request.question)} questions.')
|
|
@@ -51,7 +51,7 @@ class Proxy(server.Plain):
|
|
|
51
51
|
if exchange.response.is_complete:
|
|
52
52
|
return
|
|
53
53
|
|
|
54
|
-
with logger.span(f'Making upstream request
|
|
54
|
+
with logger.span(f'Making upstream request...'):
|
|
55
55
|
self.client.resolve(exchange)
|
|
56
56
|
if exchange.response.is_complete:
|
|
57
57
|
return
|
|
@@ -61,8 +61,7 @@ class Proxy(server.Plain):
|
|
|
61
61
|
if exchange.response.is_complete:
|
|
62
62
|
return
|
|
63
63
|
|
|
64
|
-
if exchange.response:
|
|
65
|
-
return
|
|
66
|
-
|
|
67
64
|
exchange.response.is_complete = True
|
|
68
|
-
|
|
65
|
+
|
|
66
|
+
logger.info(f'Resolution complete {request.message.id=} {exchange.response.answer=}')
|
|
67
|
+
return
|
fmtr/tools/pattern_tools.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import regex as re
|
|
2
1
|
from dataclasses import dataclass, asdict
|
|
3
2
|
from functools import cached_property
|
|
4
3
|
from typing import List, Any
|
|
5
4
|
|
|
5
|
+
import regex as re
|
|
6
|
+
|
|
6
7
|
from fmtr.tools.logging_tools import logger
|
|
7
8
|
from fmtr.tools.string_tools import join
|
|
8
9
|
|
|
@@ -25,11 +26,6 @@ def alt(*patterns):
|
|
|
25
26
|
pattern = MASK_GROUP.format(pattern=pattern)
|
|
26
27
|
return pattern
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
29
|
@dataclass
|
|
34
30
|
class Key:
|
|
35
31
|
RECORD_SEP = '␞'
|
|
@@ -93,17 +89,18 @@ class Item:
|
|
|
93
89
|
Key-value pair
|
|
94
90
|
|
|
95
91
|
"""
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
source: Key
|
|
93
|
+
target: Key
|
|
98
94
|
|
|
99
95
|
@dataclass
|
|
100
|
-
class
|
|
96
|
+
class Transformer:
|
|
101
97
|
"""
|
|
102
98
|
|
|
103
99
|
Pattern-based, dictionary-like mapper.
|
|
104
|
-
Compiles
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
Compiles an complex set of rules into single regex pattern, and determines which rule matched.
|
|
101
|
+
Inputs are then transformed according to the matching rule.
|
|
102
|
+
Works like a pattern-based dictionary when is_recursive==False.
|
|
103
|
+
Works something like an FSA/transducer when is_recursive=True.
|
|
107
104
|
|
|
108
105
|
"""
|
|
109
106
|
PREFIX_GROUP = '__'
|
|
@@ -112,21 +109,21 @@ class Mapper:
|
|
|
112
109
|
is_recursive: bool = False
|
|
113
110
|
|
|
114
111
|
@cached_property
|
|
115
|
-
def pattern(self):
|
|
112
|
+
def pattern(self) -> str:
|
|
116
113
|
"""
|
|
117
114
|
|
|
118
|
-
|
|
115
|
+
Dynamically generated regex pattern based on the rules provided.
|
|
119
116
|
|
|
120
117
|
"""
|
|
121
118
|
patterns = [
|
|
122
|
-
MASK_NAMED.format(key=f'{self.PREFIX_GROUP}{i}', pattern=item.
|
|
119
|
+
MASK_NAMED.format(key=f'{self.PREFIX_GROUP}{i}', pattern=item.source.pattern)
|
|
123
120
|
for i, item in enumerate(self.items)
|
|
124
121
|
]
|
|
125
122
|
pattern = alt(*patterns)
|
|
126
123
|
return pattern
|
|
127
124
|
|
|
128
125
|
@cached_property
|
|
129
|
-
def rx(self):
|
|
126
|
+
def rx(self) -> re.Pattern:
|
|
130
127
|
"""
|
|
131
128
|
|
|
132
129
|
Regex object.
|
|
@@ -134,24 +131,26 @@ class Mapper:
|
|
|
134
131
|
"""
|
|
135
132
|
return re.compile(self.pattern)
|
|
136
133
|
|
|
137
|
-
def get_default(self, key: Key):
|
|
134
|
+
def get_default(self, key: Key) -> Any:
|
|
138
135
|
if self.is_recursive:
|
|
139
136
|
return key
|
|
140
137
|
else:
|
|
141
138
|
return self.default
|
|
142
139
|
|
|
143
|
-
def get(self, key: Key) -> Key:
|
|
140
|
+
def get(self, key: Key) -> Key | Any:
|
|
144
141
|
"""
|
|
145
142
|
|
|
146
143
|
Use recursive or single lookup pass, depending on whether recursive lookups have been specified.
|
|
147
144
|
|
|
148
145
|
"""
|
|
149
146
|
if self.is_recursive:
|
|
150
|
-
|
|
147
|
+
with logger.span(f'Transforming recursively {key=}...'):
|
|
148
|
+
return self.get_recursive(key)
|
|
151
149
|
else:
|
|
152
|
-
|
|
150
|
+
with logger.span(f'Transforming linearly {key=}...'):
|
|
151
|
+
return self.get_one(key)
|
|
153
152
|
|
|
154
|
-
def get_one(self, key: Key):
|
|
153
|
+
def get_one(self, key: Key) -> Key | Any:
|
|
155
154
|
"""
|
|
156
155
|
|
|
157
156
|
Single lookup pass.
|
|
@@ -163,7 +162,7 @@ class Mapper:
|
|
|
163
162
|
|
|
164
163
|
if not match:
|
|
165
164
|
value = self.get_default(key)
|
|
166
|
-
logger.debug(f'No match for {key=}.')
|
|
165
|
+
logger.debug(f'No match for {key=}. Returning {self.default=}')
|
|
167
166
|
else:
|
|
168
167
|
|
|
169
168
|
match_ids = {name: v for name, v in match.groupdict().items() if v}
|
|
@@ -179,19 +178,21 @@ class Mapper:
|
|
|
179
178
|
rule_id = next(iter(rule_ids))
|
|
180
179
|
rule = self.items[rule_id]
|
|
181
180
|
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
logger.debug(f'Matched using {rule_id=}: {rule.source=}')
|
|
182
|
+
|
|
183
|
+
if isinstance(rule.target, Key):
|
|
184
|
+
value = rule.target.transform(match)
|
|
184
185
|
else:
|
|
185
|
-
value = rule.
|
|
186
|
+
value = rule.target
|
|
186
187
|
|
|
187
|
-
logger.debug(f'
|
|
188
|
+
logger.debug(f'Transformed using {rule_id=}: {key=} → {value=}')
|
|
188
189
|
|
|
189
190
|
return value
|
|
190
191
|
|
|
191
|
-
def get_recursive(self, key: Key) -> Key:
|
|
192
|
+
def get_recursive(self, key: Key) -> Key | Any:
|
|
192
193
|
"""
|
|
193
194
|
|
|
194
|
-
Lookup the provided
|
|
195
|
+
Lookup the provided key by continuously applying transforms until no changes are made
|
|
195
196
|
or a circular loop is detected.
|
|
196
197
|
|
|
197
198
|
"""
|
|
@@ -201,29 +202,28 @@ class Mapper:
|
|
|
201
202
|
def get_history_str():
|
|
202
203
|
return join(history, sep=' → ')
|
|
203
204
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if previous in history:
|
|
207
|
-
history.append(previous)
|
|
208
|
-
msg = f'Loop detected on node "{previous}": {get_history_str()}'
|
|
209
|
-
raise RewriteCircularLoopError(msg)
|
|
210
|
-
|
|
205
|
+
while True:
|
|
206
|
+
if previous in history:
|
|
211
207
|
history.append(previous)
|
|
208
|
+
msg = f'Loop detected on node "{previous}": {get_history_str()}'
|
|
209
|
+
raise RewriteCircularLoopError(msg)
|
|
212
210
|
|
|
213
|
-
|
|
211
|
+
history.append(previous)
|
|
212
|
+
new = previous
|
|
213
|
+
new = self.get_one(new)
|
|
214
|
+
if new == previous:
|
|
215
|
+
break
|
|
216
|
+
previous = new
|
|
214
217
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
break
|
|
219
|
-
|
|
220
|
-
previous = new
|
|
218
|
+
if not isinstance(new, Key):
|
|
219
|
+
history.append(previous)
|
|
220
|
+
break
|
|
221
221
|
|
|
222
222
|
if len(history) == 1:
|
|
223
|
-
history_str = 'No
|
|
223
|
+
history_str = 'No transforms performed.'
|
|
224
224
|
else:
|
|
225
225
|
history_str = get_history_str()
|
|
226
|
-
logger.debug(f'Finished
|
|
226
|
+
logger.debug(f'Finished transforming: {history_str}')
|
|
227
227
|
|
|
228
228
|
return previous
|
|
229
229
|
|
fmtr/tools/version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.3.
|
|
1
|
+
1.3.3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmtr.tools
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.3
|
|
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/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: appdirs; extra == "all"
|
|
134
|
+
Requires-Dist: diskcache; extra == "all"
|
|
135
|
+
Requires-Dist: html2text; extra == "all"
|
|
136
|
+
Requires-Dist: semver; extra == "all"
|
|
137
|
+
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
138
|
+
Requires-Dist: json_repair; extra == "all"
|
|
139
|
+
Requires-Dist: sre_yield; extra == "all"
|
|
140
|
+
Requires-Dist: torchvision; extra == "all"
|
|
141
|
+
Requires-Dist: pymupdf; extra == "all"
|
|
142
|
+
Requires-Dist: Unidecode; extra == "all"
|
|
143
|
+
Requires-Dist: ollama; extra == "all"
|
|
144
|
+
Requires-Dist: peft; extra == "all"
|
|
133
145
|
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
134
|
-
Requires-Dist:
|
|
135
|
-
Requires-Dist:
|
|
146
|
+
Requires-Dist: pandas; extra == "all"
|
|
147
|
+
Requires-Dist: pydantic; extra == "all"
|
|
148
|
+
Requires-Dist: yamlscript; extra == "all"
|
|
149
|
+
Requires-Dist: pyyaml; extra == "all"
|
|
150
|
+
Requires-Dist: pymupdf4llm; extra == "all"
|
|
151
|
+
Requires-Dist: docker; extra == "all"
|
|
152
|
+
Requires-Dist: faker; extra == "all"
|
|
153
|
+
Requires-Dist: distributed; extra == "all"
|
|
136
154
|
Requires-Dist: flet[all]; extra == "all"
|
|
137
|
-
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
138
|
-
Requires-Dist: tinynetrc; extra == "all"
|
|
139
|
-
Requires-Dist: html2text; extra == "all"
|
|
140
|
-
Requires-Dist: deepmerge; extra == "all"
|
|
141
155
|
Requires-Dist: pytest-cov; extra == "all"
|
|
142
|
-
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
143
156
|
Requires-Dist: dnspython[doh]; extra == "all"
|
|
144
|
-
Requires-Dist:
|
|
145
|
-
Requires-Dist: peft; extra == "all"
|
|
146
|
-
Requires-Dist: filetype; extra == "all"
|
|
147
|
-
Requires-Dist: flet-webview; extra == "all"
|
|
157
|
+
Requires-Dist: tinynetrc; extra == "all"
|
|
148
158
|
Requires-Dist: flet-video; extra == "all"
|
|
149
|
-
Requires-Dist:
|
|
150
|
-
Requires-Dist:
|
|
151
|
-
Requires-Dist: semver; extra == "all"
|
|
159
|
+
Requires-Dist: dask[bag]; extra == "all"
|
|
160
|
+
Requires-Dist: bokeh; extra == "all"
|
|
152
161
|
Requires-Dist: httpx; extra == "all"
|
|
153
|
-
Requires-Dist:
|
|
154
|
-
Requires-Dist:
|
|
155
|
-
Requires-Dist: pymupdf4llm; extra == "all"
|
|
156
|
-
Requires-Dist: appdirs; extra == "all"
|
|
157
|
-
Requires-Dist: pyyaml; extra == "all"
|
|
158
|
-
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
162
|
+
Requires-Dist: logfire; extra == "all"
|
|
163
|
+
Requires-Dist: contexttimer; extra == "all"
|
|
159
164
|
Requires-Dist: httpx_retries; extra == "all"
|
|
160
|
-
Requires-Dist:
|
|
165
|
+
Requires-Dist: google-auth; extra == "all"
|
|
166
|
+
Requires-Dist: deepmerge; extra == "all"
|
|
167
|
+
Requires-Dist: torchaudio; extra == "all"
|
|
168
|
+
Requires-Dist: regex; extra == "all"
|
|
161
169
|
Requires-Dist: sentence_transformers; extra == "all"
|
|
162
|
-
Requires-Dist:
|
|
163
|
-
Requires-Dist: distributed; extra == "all"
|
|
170
|
+
Requires-Dist: tokenizers; extra == "all"
|
|
164
171
|
Requires-Dist: huggingface_hub; extra == "all"
|
|
165
|
-
Requires-Dist:
|
|
166
|
-
Requires-Dist:
|
|
167
|
-
Requires-Dist:
|
|
172
|
+
Requires-Dist: tabulate; extra == "all"
|
|
173
|
+
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
174
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
175
|
+
Requires-Dist: flet-webview; extra == "all"
|
|
176
|
+
Requires-Dist: pydantic-settings; extra == "all"
|
|
177
|
+
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
168
178
|
Requires-Dist: openai; extra == "all"
|
|
169
|
-
Requires-Dist: yamlscript; extra == "all"
|
|
170
|
-
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
171
|
-
Requires-Dist: Unidecode; extra == "all"
|
|
172
|
-
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
173
|
-
Requires-Dist: pandas; extra == "all"
|
|
174
|
-
Requires-Dist: bokeh; extra == "all"
|
|
175
|
-
Requires-Dist: diskcache; extra == "all"
|
|
176
|
-
Requires-Dist: json_repair; extra == "all"
|
|
177
|
-
Requires-Dist: logfire; extra == "all"
|
|
178
|
-
Requires-Dist: regex; extra == "all"
|
|
179
|
-
Requires-Dist: fastapi; extra == "all"
|
|
180
|
-
Requires-Dist: contexttimer; extra == "all"
|
|
181
179
|
Requires-Dist: pydevd-pycharm; extra == "all"
|
|
182
|
-
Requires-Dist: faker; extra == "all"
|
|
183
|
-
Requires-Dist: pymupdf; extra == "all"
|
|
184
180
|
Requires-Dist: google-api-python-client; extra == "all"
|
|
185
|
-
Requires-Dist:
|
|
186
|
-
Requires-Dist:
|
|
181
|
+
Requires-Dist: fastapi; extra == "all"
|
|
182
|
+
Requires-Dist: logfire[httpx]; extra == "all"
|
|
183
|
+
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
184
|
+
Requires-Dist: filetype; extra == "all"
|
|
185
|
+
Requires-Dist: openpyxl; extra == "all"
|
|
186
|
+
Requires-Dist: setuptools; 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=qlyMVpkkzsoxV-TRhaevsNvLekFotqUsgf2DA8L0sGk,5689
|
|
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=pbg4E5bSWOYbKrcebHaTPc25w2I4kZ1HI9h4zfIedp8,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
|
|
@@ -53,7 +53,7 @@ fmtr/tools/ai_tools/inference_tools.py,sha256=2UP2gXEyOJUjyyV6zmFIYmIxUsh1rXkRH0
|
|
|
53
53
|
fmtr/tools/dns_tools/__init__.py,sha256=PjD3Og6D5yvDVpKmsUsrnSpz_rjXpl4zBtvMqm8xKWU,237
|
|
54
54
|
fmtr/tools/dns_tools/client.py,sha256=c2vzWBDZSxijwL1KvWUoDGc8wqk_KTAFxCr0P1rNjy8,2367
|
|
55
55
|
fmtr/tools/dns_tools/dm.py,sha256=KWQeeZhsDyrKoXzAD5zEOoHH3aiD4uKRqwnD8fFP1nI,3725
|
|
56
|
-
fmtr/tools/dns_tools/proxy.py,sha256=
|
|
56
|
+
fmtr/tools/dns_tools/proxy.py,sha256=L0utKw8D1JXtAW9IfXcBdNMb-AyPFgW5XGiPnWuk7D8,1878
|
|
57
57
|
fmtr/tools/dns_tools/server.py,sha256=0RLsyVH8C-15PAJgqMNqxbHTPbTWkq_thh8nnS1clAg,892
|
|
58
58
|
fmtr/tools/entrypoints/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
59
|
fmtr/tools/entrypoints/cache_hfh.py,sha256=fQNs4J9twQuZH_Yj98-oOvEX7-LrSUP3kO8nzw2HrHs,60
|
|
@@ -74,9 +74,9 @@ fmtr/tools/tests/test_environment.py,sha256=iHaiMQfECYZPkPKwfuIZV9uHuWe3aE-p_dN_
|
|
|
74
74
|
fmtr/tools/tests/test_json.py,sha256=IeSP4ziPvRcmS8kq7k9tHonC9rN5YYq9GSNT2ul6Msk,287
|
|
75
75
|
fmtr/tools/tests/test_path.py,sha256=AkZQa6_8BQ-VaCyL_J-iKmdf2ZaM-xFYR37Kun3k4_g,2188
|
|
76
76
|
fmtr/tools/tests/test_yaml.py,sha256=jc0TwwKu9eC0LvFGNMERdgBue591xwLxYXFbtsRwXVM,287
|
|
77
|
-
fmtr_tools-1.3.
|
|
78
|
-
fmtr_tools-1.3.
|
|
79
|
-
fmtr_tools-1.3.
|
|
80
|
-
fmtr_tools-1.3.
|
|
81
|
-
fmtr_tools-1.3.
|
|
82
|
-
fmtr_tools-1.3.
|
|
77
|
+
fmtr_tools-1.3.3.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
|
|
78
|
+
fmtr_tools-1.3.3.dist-info/METADATA,sha256=mqGPV0sovCZznll14sPWlH6fr1oa1WdyPit9_WiOu0I,16030
|
|
79
|
+
fmtr_tools-1.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
80
|
+
fmtr_tools-1.3.3.dist-info/entry_points.txt,sha256=fSQrDGNctdQXbUxpMWYVfVQ0mhZMDyaEDG3D3a0zOSc,278
|
|
81
|
+
fmtr_tools-1.3.3.dist-info/top_level.txt,sha256=LXem9xCgNOD72tE2gRKESdiQTL902mfFkwWb6-dlwEE,5
|
|
82
|
+
fmtr_tools-1.3.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|