fmtr.tools 1.3.2__tar.gz → 1.3.4__tar.gz

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.

Files changed (89) hide show
  1. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/PKG-INFO +45 -45
  2. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/dns_tools/proxy.py +5 -6
  3. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/dns_tools/server.py +2 -1
  4. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/pattern_tools.py +54 -44
  5. fmtr_tools-1.3.4/fmtr/tools/version +1 -0
  6. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr.tools.egg-info/PKG-INFO +45 -45
  7. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr.tools.egg-info/requires.txt +44 -44
  8. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/setup.py +1 -1
  9. fmtr_tools-1.3.2/fmtr/tools/version +0 -1
  10. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/LICENSE +0 -0
  11. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/README.md +0 -0
  12. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/__init__.py +0 -0
  13. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/ai_tools/__init__.py +0 -0
  14. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/ai_tools/agentic_tools.py +0 -0
  15. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/ai_tools/inference_tools.py +0 -0
  16. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/api_tools.py +0 -0
  17. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/async_tools.py +0 -0
  18. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/augmentation_tools.py +0 -0
  19. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/caching_tools.py +0 -0
  20. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/constants.py +0 -0
  21. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/data_modelling_tools.py +0 -0
  22. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/dataclass_tools.py +0 -0
  23. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/datatype_tools.py +0 -0
  24. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/debugging_tools.py +0 -0
  25. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/dns_tools/__init__.py +0 -0
  26. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/dns_tools/client.py +0 -0
  27. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/dns_tools/dm.py +0 -0
  28. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/docker_tools.py +0 -0
  29. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/entrypoints/__init__.py +0 -0
  30. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/entrypoints/cache_hfh.py +0 -0
  31. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/entrypoints/ep_test.py +0 -0
  32. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/entrypoints/remote_debug_test.py +0 -0
  33. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/entrypoints/shell_debug.py +0 -0
  34. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/environment_tools.py +0 -0
  35. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/function_tools.py +0 -0
  36. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/google_api_tools.py +0 -0
  37. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/hash_tools.py +0 -0
  38. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/hfh_tools.py +0 -0
  39. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/html_tools.py +0 -0
  40. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/http_tools.py +0 -0
  41. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/import_tools.py +0 -0
  42. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/inspection_tools.py +0 -0
  43. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/interface_tools.py +0 -0
  44. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/iterator_tools.py +0 -0
  45. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/json_fix_tools.py +0 -0
  46. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/json_tools.py +0 -0
  47. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/logging_tools.py +0 -0
  48. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/merging_tools.py +0 -0
  49. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/metric_tools.py +0 -0
  50. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/name_tools.py +0 -0
  51. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/netrc_tools.py +0 -0
  52. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/openai_tools.py +0 -0
  53. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/packaging_tools.py +0 -0
  54. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/parallel_tools.py +0 -0
  55. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/path_tools/__init__.py +0 -0
  56. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/path_tools/app_path_tools.py +0 -0
  57. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/path_tools/path_tools.py +0 -0
  58. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/path_tools/type_path_tools.py +0 -0
  59. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/pdf_tools.py +0 -0
  60. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/platform_tools.py +0 -0
  61. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/process_tools.py +0 -0
  62. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/profiling_tools.py +0 -0
  63. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/random_tools.py +0 -0
  64. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/semantic_tools.py +0 -0
  65. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/settings_tools.py +0 -0
  66. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/setup_tools/__init__.py +0 -0
  67. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/setup_tools/setup_tools.py +0 -0
  68. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/spaces_tools.py +0 -0
  69. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/string_tools.py +0 -0
  70. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tabular_tools.py +0 -0
  71. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/__init__.py +0 -0
  72. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/conftest.py +0 -0
  73. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/helpers.py +0 -0
  74. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/test_datatype.py +0 -0
  75. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/test_environment.py +0 -0
  76. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/test_json.py +0 -0
  77. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/test_path.py +0 -0
  78. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tests/test_yaml.py +0 -0
  79. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tokenization_tools.py +0 -0
  80. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/tools.py +0 -0
  81. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/unicode_tools.py +0 -0
  82. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/version_tools.py +0 -0
  83. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr/tools/yaml_tools.py +0 -0
  84. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr.tools.egg-info/SOURCES.txt +0 -0
  85. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr.tools.egg-info/dependency_links.txt +0 -0
  86. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr.tools.egg-info/entry_points.txt +0 -0
  87. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/fmtr.tools.egg-info/top_level.txt +0 -0
  88. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/pyproject.toml +0 -0
  89. {fmtr_tools-1.3.2 → fmtr_tools-1.3.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.3.2
3
+ Version: 1.3.4
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
@@ -102,7 +102,7 @@ Requires-Dist: pymupdf; extra == "pdf"
102
102
  Requires-Dist: pydantic; extra == "pdf"
103
103
  Requires-Dist: pymupdf4llm; extra == "pdf"
104
104
  Provides-Extra: debug
105
- Requires-Dist: pydevd-pycharm; extra == "debug"
105
+ Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "debug"
106
106
  Provides-Extra: sets
107
107
  Requires-Dist: pydantic-settings; extra == "sets"
108
108
  Requires-Dist: pydantic; extra == "sets"
@@ -130,59 +130,59 @@ 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"
133
+ Requires-Dist: logfire; extra == "all"
134
+ Requires-Dist: distributed; extra == "all"
135
+ Requires-Dist: dnspython[doh]; extra == "all"
136
+ Requires-Dist: google-auth; extra == "all"
137
+ Requires-Dist: tinynetrc; extra == "all"
138
+ Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
139
+ Requires-Dist: Unidecode; extra == "all"
140
+ Requires-Dist: huggingface_hub; extra == "all"
134
141
  Requires-Dist: openpyxl; extra == "all"
135
- Requires-Dist: sentence_transformers; extra == "all"
136
- Requires-Dist: peft; extra == "all"
137
- Requires-Dist: httpx_retries; extra == "all"
138
142
  Requires-Dist: sre_yield; extra == "all"
139
- Requires-Dist: faker; extra == "all"
140
- Requires-Dist: ollama; extra == "all"
141
- Requires-Dist: logfire; extra == "all"
142
- Requires-Dist: bokeh; extra == "all"
143
- Requires-Dist: setuptools; extra == "all"
144
- Requires-Dist: dask[bag]; extra == "all"
145
- Requires-Dist: diskcache; extra == "all"
146
143
  Requires-Dist: torchaudio; extra == "all"
144
+ Requires-Dist: diskcache; extra == "all"
145
+ Requires-Dist: google-auth-oauthlib; extra == "all"
146
+ Requires-Dist: httpx; extra == "all"
147
147
  Requires-Dist: tokenizers; extra == "all"
148
- Requires-Dist: pydantic; extra == "all"
149
- Requires-Dist: pandas; extra == "all"
150
- Requires-Dist: flet-video; extra == "all"
151
- Requires-Dist: Unidecode; extra == "all"
152
- Requires-Dist: pydantic-settings; extra == "all"
153
- Requires-Dist: dnspython[doh]; extra == "all"
154
- Requires-Dist: logfire[httpx]; extra == "all"
148
+ Requires-Dist: html2text; extra == "all"
149
+ Requires-Dist: pytest-cov; extra == "all"
150
+ Requires-Dist: appdirs; extra == "all"
151
+ Requires-Dist: uvicorn[standard]; extra == "all"
152
+ Requires-Dist: json_repair; extra == "all"
153
+ Requires-Dist: httpx_retries; extra == "all"
154
+ Requires-Dist: dask[bag]; extra == "all"
155
+ Requires-Dist: filetype; extra == "all"
156
+ Requires-Dist: google-auth-httplib2; extra == "all"
157
+ Requires-Dist: faker; extra == "all"
158
+ Requires-Dist: transformers[sentencepiece]; extra == "all"
159
+ Requires-Dist: logfire[fastapi]; extra == "all"
155
160
  Requires-Dist: yamlscript; extra == "all"
156
- Requires-Dist: fastapi; extra == "all"
157
161
  Requires-Dist: openai; extra == "all"
162
+ Requires-Dist: pymupdf4llm; extra == "all"
163
+ Requires-Dist: setuptools; extra == "all"
164
+ Requires-Dist: ollama; extra == "all"
165
+ Requires-Dist: tabulate; extra == "all"
158
166
  Requires-Dist: deepmerge; extra == "all"
159
- Requires-Dist: html2text; extra == "all"
160
- Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
161
- Requires-Dist: contexttimer; extra == "all"
167
+ Requires-Dist: bokeh; extra == "all"
168
+ Requires-Dist: flet-webview; extra == "all"
169
+ Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
170
+ Requires-Dist: semver; extra == "all"
171
+ Requires-Dist: logfire[httpx]; extra == "all"
172
+ Requires-Dist: fastapi; extra == "all"
162
173
  Requires-Dist: flet[all]; extra == "all"
163
- Requires-Dist: logfire[fastapi]; extra == "all"
164
- Requires-Dist: regex; extra == "all"
165
- Requires-Dist: docker; extra == "all"
166
- Requires-Dist: filetype; extra == "all"
167
- Requires-Dist: google-auth-oauthlib; extra == "all"
168
- Requires-Dist: tabulate; extra == "all"
169
- Requires-Dist: pytest-cov; extra == "all"
170
- Requires-Dist: pyyaml; extra == "all"
171
- Requires-Dist: transformers[sentencepiece]; extra == "all"
174
+ Requires-Dist: peft; extra == "all"
172
175
  Requires-Dist: pymupdf; extra == "all"
173
- Requires-Dist: pydevd-pycharm; extra == "all"
176
+ Requires-Dist: pandas; extra == "all"
174
177
  Requires-Dist: torchvision; extra == "all"
175
- Requires-Dist: google-auth; extra == "all"
176
- Requires-Dist: flet-webview; extra == "all"
177
- Requires-Dist: huggingface_hub; extra == "all"
178
- Requires-Dist: httpx; extra == "all"
179
- Requires-Dist: semver; extra == "all"
180
- Requires-Dist: json_repair; extra == "all"
181
- Requires-Dist: tinynetrc; extra == "all"
182
- Requires-Dist: google-auth-httplib2; extra == "all"
183
- Requires-Dist: appdirs; extra == "all"
184
- Requires-Dist: pymupdf4llm; extra == "all"
185
- Requires-Dist: distributed; extra == "all"
178
+ Requires-Dist: contexttimer; extra == "all"
179
+ Requires-Dist: docker; extra == "all"
180
+ Requires-Dist: flet-video; extra == "all"
181
+ Requires-Dist: pydantic-settings; extra == "all"
182
+ Requires-Dist: regex; extra == "all"
183
+ Requires-Dist: pyyaml; extra == "all"
184
+ Requires-Dist: pydantic; extra == "all"
185
+ Requires-Dist: sentence_transformers; extra == "all"
186
186
  Requires-Dist: google-api-python-client; extra == "all"
187
187
  Dynamic: author
188
188
  Dynamic: author-email
@@ -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
@@ -2,6 +2,7 @@ import socket
2
2
  from dataclasses import dataclass
3
3
 
4
4
  from fmtr.tools.dns_tools.dm import Exchange
5
+ from fmtr.tools.logging_tools import logger
5
6
 
6
7
 
7
8
  @dataclass
@@ -30,7 +31,7 @@ class Plain:
30
31
  """
31
32
  sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
32
33
  sock.bind((self.host, self.port))
33
- print(f"Listening on {self.host}:{self.port}")
34
+ logger.info(f'Listening on {self.host}:{self.port}')
34
35
  while True:
35
36
  data, (ip, port) = sock.recvfrom(512)
36
37
  exchange = Exchange.from_wire(data, ip=ip, port=port)
@@ -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 = '__'
@@ -111,22 +108,27 @@ class Mapper:
111
108
  default: Any = None
112
109
  is_recursive: bool = False
113
110
 
111
+ def __post_init__(self):
112
+ with logger.span(f'Compiling expression {len(self.items)=}'):
113
+ rx = self.rx
114
+ logger.debug(f'Compiled successfully {rx.groups=}')
115
+
114
116
  @cached_property
115
- def pattern(self):
117
+ def pattern(self) -> str:
116
118
  """
117
119
 
118
- Provides a dynamically generated regex pattern based on the rules provided.
120
+ Dynamically generated regex pattern based on the rules provided.
119
121
 
120
122
  """
121
123
  patterns = [
122
- MASK_NAMED.format(key=f'{self.PREFIX_GROUP}{i}', pattern=item.key.pattern)
124
+ MASK_NAMED.format(key=f'{self.PREFIX_GROUP}{i}', pattern=item.source.pattern)
123
125
  for i, item in enumerate(self.items)
124
126
  ]
125
127
  pattern = alt(*patterns)
126
128
  return pattern
127
129
 
128
130
  @cached_property
129
- def rx(self):
131
+ def rx(self) -> re.Pattern:
130
132
  """
131
133
 
132
134
  Regex object.
@@ -134,24 +136,31 @@ class Mapper:
134
136
  """
135
137
  return re.compile(self.pattern)
136
138
 
137
- def get_default(self, key: Key):
139
+ def get_default(self, key: Key) -> Any:
140
+ """
141
+
142
+ Define what to return in case of no match
143
+
144
+ """
138
145
  if self.is_recursive:
139
146
  return key
140
147
  else:
141
148
  return self.default
142
149
 
143
- def get(self, key: Key) -> Key:
150
+ def get(self, key: Key) -> Key | Any:
144
151
  """
145
152
 
146
153
  Use recursive or single lookup pass, depending on whether recursive lookups have been specified.
147
154
 
148
155
  """
149
156
  if self.is_recursive:
150
- return self.get_recursive(key)
157
+ with logger.span(f'Transforming recursively {key=}...'):
158
+ return self.get_recursive(key)
151
159
  else:
152
- return self.get_one(key)
160
+ with logger.span(f'Transforming linearly {key=}...'):
161
+ return self.get_one(key)
153
162
 
154
- def get_one(self, key: Key):
163
+ def get_one(self, key: Key) -> Key | Any:
155
164
  """
156
165
 
157
166
  Single lookup pass.
@@ -163,7 +172,7 @@ class Mapper:
163
172
 
164
173
  if not match:
165
174
  value = self.get_default(key)
166
- logger.debug(f'No match for {key=}.')
175
+ logger.debug(f'No match for {key=}. Returning {self.get_default(key)=}')
167
176
  else:
168
177
 
169
178
  match_ids = {name: v for name, v in match.groupdict().items() if v}
@@ -179,19 +188,21 @@ class Mapper:
179
188
  rule_id = next(iter(rule_ids))
180
189
  rule = self.items[rule_id]
181
190
 
182
- if isinstance(rule.value, Key):
183
- value = rule.value.transform(match)
191
+ logger.debug(f'Matched using {rule_id=}: {rule.source=}')
192
+
193
+ if isinstance(rule.target, Key):
194
+ value = rule.target.transform(match)
184
195
  else:
185
- value = rule.value
196
+ value = rule.target
186
197
 
187
- logger.debug(f'Matched using {rule_id=}: {key=} → {value=}')
198
+ logger.debug(f'Transformed using {rule_id=}: {key=} → {value=}')
188
199
 
189
200
  return value
190
201
 
191
- def get_recursive(self, key: Key) -> Key:
202
+ def get_recursive(self, key: Key) -> Key | Any:
192
203
  """
193
204
 
194
- Lookup the provided text by continuously applying lookup rules until no changes are made
205
+ Lookup the provided key by continuously applying transforms until no changes are made
195
206
  or a circular loop is detected.
196
207
 
197
208
  """
@@ -201,29 +212,28 @@ class Mapper:
201
212
  def get_history_str():
202
213
  return join(history, sep=' → ')
203
214
 
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
-
215
+ while True:
216
+ if previous in history:
211
217
  history.append(previous)
218
+ msg = f'Loop detected on node "{previous}": {get_history_str()}'
219
+ raise RewriteCircularLoopError(msg)
212
220
 
213
- new = previous
214
-
215
- new = self.get_one(new)
221
+ history.append(previous)
222
+ new = previous
223
+ new = self.get_one(new)
224
+ if new == previous:
225
+ break
226
+ previous = new
216
227
 
217
- if new == previous:
218
- break
219
-
220
- previous = new
228
+ if not isinstance(new, Key):
229
+ history.append(previous)
230
+ break
221
231
 
222
232
  if len(history) == 1:
223
- history_str = 'No matching performed.'
233
+ history_str = 'No transforms performed.'
224
234
  else:
225
235
  history_str = get_history_str()
226
- logger.debug(f'Finished matching: {history_str}')
236
+ logger.debug(f'Finished transforming: {history_str}')
227
237
 
228
238
  return previous
229
239
 
@@ -0,0 +1 @@
1
+ 1.3.4
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.3.2
3
+ Version: 1.3.4
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
@@ -102,7 +102,7 @@ Requires-Dist: pymupdf; extra == "pdf"
102
102
  Requires-Dist: pydantic; extra == "pdf"
103
103
  Requires-Dist: pymupdf4llm; extra == "pdf"
104
104
  Provides-Extra: debug
105
- Requires-Dist: pydevd-pycharm; extra == "debug"
105
+ Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "debug"
106
106
  Provides-Extra: sets
107
107
  Requires-Dist: pydantic-settings; extra == "sets"
108
108
  Requires-Dist: pydantic; extra == "sets"
@@ -130,59 +130,59 @@ 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"
133
+ Requires-Dist: logfire; extra == "all"
134
+ Requires-Dist: distributed; extra == "all"
135
+ Requires-Dist: dnspython[doh]; extra == "all"
136
+ Requires-Dist: google-auth; extra == "all"
137
+ Requires-Dist: tinynetrc; extra == "all"
138
+ Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
139
+ Requires-Dist: Unidecode; extra == "all"
140
+ Requires-Dist: huggingface_hub; extra == "all"
134
141
  Requires-Dist: openpyxl; extra == "all"
135
- Requires-Dist: sentence_transformers; extra == "all"
136
- Requires-Dist: peft; extra == "all"
137
- Requires-Dist: httpx_retries; extra == "all"
138
142
  Requires-Dist: sre_yield; extra == "all"
139
- Requires-Dist: faker; extra == "all"
140
- Requires-Dist: ollama; extra == "all"
141
- Requires-Dist: logfire; extra == "all"
142
- Requires-Dist: bokeh; extra == "all"
143
- Requires-Dist: setuptools; extra == "all"
144
- Requires-Dist: dask[bag]; extra == "all"
145
- Requires-Dist: diskcache; extra == "all"
146
143
  Requires-Dist: torchaudio; extra == "all"
144
+ Requires-Dist: diskcache; extra == "all"
145
+ Requires-Dist: google-auth-oauthlib; extra == "all"
146
+ Requires-Dist: httpx; extra == "all"
147
147
  Requires-Dist: tokenizers; extra == "all"
148
- Requires-Dist: pydantic; extra == "all"
149
- Requires-Dist: pandas; extra == "all"
150
- Requires-Dist: flet-video; extra == "all"
151
- Requires-Dist: Unidecode; extra == "all"
152
- Requires-Dist: pydantic-settings; extra == "all"
153
- Requires-Dist: dnspython[doh]; extra == "all"
154
- Requires-Dist: logfire[httpx]; extra == "all"
148
+ Requires-Dist: html2text; extra == "all"
149
+ Requires-Dist: pytest-cov; extra == "all"
150
+ Requires-Dist: appdirs; extra == "all"
151
+ Requires-Dist: uvicorn[standard]; extra == "all"
152
+ Requires-Dist: json_repair; extra == "all"
153
+ Requires-Dist: httpx_retries; extra == "all"
154
+ Requires-Dist: dask[bag]; extra == "all"
155
+ Requires-Dist: filetype; extra == "all"
156
+ Requires-Dist: google-auth-httplib2; extra == "all"
157
+ Requires-Dist: faker; extra == "all"
158
+ Requires-Dist: transformers[sentencepiece]; extra == "all"
159
+ Requires-Dist: logfire[fastapi]; extra == "all"
155
160
  Requires-Dist: yamlscript; extra == "all"
156
- Requires-Dist: fastapi; extra == "all"
157
161
  Requires-Dist: openai; extra == "all"
162
+ Requires-Dist: pymupdf4llm; extra == "all"
163
+ Requires-Dist: setuptools; extra == "all"
164
+ Requires-Dist: ollama; extra == "all"
165
+ Requires-Dist: tabulate; extra == "all"
158
166
  Requires-Dist: deepmerge; extra == "all"
159
- Requires-Dist: html2text; extra == "all"
160
- Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
161
- Requires-Dist: contexttimer; extra == "all"
167
+ Requires-Dist: bokeh; extra == "all"
168
+ Requires-Dist: flet-webview; extra == "all"
169
+ Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
170
+ Requires-Dist: semver; extra == "all"
171
+ Requires-Dist: logfire[httpx]; extra == "all"
172
+ Requires-Dist: fastapi; extra == "all"
162
173
  Requires-Dist: flet[all]; extra == "all"
163
- Requires-Dist: logfire[fastapi]; extra == "all"
164
- Requires-Dist: regex; extra == "all"
165
- Requires-Dist: docker; extra == "all"
166
- Requires-Dist: filetype; extra == "all"
167
- Requires-Dist: google-auth-oauthlib; extra == "all"
168
- Requires-Dist: tabulate; extra == "all"
169
- Requires-Dist: pytest-cov; extra == "all"
170
- Requires-Dist: pyyaml; extra == "all"
171
- Requires-Dist: transformers[sentencepiece]; extra == "all"
174
+ Requires-Dist: peft; extra == "all"
172
175
  Requires-Dist: pymupdf; extra == "all"
173
- Requires-Dist: pydevd-pycharm; extra == "all"
176
+ Requires-Dist: pandas; extra == "all"
174
177
  Requires-Dist: torchvision; extra == "all"
175
- Requires-Dist: google-auth; extra == "all"
176
- Requires-Dist: flet-webview; extra == "all"
177
- Requires-Dist: huggingface_hub; extra == "all"
178
- Requires-Dist: httpx; extra == "all"
179
- Requires-Dist: semver; extra == "all"
180
- Requires-Dist: json_repair; extra == "all"
181
- Requires-Dist: tinynetrc; extra == "all"
182
- Requires-Dist: google-auth-httplib2; extra == "all"
183
- Requires-Dist: appdirs; extra == "all"
184
- Requires-Dist: pymupdf4llm; extra == "all"
185
- Requires-Dist: distributed; extra == "all"
178
+ Requires-Dist: contexttimer; extra == "all"
179
+ Requires-Dist: docker; extra == "all"
180
+ Requires-Dist: flet-video; extra == "all"
181
+ Requires-Dist: pydantic-settings; extra == "all"
182
+ Requires-Dist: regex; extra == "all"
183
+ Requires-Dist: pyyaml; extra == "all"
184
+ Requires-Dist: pydantic; extra == "all"
185
+ Requires-Dist: sentence_transformers; extra == "all"
186
186
  Requires-Dist: google-api-python-client; extra == "all"
187
187
  Dynamic: author
188
188
  Dynamic: author-email
@@ -15,59 +15,59 @@ pydantic-ai[logfire,openai]
15
15
  ollama
16
16
 
17
17
  [all]
18
- uvicorn[standard]
18
+ logfire
19
+ distributed
20
+ dnspython[doh]
21
+ google-auth
22
+ tinynetrc
23
+ pydantic-ai[logfire,openai]
24
+ Unidecode
25
+ huggingface_hub
19
26
  openpyxl
20
- sentence_transformers
21
- peft
22
- httpx_retries
23
27
  sre_yield
24
- faker
25
- ollama
26
- logfire
27
- bokeh
28
- setuptools
29
- dask[bag]
30
- diskcache
31
28
  torchaudio
29
+ diskcache
30
+ google-auth-oauthlib
31
+ httpx
32
32
  tokenizers
33
- pydantic
34
- pandas
35
- flet-video
36
- Unidecode
37
- pydantic-settings
38
- dnspython[doh]
39
- logfire[httpx]
33
+ html2text
34
+ pytest-cov
35
+ appdirs
36
+ uvicorn[standard]
37
+ json_repair
38
+ httpx_retries
39
+ dask[bag]
40
+ filetype
41
+ google-auth-httplib2
42
+ faker
43
+ transformers[sentencepiece]
44
+ logfire[fastapi]
40
45
  yamlscript
41
- fastapi
42
46
  openai
47
+ pymupdf4llm
48
+ setuptools
49
+ ollama
50
+ tabulate
43
51
  deepmerge
44
- html2text
45
- pydantic-ai[logfire,openai]
46
- contexttimer
52
+ bokeh
53
+ flet-webview
54
+ pydevd-pycharm~=251.25410.159
55
+ semver
56
+ logfire[httpx]
57
+ fastapi
47
58
  flet[all]
48
- logfire[fastapi]
49
- regex
50
- docker
51
- filetype
52
- google-auth-oauthlib
53
- tabulate
54
- pytest-cov
55
- pyyaml
56
- transformers[sentencepiece]
59
+ peft
57
60
  pymupdf
58
- pydevd-pycharm
61
+ pandas
59
62
  torchvision
60
- google-auth
61
- flet-webview
62
- huggingface_hub
63
- httpx
64
- semver
65
- json_repair
66
- tinynetrc
67
- google-auth-httplib2
68
- appdirs
69
- pymupdf4llm
70
- distributed
63
+ contexttimer
64
+ docker
65
+ flet-video
66
+ pydantic-settings
67
+ regex
68
+ pyyaml
69
+ pydantic
70
+ sentence_transformers
71
71
  google-api-python-client
72
72
 
73
73
  [api]
@@ -86,7 +86,7 @@ sre_yield
86
86
  diskcache
87
87
 
88
88
  [debug]
89
- pydevd-pycharm
89
+ pydevd-pycharm~=251.25410.159
90
90
 
91
91
  [dm]
92
92
  pydantic
@@ -31,7 +31,7 @@ DEPENDENCIES = {
31
31
  'google.api': ['google-auth', 'google-auth-oauthlib', 'google-auth-httplib2', 'google-api-python-client'],
32
32
  'caching': ['diskcache'],
33
33
  'pdf': ['pymupdf', 'dm', 'pymupdf4llm'],
34
- 'debug': ['pydevd-pycharm'],
34
+ 'debug': ['pydevd-pycharm~=251.25410.159'],
35
35
  'sets': ['pydantic-settings', 'dm', 'yaml'],
36
36
  'path.app': ['appdirs'],
37
37
  'path.type': ['filetype'],
@@ -1 +0,0 @@
1
- 1.3.2
File without changes
File without changes
File without changes
File without changes