fmtr.tools 1.3.62__tar.gz → 1.3.64__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.
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/PKG-INFO +65 -51
- fmtr_tools-1.3.64/fmtr/tools/data_modelling_tools.py +218 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/datatype_tools.py +14 -1
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/iterator_tools.py +10 -1
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/string_tools.py +21 -5
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tools.py +27 -2
- fmtr_tools-1.3.64/fmtr/tools/version +1 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr.tools.egg-info/PKG-INFO +65 -51
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr.tools.egg-info/requires.txt +63 -50
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/setup.py +4 -1
- fmtr_tools-1.3.62/fmtr/tools/data_modelling_tools.py +0 -93
- fmtr_tools-1.3.62/fmtr/tools/version +0 -1
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/LICENSE +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/README.md +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/ai_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/ai_tools/agentic_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/ai_tools/inference_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/api_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/async_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/augmentation_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/caching_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/constants.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/context_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/database_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/database_tools/document.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/dataclass_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/datetime_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/debugging_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/dns_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/dns_tools/client.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/dns_tools/dm.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/dns_tools/proxy.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/dns_tools/server.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/docker_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/entrypoints/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/entrypoints/cache_hfh.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/entrypoints/ep_test.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/entrypoints/install_yamlscript.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/entrypoints/remote_debug_test.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/entrypoints/shell_debug.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/environment_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/function_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/google_api_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/hash_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/hfh_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/html_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/http_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/import_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/inherit_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/inspection_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/interface_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/interface_tools/context.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/interface_tools/controls.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/interface_tools/interface_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/json_fix_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/json_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/logging_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/merging_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/metric_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/name_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/netrc_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/openai_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/packaging_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/parallel_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/path_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/path_tools/app_path_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/path_tools/path_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/path_tools/type_path_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/pattern_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/pdf_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/platform_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/process_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/profiling_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/random_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/semantic_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/settings_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/setup_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/setup_tools/setup_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/spaces_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tabular_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/conftest.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/helpers.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/test_datatype.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/test_environment.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/test_json.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/test_path.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tests/test_yaml.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/tokenization_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/unicode_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/version_tools/__init__.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/version_tools/version_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/webhook_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr/tools/yaml_tools.py +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr.tools.egg-info/SOURCES.txt +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr.tools.egg-info/dependency_links.txt +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr.tools.egg-info/entry_points.txt +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/fmtr.tools.egg-info/top_level.txt +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/pyproject.toml +0 -0
- {fmtr_tools-1.3.62 → fmtr_tools-1.3.64}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmtr.tools
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.64
|
|
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
|
|
@@ -8,6 +8,20 @@ Author-email: innovative.fowler@mask.pro.fmtr.dev
|
|
|
8
8
|
License: Copyright © 2025 Frontmatter. All rights reserved.
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: logfire; extra == "dev"
|
|
13
|
+
Requires-Dist: semver; extra == "dev"
|
|
14
|
+
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "dev"
|
|
15
|
+
Requires-Dist: pydantic-settings; extra == "dev"
|
|
16
|
+
Requires-Dist: pydantic; extra == "dev"
|
|
17
|
+
Requires-Dist: pydantic-extra-types; extra == "dev"
|
|
18
|
+
Requires-Dist: pycountry; extra == "dev"
|
|
19
|
+
Requires-Dist: yamlscript; extra == "dev"
|
|
20
|
+
Requires-Dist: pyyaml; extra == "dev"
|
|
21
|
+
Requires-Dist: yamlscript; extra == "dev"
|
|
22
|
+
Requires-Dist: pyyaml; extra == "dev"
|
|
23
|
+
Requires-Dist: beanie[odm]; extra == "dev"
|
|
24
|
+
Requires-Dist: motor; extra == "dev"
|
|
11
25
|
Provides-Extra: test
|
|
12
26
|
Requires-Dist: pytest-cov; extra == "test"
|
|
13
27
|
Provides-Extra: yaml
|
|
@@ -154,68 +168,68 @@ Provides-Extra: db-document
|
|
|
154
168
|
Requires-Dist: beanie[odm]; extra == "db-document"
|
|
155
169
|
Requires-Dist: motor; extra == "db-document"
|
|
156
170
|
Provides-Extra: all
|
|
157
|
-
Requires-Dist:
|
|
158
|
-
Requires-Dist:
|
|
159
|
-
Requires-Dist:
|
|
160
|
-
Requires-Dist: cachetools; extra == "all"
|
|
161
|
-
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
162
|
-
Requires-Dist: pydantic; extra == "all"
|
|
163
|
-
Requires-Dist: openai; extra == "all"
|
|
164
|
-
Requires-Dist: ollama; extra == "all"
|
|
165
|
-
Requires-Dist: json_repair; extra == "all"
|
|
166
|
-
Requires-Dist: sentence_transformers; extra == "all"
|
|
167
|
-
Requires-Dist: tabulate; extra == "all"
|
|
168
|
-
Requires-Dist: sre_yield; extra == "all"
|
|
171
|
+
Requires-Dist: deepmerge; extra == "all"
|
|
172
|
+
Requires-Dist: faker; extra == "all"
|
|
173
|
+
Requires-Dist: pandas; extra == "all"
|
|
169
174
|
Requires-Dist: google-api-python-client; extra == "all"
|
|
175
|
+
Requires-Dist: html2text; extra == "all"
|
|
170
176
|
Requires-Dist: pyyaml; extra == "all"
|
|
171
|
-
Requires-Dist: regex; extra == "all"
|
|
172
|
-
Requires-Dist: httpx_retries; extra == "all"
|
|
173
|
-
Requires-Dist: flet-video; extra == "all"
|
|
174
|
-
Requires-Dist: pandas; extra == "all"
|
|
175
|
-
Requires-Dist: openpyxl; extra == "all"
|
|
176
|
-
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
177
|
-
Requires-Dist: semver; extra == "all"
|
|
178
|
-
Requires-Dist: yamlscript; extra == "all"
|
|
179
177
|
Requires-Dist: dask[bag]; extra == "all"
|
|
180
|
-
Requires-Dist:
|
|
181
|
-
Requires-Dist:
|
|
182
|
-
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
183
|
-
Requires-Dist: tinynetrc; extra == "all"
|
|
184
|
-
Requires-Dist: flet[all]; extra == "all"
|
|
185
|
-
Requires-Dist: appdirs; extra == "all"
|
|
186
|
-
Requires-Dist: deepmerge; extra == "all"
|
|
187
|
-
Requires-Dist: httpx; extra == "all"
|
|
188
|
-
Requires-Dist: huggingface_hub; extra == "all"
|
|
178
|
+
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
179
|
+
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
|
|
189
180
|
Requires-Dist: pymupdf; extra == "all"
|
|
190
|
-
Requires-Dist: pytest-cov; extra == "all"
|
|
191
181
|
Requires-Dist: beanie[odm]; extra == "all"
|
|
192
|
-
Requires-Dist:
|
|
193
|
-
Requires-Dist:
|
|
194
|
-
Requires-Dist:
|
|
195
|
-
Requires-Dist: pycountry; extra == "all"
|
|
196
|
-
Requires-Dist: dnspython[doh]; extra == "all"
|
|
197
|
-
Requires-Dist: faker; extra == "all"
|
|
198
|
-
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
199
|
-
Requires-Dist: odfpy; extra == "all"
|
|
200
|
-
Requires-Dist: pydantic-settings; extra == "all"
|
|
182
|
+
Requires-Dist: fastapi; extra == "all"
|
|
183
|
+
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
184
|
+
Requires-Dist: appdirs; extra == "all"
|
|
201
185
|
Requires-Dist: pydantic-extra-types; extra == "all"
|
|
186
|
+
Requires-Dist: distributed; extra == "all"
|
|
202
187
|
Requires-Dist: torchaudio; extra == "all"
|
|
203
|
-
Requires-Dist:
|
|
204
|
-
Requires-Dist:
|
|
205
|
-
Requires-Dist:
|
|
188
|
+
Requires-Dist: setuptools; extra == "all"
|
|
189
|
+
Requires-Dist: deepdiff; extra == "all"
|
|
190
|
+
Requires-Dist: odfpy; extra == "all"
|
|
206
191
|
Requires-Dist: python-on-whales; extra == "all"
|
|
207
|
-
Requires-Dist:
|
|
208
|
-
Requires-Dist: logfire; extra == "all"
|
|
209
|
-
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
|
|
210
|
-
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
192
|
+
Requires-Dist: Unidecode; extra == "all"
|
|
211
193
|
Requires-Dist: contexttimer; extra == "all"
|
|
212
|
-
Requires-Dist:
|
|
194
|
+
Requires-Dist: tokenizers; extra == "all"
|
|
195
|
+
Requires-Dist: pycountry; extra == "all"
|
|
196
|
+
Requires-Dist: openai; extra == "all"
|
|
213
197
|
Requires-Dist: flet-webview; extra == "all"
|
|
198
|
+
Requires-Dist: logfire[httpx]; extra == "all"
|
|
199
|
+
Requires-Dist: regex; extra == "all"
|
|
200
|
+
Requires-Dist: peft; extra == "all"
|
|
201
|
+
Requires-Dist: logfire; extra == "all"
|
|
202
|
+
Requires-Dist: pytest-cov; extra == "all"
|
|
214
203
|
Requires-Dist: playwright; extra == "all"
|
|
215
|
-
Requires-Dist:
|
|
216
|
-
Requires-Dist:
|
|
204
|
+
Requires-Dist: httpx; extra == "all"
|
|
205
|
+
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
206
|
+
Requires-Dist: pydantic-settings; extra == "all"
|
|
207
|
+
Requires-Dist: sentence_transformers; extra == "all"
|
|
208
|
+
Requires-Dist: filetype; extra == "all"
|
|
209
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
210
|
+
Requires-Dist: openpyxl; extra == "all"
|
|
211
|
+
Requires-Dist: ollama; extra == "all"
|
|
212
|
+
Requires-Dist: httpx_retries; extra == "all"
|
|
213
|
+
Requires-Dist: tinynetrc; extra == "all"
|
|
214
|
+
Requires-Dist: flet-video; extra == "all"
|
|
215
|
+
Requires-Dist: pymupdf4llm; extra == "all"
|
|
216
|
+
Requires-Dist: bokeh; extra == "all"
|
|
217
217
|
Requires-Dist: diskcache; extra == "all"
|
|
218
|
-
Requires-Dist:
|
|
218
|
+
Requires-Dist: semver; extra == "all"
|
|
219
|
+
Requires-Dist: huggingface_hub; extra == "all"
|
|
220
|
+
Requires-Dist: flet[all]; extra == "all"
|
|
221
|
+
Requires-Dist: google-auth; extra == "all"
|
|
222
|
+
Requires-Dist: tabulate; extra == "all"
|
|
223
|
+
Requires-Dist: torchvision; extra == "all"
|
|
224
|
+
Requires-Dist: yamlscript; extra == "all"
|
|
225
|
+
Requires-Dist: sre_yield; extra == "all"
|
|
226
|
+
Requires-Dist: json_repair; extra == "all"
|
|
227
|
+
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
228
|
+
Requires-Dist: pydantic; extra == "all"
|
|
229
|
+
Requires-Dist: cachetools; extra == "all"
|
|
230
|
+
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
231
|
+
Requires-Dist: dnspython[doh]; extra == "all"
|
|
232
|
+
Requires-Dist: motor; extra == "all"
|
|
219
233
|
Dynamic: author
|
|
220
234
|
Dynamic: author-email
|
|
221
235
|
Dynamic: description
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
from functools import cached_property
|
|
2
|
+
from typing import ClassVar, List, Any, Dict
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
from pydantic import RootModel, ConfigDict
|
|
6
|
+
from pydantic.fields import FieldInfo
|
|
7
|
+
from pydantic_core import PydanticUndefined, PydanticUndefinedType
|
|
8
|
+
|
|
9
|
+
from fmtr.tools.datatype_tools import is_optional
|
|
10
|
+
from fmtr.tools.iterator_tools import get_class_lookup
|
|
11
|
+
from fmtr.tools.tools import Auto, Required
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Field(FieldInfo):
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
Allow DRYer field definitions, set annotation and defaults at the same time, easier field inheritance, etc.
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
ANNOTATION = None
|
|
21
|
+
DEFAULT = Auto
|
|
22
|
+
FILLS = None
|
|
23
|
+
DESCRIPTION = None
|
|
24
|
+
TITLE = Auto
|
|
25
|
+
KWARGS = None
|
|
26
|
+
|
|
27
|
+
def __init__(self):
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
Infer default from type annotation, if enabled, use class/argument fills to create titles/descriptions, etc.
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
title = self.get_title_auto()
|
|
34
|
+
description = self.get_desc()
|
|
35
|
+
default = self.get_default_auto()
|
|
36
|
+
kwargs = self.KWARGS or {}
|
|
37
|
+
|
|
38
|
+
if default is Required:
|
|
39
|
+
default = PydanticUndefined
|
|
40
|
+
|
|
41
|
+
super().__init__(default=default, title=title, description=description, **kwargs)
|
|
42
|
+
|
|
43
|
+
@cached_property
|
|
44
|
+
def fills(self) -> Dict[str, str]:
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
Get fills with filled title merged in
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
return (self.FILLS or {}) | dict(title=self.get_title_auto())
|
|
51
|
+
|
|
52
|
+
def get_default_auto(self) -> type[Any] | None | PydanticUndefinedType:
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
Infer default, if not specified.
|
|
56
|
+
|
|
57
|
+
"""
|
|
58
|
+
if self.DEFAULT is not Auto:
|
|
59
|
+
return self.DEFAULT
|
|
60
|
+
|
|
61
|
+
if is_optional(self.ANNOTATION):
|
|
62
|
+
return None
|
|
63
|
+
else:
|
|
64
|
+
return Required
|
|
65
|
+
|
|
66
|
+
def get_title_auto(self) -> str | None:
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
Get title from classname/mask
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
mask = self.__class__.__name__ if self.TITLE is Auto else self.TITLE
|
|
74
|
+
fills = (self.FILLS or {})
|
|
75
|
+
|
|
76
|
+
if mask:
|
|
77
|
+
return mask.format(**fills)
|
|
78
|
+
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
def get_desc(self) -> str | None:
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
Get description from classname/mask
|
|
85
|
+
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
if self.DESCRIPTION:
|
|
89
|
+
return self.DESCRIPTION.format(**self.fills)
|
|
90
|
+
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def to_df(*objs, name_value='value'):
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
DataFrame representation of Data Models as rows.
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
from fmtr.tools import tabular
|
|
101
|
+
|
|
102
|
+
rows = []
|
|
103
|
+
for obj in objs:
|
|
104
|
+
if isinstance(obj, BaseModel):
|
|
105
|
+
row = obj.model_dump()
|
|
106
|
+
else:
|
|
107
|
+
row = {name_value: obj}
|
|
108
|
+
rows.append(row)
|
|
109
|
+
|
|
110
|
+
df = tabular.DataFrame(rows)
|
|
111
|
+
if 'id' in df.columns:
|
|
112
|
+
df.set_index('id', inplace=True, drop=True)
|
|
113
|
+
return df
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class MixinArbitraryTypes:
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
Convenience for when non-serializable types are needed
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
123
|
+
|
|
124
|
+
class MixinFromJson:
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def from_json(cls, json_str):
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
Error-tolerant deserialization
|
|
131
|
+
|
|
132
|
+
"""
|
|
133
|
+
from fmtr.tools import json_fix
|
|
134
|
+
data = json_fix.from_json(json_str, default={})
|
|
135
|
+
|
|
136
|
+
if type(data) is dict:
|
|
137
|
+
self = cls(**data)
|
|
138
|
+
else:
|
|
139
|
+
self = cls(data)
|
|
140
|
+
|
|
141
|
+
return self
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class Base(BaseModel, MixinFromJson):
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
Base model allowing model definition via a list of custom Field objects.
|
|
149
|
+
|
|
150
|
+
"""
|
|
151
|
+
FIELDS: ClassVar[List[Field] | Dict[str, Field]] = []
|
|
152
|
+
|
|
153
|
+
def __init_subclass__(cls, **kwargs):
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
Fetch aggregated fields metadata from the hierarchy and set annotations and FieldInfo objects in the class.
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
super().__init_subclass__(**kwargs)
|
|
160
|
+
|
|
161
|
+
fields = {}
|
|
162
|
+
for base in reversed(cls.__mro__):
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
raw = base.FIELDS
|
|
166
|
+
except AttributeError:
|
|
167
|
+
raw = {}
|
|
168
|
+
|
|
169
|
+
if isinstance(raw, dict):
|
|
170
|
+
fields |= raw
|
|
171
|
+
else:
|
|
172
|
+
fields |= get_class_lookup(*raw, name_function=str.lower)
|
|
173
|
+
|
|
174
|
+
cls.FIELDS = fields
|
|
175
|
+
|
|
176
|
+
for name, FieldInfoType in fields.items():
|
|
177
|
+
if name in cls.__annotations__:
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
field = FieldInfoType()
|
|
181
|
+
setattr(cls, name, field)
|
|
182
|
+
|
|
183
|
+
annotation = FieldInfoType.ANNOTATION
|
|
184
|
+
cls.__annotations__[name] = annotation
|
|
185
|
+
|
|
186
|
+
def to_df(self, name_value='value'):
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
DataFrame representation with Fields as rows.
|
|
190
|
+
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
objs = []
|
|
194
|
+
for name in self.model_fields.keys():
|
|
195
|
+
val = getattr(self, name)
|
|
196
|
+
objs.append(val)
|
|
197
|
+
|
|
198
|
+
df = to_df(*objs, name_value=name_value)
|
|
199
|
+
df['id'] = list(self.model_fields.keys())
|
|
200
|
+
df = df.set_index('id', drop=True)
|
|
201
|
+
return df
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class Root(RootModel, MixinFromJson):
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
Root (list) model
|
|
208
|
+
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
def to_df(self):
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
DataFrame representation with items as rows.
|
|
215
|
+
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
return to_df(*self.items)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from types import UnionType, NoneType
|
|
2
|
+
from typing import Any, get_origin, get_args
|
|
2
3
|
|
|
3
4
|
from fmtr.tools.tools import Raise
|
|
4
5
|
|
|
@@ -84,3 +85,15 @@ def none_else(value: Any, default: Any) -> Any:
|
|
|
84
85
|
if is_none(value):
|
|
85
86
|
return default
|
|
86
87
|
return value
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def is_optional(annotation) -> bool:
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
Is type/annotation optional? todo should be in typing_tools?
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
origin = get_origin(annotation)
|
|
97
|
+
args = get_args(annotation)
|
|
98
|
+
is_opt = origin is UnionType and NoneType in args
|
|
99
|
+
return is_opt
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from itertools import chain, batched
|
|
2
|
-
|
|
3
2
|
from typing import List, Dict, Any
|
|
4
3
|
|
|
5
4
|
from fmtr.tools.datatype_tools import is_none
|
|
5
|
+
from fmtr.tools.tools import identity
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def enlist(value) -> List[Any]:
|
|
@@ -73,3 +73,12 @@ def dedupe(items):
|
|
|
73
73
|
|
|
74
74
|
"""
|
|
75
75
|
return list(dict.fromkeys(items))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_class_lookup(*classes, name_function=identity):
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
Dictionary of class names to classes
|
|
82
|
+
|
|
83
|
+
"""
|
|
84
|
+
return {name_function(cls.__name__): cls for cls in classes}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
from collections import namedtuple
|
|
2
|
-
from string import Formatter
|
|
3
|
-
|
|
4
1
|
import re
|
|
2
|
+
from collections import namedtuple
|
|
5
3
|
from dataclasses import dataclass
|
|
4
|
+
from string import Formatter
|
|
6
5
|
from textwrap import dedent
|
|
7
6
|
from typing import List
|
|
8
7
|
|
|
@@ -151,14 +150,14 @@ def truncate_mid(text, length=None, sep=ELLIPSIS, return_type=str):
|
|
|
151
150
|
)
|
|
152
151
|
|
|
153
152
|
|
|
154
|
-
def flatten(raw):
|
|
153
|
+
def flatten(raw, sep=' '):
|
|
155
154
|
"""
|
|
156
155
|
|
|
157
156
|
Flatten a multiline string to a single line
|
|
158
157
|
|
|
159
158
|
"""
|
|
160
159
|
lines = raw.splitlines()
|
|
161
|
-
text =
|
|
160
|
+
text = sep.join(lines)
|
|
162
161
|
text = text.strip()
|
|
163
162
|
return text
|
|
164
163
|
|
|
@@ -175,6 +174,23 @@ def join(strings, sep=' '):
|
|
|
175
174
|
return text
|
|
176
175
|
|
|
177
176
|
|
|
177
|
+
def join_natural(items, sep=', ', conj='and'):
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
Natural language list
|
|
181
|
+
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
items = list(items)
|
|
185
|
+
if not items:
|
|
186
|
+
return ""
|
|
187
|
+
if len(items) == 1:
|
|
188
|
+
return items[0]
|
|
189
|
+
firsts, last = items[:-1], items[-1]
|
|
190
|
+
firsts_str = join(firsts, sep=sep)
|
|
191
|
+
text = f"{firsts_str} {conj} {last}"
|
|
192
|
+
return text
|
|
193
|
+
|
|
178
194
|
class Mask:
|
|
179
195
|
"""
|
|
180
196
|
|
|
@@ -27,7 +27,15 @@ def identity(x: Any) -> Any:
|
|
|
27
27
|
return x
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class
|
|
30
|
+
class Special:
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
Classes to differentiate special arguments from primitive arguments.
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Empty(Special):
|
|
31
39
|
"""
|
|
32
40
|
|
|
33
41
|
Class to denote an unspecified object (e.g. argument) when `None` cannot be used.
|
|
@@ -35,7 +43,7 @@ class Empty:
|
|
|
35
43
|
"""
|
|
36
44
|
|
|
37
45
|
|
|
38
|
-
class Raise:
|
|
46
|
+
class Raise(Special):
|
|
39
47
|
"""
|
|
40
48
|
|
|
41
49
|
Class to denote when a function should raise instead of e.g. returning a default.
|
|
@@ -43,4 +51,21 @@ class Raise:
|
|
|
43
51
|
"""
|
|
44
52
|
|
|
45
53
|
|
|
54
|
+
class Auto(Special):
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
Class to denote when an argument should be inferred.
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class Required(Special):
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
Class to denote when an argument is required.
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
46
71
|
EMPTY = Empty()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.3.64
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmtr.tools
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.64
|
|
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
|
|
@@ -8,6 +8,20 @@ Author-email: innovative.fowler@mask.pro.fmtr.dev
|
|
|
8
8
|
License: Copyright © 2025 Frontmatter. All rights reserved.
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: logfire; extra == "dev"
|
|
13
|
+
Requires-Dist: semver; extra == "dev"
|
|
14
|
+
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "dev"
|
|
15
|
+
Requires-Dist: pydantic-settings; extra == "dev"
|
|
16
|
+
Requires-Dist: pydantic; extra == "dev"
|
|
17
|
+
Requires-Dist: pydantic-extra-types; extra == "dev"
|
|
18
|
+
Requires-Dist: pycountry; extra == "dev"
|
|
19
|
+
Requires-Dist: yamlscript; extra == "dev"
|
|
20
|
+
Requires-Dist: pyyaml; extra == "dev"
|
|
21
|
+
Requires-Dist: yamlscript; extra == "dev"
|
|
22
|
+
Requires-Dist: pyyaml; extra == "dev"
|
|
23
|
+
Requires-Dist: beanie[odm]; extra == "dev"
|
|
24
|
+
Requires-Dist: motor; extra == "dev"
|
|
11
25
|
Provides-Extra: test
|
|
12
26
|
Requires-Dist: pytest-cov; extra == "test"
|
|
13
27
|
Provides-Extra: yaml
|
|
@@ -154,68 +168,68 @@ Provides-Extra: db-document
|
|
|
154
168
|
Requires-Dist: beanie[odm]; extra == "db-document"
|
|
155
169
|
Requires-Dist: motor; extra == "db-document"
|
|
156
170
|
Provides-Extra: all
|
|
157
|
-
Requires-Dist:
|
|
158
|
-
Requires-Dist:
|
|
159
|
-
Requires-Dist:
|
|
160
|
-
Requires-Dist: cachetools; extra == "all"
|
|
161
|
-
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
162
|
-
Requires-Dist: pydantic; extra == "all"
|
|
163
|
-
Requires-Dist: openai; extra == "all"
|
|
164
|
-
Requires-Dist: ollama; extra == "all"
|
|
165
|
-
Requires-Dist: json_repair; extra == "all"
|
|
166
|
-
Requires-Dist: sentence_transformers; extra == "all"
|
|
167
|
-
Requires-Dist: tabulate; extra == "all"
|
|
168
|
-
Requires-Dist: sre_yield; extra == "all"
|
|
171
|
+
Requires-Dist: deepmerge; extra == "all"
|
|
172
|
+
Requires-Dist: faker; extra == "all"
|
|
173
|
+
Requires-Dist: pandas; extra == "all"
|
|
169
174
|
Requires-Dist: google-api-python-client; extra == "all"
|
|
175
|
+
Requires-Dist: html2text; extra == "all"
|
|
170
176
|
Requires-Dist: pyyaml; extra == "all"
|
|
171
|
-
Requires-Dist: regex; extra == "all"
|
|
172
|
-
Requires-Dist: httpx_retries; extra == "all"
|
|
173
|
-
Requires-Dist: flet-video; extra == "all"
|
|
174
|
-
Requires-Dist: pandas; extra == "all"
|
|
175
|
-
Requires-Dist: openpyxl; extra == "all"
|
|
176
|
-
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
177
|
-
Requires-Dist: semver; extra == "all"
|
|
178
|
-
Requires-Dist: yamlscript; extra == "all"
|
|
179
177
|
Requires-Dist: dask[bag]; extra == "all"
|
|
180
|
-
Requires-Dist:
|
|
181
|
-
Requires-Dist:
|
|
182
|
-
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
183
|
-
Requires-Dist: tinynetrc; extra == "all"
|
|
184
|
-
Requires-Dist: flet[all]; extra == "all"
|
|
185
|
-
Requires-Dist: appdirs; extra == "all"
|
|
186
|
-
Requires-Dist: deepmerge; extra == "all"
|
|
187
|
-
Requires-Dist: httpx; extra == "all"
|
|
188
|
-
Requires-Dist: huggingface_hub; extra == "all"
|
|
178
|
+
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
179
|
+
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
|
|
189
180
|
Requires-Dist: pymupdf; extra == "all"
|
|
190
|
-
Requires-Dist: pytest-cov; extra == "all"
|
|
191
181
|
Requires-Dist: beanie[odm]; extra == "all"
|
|
192
|
-
Requires-Dist:
|
|
193
|
-
Requires-Dist:
|
|
194
|
-
Requires-Dist:
|
|
195
|
-
Requires-Dist: pycountry; extra == "all"
|
|
196
|
-
Requires-Dist: dnspython[doh]; extra == "all"
|
|
197
|
-
Requires-Dist: faker; extra == "all"
|
|
198
|
-
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
199
|
-
Requires-Dist: odfpy; extra == "all"
|
|
200
|
-
Requires-Dist: pydantic-settings; extra == "all"
|
|
182
|
+
Requires-Dist: fastapi; extra == "all"
|
|
183
|
+
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
184
|
+
Requires-Dist: appdirs; extra == "all"
|
|
201
185
|
Requires-Dist: pydantic-extra-types; extra == "all"
|
|
186
|
+
Requires-Dist: distributed; extra == "all"
|
|
202
187
|
Requires-Dist: torchaudio; extra == "all"
|
|
203
|
-
Requires-Dist:
|
|
204
|
-
Requires-Dist:
|
|
205
|
-
Requires-Dist:
|
|
188
|
+
Requires-Dist: setuptools; extra == "all"
|
|
189
|
+
Requires-Dist: deepdiff; extra == "all"
|
|
190
|
+
Requires-Dist: odfpy; extra == "all"
|
|
206
191
|
Requires-Dist: python-on-whales; extra == "all"
|
|
207
|
-
Requires-Dist:
|
|
208
|
-
Requires-Dist: logfire; extra == "all"
|
|
209
|
-
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
|
|
210
|
-
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
192
|
+
Requires-Dist: Unidecode; extra == "all"
|
|
211
193
|
Requires-Dist: contexttimer; extra == "all"
|
|
212
|
-
Requires-Dist:
|
|
194
|
+
Requires-Dist: tokenizers; extra == "all"
|
|
195
|
+
Requires-Dist: pycountry; extra == "all"
|
|
196
|
+
Requires-Dist: openai; extra == "all"
|
|
213
197
|
Requires-Dist: flet-webview; extra == "all"
|
|
198
|
+
Requires-Dist: logfire[httpx]; extra == "all"
|
|
199
|
+
Requires-Dist: regex; extra == "all"
|
|
200
|
+
Requires-Dist: peft; extra == "all"
|
|
201
|
+
Requires-Dist: logfire; extra == "all"
|
|
202
|
+
Requires-Dist: pytest-cov; extra == "all"
|
|
214
203
|
Requires-Dist: playwright; extra == "all"
|
|
215
|
-
Requires-Dist:
|
|
216
|
-
Requires-Dist:
|
|
204
|
+
Requires-Dist: httpx; extra == "all"
|
|
205
|
+
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
206
|
+
Requires-Dist: pydantic-settings; extra == "all"
|
|
207
|
+
Requires-Dist: sentence_transformers; extra == "all"
|
|
208
|
+
Requires-Dist: filetype; extra == "all"
|
|
209
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
210
|
+
Requires-Dist: openpyxl; extra == "all"
|
|
211
|
+
Requires-Dist: ollama; extra == "all"
|
|
212
|
+
Requires-Dist: httpx_retries; extra == "all"
|
|
213
|
+
Requires-Dist: tinynetrc; extra == "all"
|
|
214
|
+
Requires-Dist: flet-video; extra == "all"
|
|
215
|
+
Requires-Dist: pymupdf4llm; extra == "all"
|
|
216
|
+
Requires-Dist: bokeh; extra == "all"
|
|
217
217
|
Requires-Dist: diskcache; extra == "all"
|
|
218
|
-
Requires-Dist:
|
|
218
|
+
Requires-Dist: semver; extra == "all"
|
|
219
|
+
Requires-Dist: huggingface_hub; extra == "all"
|
|
220
|
+
Requires-Dist: flet[all]; extra == "all"
|
|
221
|
+
Requires-Dist: google-auth; extra == "all"
|
|
222
|
+
Requires-Dist: tabulate; extra == "all"
|
|
223
|
+
Requires-Dist: torchvision; extra == "all"
|
|
224
|
+
Requires-Dist: yamlscript; extra == "all"
|
|
225
|
+
Requires-Dist: sre_yield; extra == "all"
|
|
226
|
+
Requires-Dist: json_repair; extra == "all"
|
|
227
|
+
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
228
|
+
Requires-Dist: pydantic; extra == "all"
|
|
229
|
+
Requires-Dist: cachetools; extra == "all"
|
|
230
|
+
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
231
|
+
Requires-Dist: dnspython[doh]; extra == "all"
|
|
232
|
+
Requires-Dist: motor; extra == "all"
|
|
219
233
|
Dynamic: author
|
|
220
234
|
Dynamic: author-email
|
|
221
235
|
Dynamic: description
|
|
@@ -18,68 +18,68 @@ pydantic-ai[logfire,openai]
|
|
|
18
18
|
ollama
|
|
19
19
|
|
|
20
20
|
[all]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
cachetools
|
|
25
|
-
uvicorn[standard]
|
|
26
|
-
pydantic
|
|
27
|
-
openai
|
|
28
|
-
ollama
|
|
29
|
-
json_repair
|
|
30
|
-
sentence_transformers
|
|
31
|
-
tabulate
|
|
32
|
-
sre_yield
|
|
21
|
+
deepmerge
|
|
22
|
+
faker
|
|
23
|
+
pandas
|
|
33
24
|
google-api-python-client
|
|
25
|
+
html2text
|
|
34
26
|
pyyaml
|
|
35
|
-
regex
|
|
36
|
-
httpx_retries
|
|
37
|
-
flet-video
|
|
38
|
-
pandas
|
|
39
|
-
openpyxl
|
|
40
|
-
google-auth-httplib2
|
|
41
|
-
semver
|
|
42
|
-
yamlscript
|
|
43
27
|
dask[bag]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
transformers[sentencepiece]
|
|
47
|
-
tinynetrc
|
|
48
|
-
flet[all]
|
|
49
|
-
appdirs
|
|
50
|
-
deepmerge
|
|
51
|
-
httpx
|
|
52
|
-
huggingface_hub
|
|
28
|
+
google-auth-httplib2
|
|
29
|
+
pydevd-pycharm~=251.25410.159
|
|
53
30
|
pymupdf
|
|
54
|
-
pytest-cov
|
|
55
31
|
beanie[odm]
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
pycountry
|
|
60
|
-
dnspython[doh]
|
|
61
|
-
faker
|
|
62
|
-
pydantic-ai[logfire,openai]
|
|
63
|
-
odfpy
|
|
64
|
-
pydantic-settings
|
|
32
|
+
fastapi
|
|
33
|
+
uvicorn[standard]
|
|
34
|
+
appdirs
|
|
65
35
|
pydantic-extra-types
|
|
36
|
+
distributed
|
|
66
37
|
torchaudio
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
38
|
+
setuptools
|
|
39
|
+
deepdiff
|
|
40
|
+
odfpy
|
|
70
41
|
python-on-whales
|
|
71
|
-
|
|
72
|
-
logfire
|
|
73
|
-
pydevd-pycharm~=251.25410.159
|
|
74
|
-
logfire[fastapi]
|
|
42
|
+
Unidecode
|
|
75
43
|
contexttimer
|
|
76
|
-
|
|
44
|
+
tokenizers
|
|
45
|
+
pycountry
|
|
46
|
+
openai
|
|
77
47
|
flet-webview
|
|
48
|
+
logfire[httpx]
|
|
49
|
+
regex
|
|
50
|
+
peft
|
|
51
|
+
logfire
|
|
52
|
+
pytest-cov
|
|
78
53
|
playwright
|
|
79
|
-
|
|
80
|
-
|
|
54
|
+
httpx
|
|
55
|
+
logfire[fastapi]
|
|
56
|
+
pydantic-settings
|
|
57
|
+
sentence_transformers
|
|
58
|
+
filetype
|
|
59
|
+
pydantic-ai[logfire,openai]
|
|
60
|
+
openpyxl
|
|
61
|
+
ollama
|
|
62
|
+
httpx_retries
|
|
63
|
+
tinynetrc
|
|
64
|
+
flet-video
|
|
65
|
+
pymupdf4llm
|
|
66
|
+
bokeh
|
|
81
67
|
diskcache
|
|
82
|
-
|
|
68
|
+
semver
|
|
69
|
+
huggingface_hub
|
|
70
|
+
flet[all]
|
|
71
|
+
google-auth
|
|
72
|
+
tabulate
|
|
73
|
+
torchvision
|
|
74
|
+
yamlscript
|
|
75
|
+
sre_yield
|
|
76
|
+
json_repair
|
|
77
|
+
transformers[sentencepiece]
|
|
78
|
+
pydantic
|
|
79
|
+
cachetools
|
|
80
|
+
google-auth-oauthlib
|
|
81
|
+
dnspython[doh]
|
|
82
|
+
motor
|
|
83
83
|
|
|
84
84
|
[api]
|
|
85
85
|
fastapi
|
|
@@ -110,6 +110,19 @@ motor
|
|
|
110
110
|
[debug]
|
|
111
111
|
pydevd-pycharm~=251.25410.159
|
|
112
112
|
|
|
113
|
+
[dev]
|
|
114
|
+
logfire
|
|
115
|
+
semver
|
|
116
|
+
pydevd-pycharm~=251.25410.159
|
|
117
|
+
pydantic-settings
|
|
118
|
+
pydantic
|
|
119
|
+
pydantic-extra-types
|
|
120
|
+
pycountry
|
|
121
|
+
yamlscript
|
|
122
|
+
pyyaml
|
|
123
|
+
beanie[odm]
|
|
124
|
+
motor
|
|
125
|
+
|
|
113
126
|
[dm]
|
|
114
127
|
pydantic
|
|
115
128
|
pydantic-extra-types
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from fmtr.tools import Setup
|
|
2
2
|
|
|
3
3
|
DEPENDENCIES = {
|
|
4
|
+
'dev': ['logging', 'version.dev', 'debug', 'sets', 'yaml', 'db.document'],
|
|
5
|
+
|
|
4
6
|
'install': [],
|
|
5
7
|
'test': ['pytest-cov'],
|
|
6
8
|
'yaml': ['yamlscript', 'pyyaml'],
|
|
@@ -43,7 +45,8 @@ DEPENDENCIES = {
|
|
|
43
45
|
'webhook': ['http'],
|
|
44
46
|
'browsers': ['playwright'],
|
|
45
47
|
'db': [],
|
|
46
|
-
'db.document': ['beanie[odm]', 'motor']
|
|
48
|
+
'db.document': ['beanie[odm]', 'motor'],
|
|
49
|
+
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
setup = Setup(
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, RootModel, ConfigDict
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def to_df(*objs, name_value='value'):
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
DataFrame representation of Data Models as rows.
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
from fmtr.tools import tabular
|
|
11
|
-
|
|
12
|
-
rows = []
|
|
13
|
-
for obj in objs:
|
|
14
|
-
if isinstance(obj, BaseModel):
|
|
15
|
-
row = obj.model_dump()
|
|
16
|
-
else:
|
|
17
|
-
row = {name_value: obj}
|
|
18
|
-
rows.append(row)
|
|
19
|
-
|
|
20
|
-
df = tabular.DataFrame(rows)
|
|
21
|
-
if 'id' in df.columns:
|
|
22
|
-
df.set_index('id', inplace=True, drop=True)
|
|
23
|
-
return df
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class MixinArbitraryTypes:
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
Convenience for when non-serializable types are needed
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
33
|
-
|
|
34
|
-
class MixinFromJson:
|
|
35
|
-
|
|
36
|
-
@classmethod
|
|
37
|
-
def from_json(cls, json_str):
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
Error-tolerant deserialization
|
|
41
|
-
|
|
42
|
-
"""
|
|
43
|
-
from fmtr.tools import json_fix
|
|
44
|
-
data = json_fix.from_json(json_str, default={})
|
|
45
|
-
|
|
46
|
-
if type(data) is dict:
|
|
47
|
-
self = cls(**data)
|
|
48
|
-
else:
|
|
49
|
-
self = cls(data)
|
|
50
|
-
|
|
51
|
-
return self
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class Base(BaseModel, MixinFromJson):
|
|
55
|
-
"""
|
|
56
|
-
|
|
57
|
-
Base model
|
|
58
|
-
|
|
59
|
-
"""
|
|
60
|
-
|
|
61
|
-
def to_df(self, name_value='value'):
|
|
62
|
-
"""
|
|
63
|
-
|
|
64
|
-
DataFrame representation with Fields as rows.
|
|
65
|
-
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
objs = []
|
|
69
|
-
for name in self.model_fields.keys():
|
|
70
|
-
val = getattr(self, name)
|
|
71
|
-
objs.append(val)
|
|
72
|
-
|
|
73
|
-
df = to_df(*objs, name_value=name_value)
|
|
74
|
-
df['id'] = list(self.model_fields.keys())
|
|
75
|
-
df = df.set_index('id', drop=True)
|
|
76
|
-
return df
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class Root(RootModel, MixinFromJson):
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
Root (list) model
|
|
83
|
-
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
def to_df(self):
|
|
87
|
-
"""
|
|
88
|
-
|
|
89
|
-
DataFrame representation with items as rows.
|
|
90
|
-
|
|
91
|
-
"""
|
|
92
|
-
|
|
93
|
-
return to_df(*self.items)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.3.62
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|