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.

@@ -41,7 +41,7 @@ class Proxy(server.Plain):
41
41
 
42
42
  request = exchange.request
43
43
 
44
- with logger.span(f'Handling request ID {request.message.id} for {request.name_text} from {exchange.client}...'):
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 for {request.name_text}...'):
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
- return
65
+
66
+ logger.info(f'Resolution complete {request.message.id=} {exchange.response.answer=}')
67
+ return
@@ -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
- key: Key
97
- value: Key
92
+ source: Key
93
+ target: Key
98
94
 
99
95
  @dataclass
100
- class Mapper:
96
+ class Transformer:
101
97
  """
102
98
 
103
99
  Pattern-based, dictionary-like mapper.
104
- Compiles a single regex pattern from a list of rules, and determines which rule matched.
105
- It supports initialization from structured rule data, execution of a single lookup pass, and
106
- recursive lookups until a stable state is reached.
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
- Provides a dynamically generated regex pattern based on the rules provided.
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.key.pattern)
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
- return self.get_recursive(key)
147
+ with logger.span(f'Transforming recursively {key=}...'):
148
+ return self.get_recursive(key)
151
149
  else:
152
- return self.get_one(key)
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
- if isinstance(rule.value, Key):
183
- value = rule.value.transform(match)
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.value
186
+ value = rule.target
186
187
 
187
- logger.debug(f'Matched using {rule_id=}: {key=} → {value=}')
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 text by continuously applying lookup rules until no changes are made
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
- with logger.span(f'Matching {key=}...'):
205
- while True:
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
- new = previous
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
- new = self.get_one(new)
216
-
217
- if new == previous:
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 matching performed.'
223
+ history_str = 'No transforms performed.'
224
224
  else:
225
225
  history_str = get_history_str()
226
- logger.debug(f'Finished matching: {history_str}')
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.2
1
+ 1.3.3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.3.2
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: dask[bag]; extra == "all"
135
- Requires-Dist: tabulate; extra == "all"
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: setuptools; extra == "all"
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: tokenizers; extra == "all"
150
- Requires-Dist: sre_yield; extra == "all"
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: google-auth; extra == "all"
154
- Requires-Dist: openpyxl; extra == "all"
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: pydantic; extra == "all"
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: ollama; extra == "all"
163
- Requires-Dist: distributed; extra == "all"
170
+ Requires-Dist: tokenizers; extra == "all"
164
171
  Requires-Dist: huggingface_hub; extra == "all"
165
- Requires-Dist: logfire[httpx]; extra == "all"
166
- Requires-Dist: torchaudio; extra == "all"
167
- Requires-Dist: docker; extra == "all"
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: torchvision; extra == "all"
186
- Requires-Dist: pydantic-settings; extra == "all"
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=GzdhKt-nIHuKCGI9y3aGUaD5k9thbqbA9UXJoPPIcIY,5328
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=exPSrztkeQgMZ8VTDFGwb8f-z8T_NbtvtmOtm7IiqvA,5
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=0TULVnD3FlZNAsNINy8bcbimTNvmkwvzXeMnOkdUqvw,1879
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.2.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
78
- fmtr_tools-1.3.2.dist-info/METADATA,sha256=KlWOZL7_0eJCCM3bZtnujinv89YPLmtU4LcDg7JZx9I,16030
79
- fmtr_tools-1.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
80
- fmtr_tools-1.3.2.dist-info/entry_points.txt,sha256=fSQrDGNctdQXbUxpMWYVfVQ0mhZMDyaEDG3D3a0zOSc,278
81
- fmtr_tools-1.3.2.dist-info/top_level.txt,sha256=LXem9xCgNOD72tE2gRKESdiQTL902mfFkwWb6-dlwEE,5
82
- fmtr_tools-1.3.2.dist-info/RECORD,,
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,,