fmtr.tools 1.0.54__tar.gz → 1.1.0__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.0.54 → fmtr_tools-1.1.0}/PKG-INFO +154 -28
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/README.md +9 -1
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/__init__.py +8 -3
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/ai_tools/agentic_tools.py +3 -3
- fmtr.tools-1.0.54/fmtr/tools/config.py → fmtr_tools-1.1.0/fmtr/tools/constants.py +1 -3
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/debugging_tools.py +5 -5
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/environment_tools.py +2 -2
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/hash_tools.py +2 -2
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/json_tools.py +2 -2
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/logging_tools.py +4 -4
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/parallel_tools.py +1 -2
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/path_tools.py +113 -33
- fmtr_tools-1.1.0/fmtr/tools/settings_tools.py +65 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tokenization_tools.py +1 -2
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tools.py +2 -2
- fmtr_tools-1.1.0/fmtr/tools/version +1 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/version_tools.py +16 -7
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr.tools.egg-info/PKG-INFO +154 -28
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr.tools.egg-info/SOURCES.txt +2 -2
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr.tools.egg-info/requires.txt +55 -50
- fmtr.tools-1.0.54/fmtr/tools/config_tools.py +0 -54
- fmtr.tools-1.0.54/fmtr/tools/version +0 -1
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/LICENSE +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/ai_tools/__init__.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/ai_tools/inference_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/api_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/async_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/augmentation_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/caching_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/console_script_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/data_modelling_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/dataclass_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/datatype_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/docker_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/function_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/google_api_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/hfh_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/html_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/import_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/inspection_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/interface_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/iterator_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/json_fix_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/merging_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/metric_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/name_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/netrc_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/openai_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/pdf_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/platform_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/process_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/profiling_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/random_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/semantic_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/spaces_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/string_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tabular_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/__init__.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/conftest.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/helpers.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/test_datatype.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/test_environment.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/test_json.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/test_path.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/tests/test_yaml.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/unicode_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr/tools/yaml_tools.py +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr.tools.egg-info/dependency_links.txt +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr.tools.egg-info/entry_points.txt +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/fmtr.tools.egg-info/top_level.txt +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/setup.cfg +0 -0
- {fmtr.tools-1.0.54 → fmtr_tools-1.1.0}/setup.py +0 -0
|
@@ -1,43 +1,161 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fmtr.tools
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
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
|
|
7
7
|
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
|
-
|
|
11
|
-
Provides-Extra:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Provides-Extra: test
|
|
12
|
+
Requires-Dist: flet-webview; extra == "test"
|
|
13
|
+
Requires-Dist: uvicorn; extra == "test"
|
|
14
|
+
Requires-Dist: pymupdf4llm; extra == "test"
|
|
15
|
+
Requires-Dist: pyyaml; extra == "test"
|
|
16
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
17
|
+
Requires-Dist: logfire; extra == "test"
|
|
18
|
+
Requires-Dist: google-auth-httplib2; extra == "test"
|
|
19
|
+
Requires-Dist: tinynetrc; extra == "test"
|
|
20
|
+
Requires-Dist: sre_yield; extra == "test"
|
|
21
|
+
Requires-Dist: bokeh; extra == "test"
|
|
22
|
+
Requires-Dist: html2text; extra == "test"
|
|
23
|
+
Requires-Dist: sentence_transformers; extra == "test"
|
|
24
|
+
Requires-Dist: docker; extra == "test"
|
|
25
|
+
Requires-Dist: peft; extra == "test"
|
|
26
|
+
Requires-Dist: google-auth; extra == "test"
|
|
27
|
+
Requires-Dist: fastapi; extra == "test"
|
|
28
|
+
Requires-Dist: pydantic; extra == "test"
|
|
29
|
+
Requires-Dist: pydantic-settings; extra == "test"
|
|
30
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "test"
|
|
31
|
+
Requires-Dist: torchvision; extra == "test"
|
|
32
|
+
Requires-Dist: google-api-python-client; extra == "test"
|
|
33
|
+
Requires-Dist: distributed; extra == "test"
|
|
34
|
+
Requires-Dist: openpyxl; extra == "test"
|
|
35
|
+
Requires-Dist: contexttimer; extra == "test"
|
|
36
|
+
Requires-Dist: huggingface_hub; extra == "test"
|
|
37
|
+
Requires-Dist: dask[bag]; extra == "test"
|
|
38
|
+
Requires-Dist: tabulate; extra == "test"
|
|
39
|
+
Requires-Dist: tokenizers; extra == "test"
|
|
40
|
+
Requires-Dist: ollama; extra == "test"
|
|
41
|
+
Requires-Dist: pandas; extra == "test"
|
|
42
|
+
Requires-Dist: flet-video; extra == "test"
|
|
43
|
+
Requires-Dist: flet[all]; extra == "test"
|
|
44
|
+
Requires-Dist: transformers[sentencepiece]; extra == "test"
|
|
45
|
+
Requires-Dist: semver; extra == "test"
|
|
46
|
+
Requires-Dist: openai; extra == "test"
|
|
47
|
+
Requires-Dist: google-auth-oauthlib; extra == "test"
|
|
48
|
+
Requires-Dist: pydevd-pycharm; extra == "test"
|
|
49
|
+
Requires-Dist: faker; extra == "test"
|
|
50
|
+
Requires-Dist: pymupdf; extra == "test"
|
|
51
|
+
Requires-Dist: deepmerge; extra == "test"
|
|
52
|
+
Requires-Dist: diskcache; extra == "test"
|
|
53
|
+
Requires-Dist: json_repair; extra == "test"
|
|
54
|
+
Requires-Dist: Unidecode; extra == "test"
|
|
55
|
+
Requires-Dist: torchaudio; extra == "test"
|
|
56
|
+
Provides-Extra: yaml
|
|
57
|
+
Requires-Dist: pyyaml; extra == "yaml"
|
|
23
58
|
Provides-Extra: logging
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Provides-Extra: netrc
|
|
27
|
-
Provides-Extra: openai.api
|
|
59
|
+
Requires-Dist: logfire; extra == "logging"
|
|
60
|
+
Requires-Dist: semver; extra == "logging"
|
|
28
61
|
Provides-Extra: parallel
|
|
29
|
-
|
|
62
|
+
Requires-Dist: dask[bag]; extra == "parallel"
|
|
63
|
+
Requires-Dist: distributed; extra == "parallel"
|
|
64
|
+
Requires-Dist: bokeh; extra == "parallel"
|
|
65
|
+
Provides-Extra: tokenization
|
|
66
|
+
Requires-Dist: tokenizers; extra == "tokenization"
|
|
67
|
+
Provides-Extra: augmentation
|
|
68
|
+
Requires-Dist: faker; extra == "augmentation"
|
|
69
|
+
Requires-Dist: sre_yield; extra == "augmentation"
|
|
30
70
|
Provides-Extra: process
|
|
71
|
+
Requires-Dist: logfire; extra == "process"
|
|
72
|
+
Requires-Dist: semver; extra == "process"
|
|
31
73
|
Provides-Extra: profiling
|
|
32
|
-
|
|
33
|
-
Provides-Extra:
|
|
34
|
-
|
|
35
|
-
Provides-Extra: test
|
|
36
|
-
Provides-Extra: tokenization
|
|
74
|
+
Requires-Dist: contexttimer; extra == "profiling"
|
|
75
|
+
Provides-Extra: docker-api
|
|
76
|
+
Requires-Dist: docker; extra == "docker-api"
|
|
37
77
|
Provides-Extra: unicode
|
|
78
|
+
Requires-Dist: Unidecode; extra == "unicode"
|
|
38
79
|
Provides-Extra: version
|
|
39
|
-
|
|
40
|
-
|
|
80
|
+
Requires-Dist: semver; extra == "version"
|
|
81
|
+
Provides-Extra: spaces
|
|
82
|
+
Requires-Dist: tinynetrc; extra == "spaces"
|
|
83
|
+
Provides-Extra: netrc
|
|
84
|
+
Requires-Dist: tinynetrc; extra == "netrc"
|
|
85
|
+
Provides-Extra: hfh
|
|
86
|
+
Requires-Dist: huggingface_hub; extra == "hfh"
|
|
87
|
+
Provides-Extra: merging
|
|
88
|
+
Requires-Dist: deepmerge; extra == "merging"
|
|
89
|
+
Provides-Extra: api
|
|
90
|
+
Requires-Dist: fastapi; extra == "api"
|
|
91
|
+
Requires-Dist: uvicorn; extra == "api"
|
|
92
|
+
Requires-Dist: logfire; extra == "api"
|
|
93
|
+
Requires-Dist: semver; extra == "api"
|
|
94
|
+
Requires-Dist: pydantic; extra == "api"
|
|
95
|
+
Provides-Extra: ai
|
|
96
|
+
Requires-Dist: peft; extra == "ai"
|
|
97
|
+
Requires-Dist: transformers[sentencepiece]; extra == "ai"
|
|
98
|
+
Requires-Dist: torchvision; extra == "ai"
|
|
99
|
+
Requires-Dist: torchaudio; extra == "ai"
|
|
100
|
+
Requires-Dist: pydantic; extra == "ai"
|
|
101
|
+
Provides-Extra: dm
|
|
102
|
+
Requires-Dist: pydantic; extra == "dm"
|
|
103
|
+
Provides-Extra: openai-api
|
|
104
|
+
Requires-Dist: openai; extra == "openai-api"
|
|
105
|
+
Provides-Extra: ai-client
|
|
106
|
+
Requires-Dist: logfire; extra == "ai-client"
|
|
107
|
+
Requires-Dist: semver; extra == "ai-client"
|
|
108
|
+
Requires-Dist: pydantic; extra == "ai-client"
|
|
109
|
+
Requires-Dist: openai; extra == "ai-client"
|
|
110
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "ai-client"
|
|
111
|
+
Requires-Dist: ollama; extra == "ai-client"
|
|
112
|
+
Provides-Extra: json-fix
|
|
113
|
+
Requires-Dist: json_repair; extra == "json-fix"
|
|
114
|
+
Provides-Extra: semantic
|
|
115
|
+
Requires-Dist: sentence_transformers; extra == "semantic"
|
|
116
|
+
Requires-Dist: pandas; extra == "semantic"
|
|
117
|
+
Requires-Dist: tabulate; extra == "semantic"
|
|
118
|
+
Requires-Dist: openpyxl; extra == "semantic"
|
|
119
|
+
Provides-Extra: metric
|
|
120
|
+
Requires-Dist: pandas; extra == "metric"
|
|
121
|
+
Requires-Dist: tabulate; extra == "metric"
|
|
122
|
+
Requires-Dist: openpyxl; extra == "metric"
|
|
123
|
+
Provides-Extra: tabular
|
|
124
|
+
Requires-Dist: pandas; extra == "tabular"
|
|
125
|
+
Requires-Dist: tabulate; extra == "tabular"
|
|
126
|
+
Requires-Dist: openpyxl; extra == "tabular"
|
|
127
|
+
Provides-Extra: html
|
|
128
|
+
Requires-Dist: html2text; extra == "html"
|
|
129
|
+
Provides-Extra: interface
|
|
130
|
+
Requires-Dist: flet[all]; extra == "interface"
|
|
131
|
+
Requires-Dist: flet-video; extra == "interface"
|
|
132
|
+
Requires-Dist: flet-webview; extra == "interface"
|
|
133
|
+
Requires-Dist: pydantic; extra == "interface"
|
|
134
|
+
Provides-Extra: google-api
|
|
135
|
+
Requires-Dist: google-auth; extra == "google-api"
|
|
136
|
+
Requires-Dist: google-auth-oauthlib; extra == "google-api"
|
|
137
|
+
Requires-Dist: google-auth-httplib2; extra == "google-api"
|
|
138
|
+
Requires-Dist: google-api-python-client; extra == "google-api"
|
|
139
|
+
Provides-Extra: caching
|
|
140
|
+
Requires-Dist: diskcache; extra == "caching"
|
|
141
|
+
Provides-Extra: pdf
|
|
142
|
+
Requires-Dist: pymupdf; extra == "pdf"
|
|
143
|
+
Requires-Dist: pydantic; extra == "pdf"
|
|
144
|
+
Requires-Dist: pymupdf4llm; extra == "pdf"
|
|
145
|
+
Provides-Extra: debug
|
|
146
|
+
Requires-Dist: pydevd-pycharm; extra == "debug"
|
|
147
|
+
Provides-Extra: sets
|
|
148
|
+
Requires-Dist: pydantic-settings; extra == "sets"
|
|
149
|
+
Requires-Dist: pydantic; extra == "sets"
|
|
150
|
+
Dynamic: author
|
|
151
|
+
Dynamic: author-email
|
|
152
|
+
Dynamic: description
|
|
153
|
+
Dynamic: description-content-type
|
|
154
|
+
Dynamic: home-page
|
|
155
|
+
Dynamic: license
|
|
156
|
+
Dynamic: license-file
|
|
157
|
+
Dynamic: provides-extra
|
|
158
|
+
Dynamic: summary
|
|
41
159
|
|
|
42
160
|
# `fmtr.tools`
|
|
43
161
|
|
|
@@ -125,6 +243,10 @@ The included modules, plus any extra requirements, are as follows:
|
|
|
125
243
|
- Extras: `ai`
|
|
126
244
|
- `tools.config`: Base config class with overridable field processors.
|
|
127
245
|
- Extras: None
|
|
246
|
+
-
|
|
247
|
+
`tools.settings`: A base configuration system built on Pydantic Settings that provides a flexible way to manage application settings from multiple sources, based on a standard
|
|
248
|
+
`path.PackagePaths` project layout.
|
|
249
|
+
- Extras: `sets`
|
|
128
250
|
- `tools.dataclass`: Utilities for extracting and filtering fields and metadata from dataclasses, with support for applying filters and retrieving enabled fields based on metadata attributes.
|
|
129
251
|
- Extras: None
|
|
130
252
|
- `tools.datatype`
|
|
@@ -155,8 +277,12 @@ The included modules, plus any extra requirements, are as follows:
|
|
|
155
277
|
- Extras: None
|
|
156
278
|
- `tools.openai`: Utilities for interacting with the OpenAI API, simple text-to-text output, etc.
|
|
157
279
|
- Extras: `openai.api`
|
|
158
|
-
- `tools.Path`: Enhanced
|
|
280
|
+
- `tools.Path`: Enhanced
|
|
281
|
+
`pathlib.Path` object with additional functionality for Windows-to-Unix path conversion in WSL environments, reading/writing JSON and YAML files with proper encoding.
|
|
159
282
|
- Extras: None
|
|
283
|
+
-
|
|
284
|
+
`tools.PackagePaths` class for managing canonical package paths, like settings files, artifact directories, version files.
|
|
285
|
+
- Extras: None
|
|
160
286
|
- `tools.platform`: Detecting if host is WSL, Docker etc.
|
|
161
287
|
- Extras: None
|
|
162
288
|
- `tools.ContextProcess`: Manages a function running in a separate process using a context manager. Provides methods to start, stop, and restart the process, with configurable restart delays. Useful for ensuring clean process management and automatic stopping when the context manager exits.
|
|
@@ -84,6 +84,10 @@ The included modules, plus any extra requirements, are as follows:
|
|
|
84
84
|
- Extras: `ai`
|
|
85
85
|
- `tools.config`: Base config class with overridable field processors.
|
|
86
86
|
- Extras: None
|
|
87
|
+
-
|
|
88
|
+
`tools.settings`: A base configuration system built on Pydantic Settings that provides a flexible way to manage application settings from multiple sources, based on a standard
|
|
89
|
+
`path.PackagePaths` project layout.
|
|
90
|
+
- Extras: `sets`
|
|
87
91
|
- `tools.dataclass`: Utilities for extracting and filtering fields and metadata from dataclasses, with support for applying filters and retrieving enabled fields based on metadata attributes.
|
|
88
92
|
- Extras: None
|
|
89
93
|
- `tools.datatype`
|
|
@@ -114,8 +118,12 @@ The included modules, plus any extra requirements, are as follows:
|
|
|
114
118
|
- Extras: None
|
|
115
119
|
- `tools.openai`: Utilities for interacting with the OpenAI API, simple text-to-text output, etc.
|
|
116
120
|
- Extras: `openai.api`
|
|
117
|
-
- `tools.Path`: Enhanced
|
|
121
|
+
- `tools.Path`: Enhanced
|
|
122
|
+
`pathlib.Path` object with additional functionality for Windows-to-Unix path conversion in WSL environments, reading/writing JSON and YAML files with proper encoding.
|
|
118
123
|
- Extras: None
|
|
124
|
+
-
|
|
125
|
+
`tools.PackagePaths` class for managing canonical package paths, like settings files, artifact directories, version files.
|
|
126
|
+
- Extras: None
|
|
119
127
|
- `tools.platform`: Detecting if host is WSL, Docker etc.
|
|
120
128
|
- Extras: None
|
|
121
129
|
- `tools.ContextProcess`: Manages a function running in a separate process using a context manager. Provides methods to start, stop, and restart the process, with configurable restart delays. Useful for ensuring clean process management and automatic stopping when the context manager exits.
|
|
@@ -2,7 +2,7 @@ from fmtr.tools import version_tools as version
|
|
|
2
2
|
|
|
3
3
|
__version__ = version.read()
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
import fmtr.tools.dataclass_tools as dataclass
|
|
7
7
|
import fmtr.tools.datatype_tools as datatype
|
|
8
8
|
import fmtr.tools.environment_tools as env
|
|
@@ -22,7 +22,8 @@ import fmtr.tools.async_tools as asyncio
|
|
|
22
22
|
from fmtr.tools.logging_tools import logger
|
|
23
23
|
|
|
24
24
|
from fmtr.tools.import_tools import MissingExtraMockModule
|
|
25
|
-
from fmtr.tools.path_tools import Path
|
|
25
|
+
from fmtr.tools.path_tools import Path, PackagePaths
|
|
26
|
+
from fmtr.tools.constants import Constants
|
|
26
27
|
|
|
27
28
|
try:
|
|
28
29
|
from fmtr.tools import augmentation_tools as augmentation
|
|
@@ -158,9 +159,13 @@ try:
|
|
|
158
159
|
except ImportError as exception:
|
|
159
160
|
debug = MissingExtraMockModule('debug', exception)
|
|
160
161
|
|
|
162
|
+
try:
|
|
163
|
+
from fmtr.tools import settings_tools as sets
|
|
164
|
+
except ImportError as exception:
|
|
165
|
+
sets = MissingExtraMockModule('sets', exception)
|
|
166
|
+
|
|
161
167
|
|
|
162
168
|
__all__ = [
|
|
163
|
-
'config',
|
|
164
169
|
'dataclass',
|
|
165
170
|
'datatype',
|
|
166
171
|
'environment',
|
|
@@ -6,7 +6,7 @@ from pydantic_ai.models.openai import OpenAIModel
|
|
|
6
6
|
from pydantic_ai.providers.openai import OpenAIProvider
|
|
7
7
|
|
|
8
8
|
from fmtr.tools import environment_tools as env
|
|
9
|
-
from fmtr.tools.
|
|
9
|
+
from fmtr.tools.constants import Constants
|
|
10
10
|
|
|
11
11
|
pydantic_ai.Agent.instrument_all()
|
|
12
12
|
|
|
@@ -17,9 +17,9 @@ class Task:
|
|
|
17
17
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
PROVIDER = OpenAIProvider(api_key=env.get(
|
|
20
|
+
PROVIDER = OpenAIProvider(api_key=env.get(Constants.FMTR_OPENAI_API_KEY_KEY))
|
|
21
21
|
|
|
22
|
-
API_HOST_FMTR = env.get(
|
|
22
|
+
API_HOST_FMTR = env.get(Constants.FMTR_AI_HOST_KEY, Constants.FMTR_AI_HOST_DEFAULT)
|
|
23
23
|
API_URL_FMTR = f'https://{API_HOST_FMTR}/v1'
|
|
24
24
|
PROVIDER_FMTR = OpenAIProvider(base_url=API_URL_FMTR)
|
|
25
25
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pydevd_pycharm
|
|
2
2
|
|
|
3
3
|
from fmtr.tools import environment_tools as env
|
|
4
|
-
from fmtr.tools.
|
|
4
|
+
from fmtr.tools.constants import Constants
|
|
5
5
|
|
|
6
6
|
MASK = 'Starting debugger at tcp://{host}:{port}...'
|
|
7
7
|
|
|
@@ -12,16 +12,16 @@ def trace(is_debug=None, host=None, port=None, stdoutToServer=True, stderrToServ
|
|
|
12
12
|
|
|
13
13
|
"""
|
|
14
14
|
if not is_debug:
|
|
15
|
-
is_debug = env.get_bool(
|
|
15
|
+
is_debug = env.get_bool(Constants.FMTR_REMOTE_DEBUG_ENABLED_KEY, False)
|
|
16
16
|
|
|
17
17
|
if not is_debug:
|
|
18
18
|
return
|
|
19
19
|
|
|
20
20
|
if is_debug is True and not host:
|
|
21
|
-
host =
|
|
21
|
+
host = Constants.FMTR_REMOTE_DEBUG_HOST_DEFAULT
|
|
22
22
|
|
|
23
|
-
host = host or env.get(
|
|
24
|
-
port = port or
|
|
23
|
+
host = host or env.get(Constants.FMTR_REMOTE_DEBUG_HOST_KEY, Constants.FMTR_REMOTE_DEBUG_HOST_DEFAULT)
|
|
24
|
+
port = port or Constants.FMTR_REMOTE_DEBUG_PORT_DEFAULT
|
|
25
25
|
|
|
26
26
|
from fmtr.tools import logger
|
|
27
27
|
|
|
@@ -8,7 +8,7 @@ from collections.abc import Callable
|
|
|
8
8
|
from datetime import date, datetime
|
|
9
9
|
from typing import Any, Dict
|
|
10
10
|
|
|
11
|
-
from fmtr.tools.
|
|
11
|
+
from fmtr.tools.constants import Constants
|
|
12
12
|
from fmtr.tools.datatype_tools import to_bool
|
|
13
13
|
from fmtr.tools.path_tools import Path
|
|
14
14
|
from fmtr.tools.tools import identity, EMPTY
|
|
@@ -76,4 +76,4 @@ get_date = get_getter(date.fromisoformat)
|
|
|
76
76
|
get_datetime = get_getter(datetime.fromisoformat)
|
|
77
77
|
get_path = get_getter(Path)
|
|
78
78
|
|
|
79
|
-
IS_DEBUG = get(
|
|
79
|
+
IS_DEBUG = get(Constants.FMTR_LOG_LEVEL_KEY, None, converter=str.upper) == 'DEBUG'
|
|
@@ -2,7 +2,7 @@ import base64
|
|
|
2
2
|
import hashlib
|
|
3
3
|
from zlib import crc32
|
|
4
4
|
|
|
5
|
-
from fmtr.tools.
|
|
5
|
+
from fmtr.tools.constants import Constants
|
|
6
6
|
|
|
7
7
|
SPECIALS = {'O': '9', '=': '9', 'I': '9'}
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ def hash_unit(value: str) -> float:
|
|
|
12
12
|
Hash the input string to a value between 0.0 and 1.0 (not secure).
|
|
13
13
|
|
|
14
14
|
"""
|
|
15
|
-
value = str(value).encode(
|
|
15
|
+
value = str(value).encode(Constants.ENCODING)
|
|
16
16
|
return float(crc32(value) & 0xffffffff) / 2 ** 32
|
|
17
17
|
|
|
18
18
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
|
|
3
|
-
from fmtr.tools.
|
|
3
|
+
from fmtr.tools.constants import Constants
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def to_json(obj):
|
|
@@ -9,7 +9,7 @@ def to_json(obj):
|
|
|
9
9
|
Serialise to JSON
|
|
10
10
|
|
|
11
11
|
"""
|
|
12
|
-
json_str = json.dumps(obj, indent=
|
|
12
|
+
json_str = json.dumps(obj, indent=Constants.SERIALIZATION_INDENT, ensure_ascii=False)
|
|
13
13
|
return json_str
|
|
14
14
|
|
|
15
15
|
|
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
4
|
from fmtr.tools import environment_tools
|
|
5
|
-
from fmtr.tools.
|
|
5
|
+
from fmtr.tools.constants import Constants
|
|
6
6
|
|
|
7
7
|
DEVELOPMENT = "development"
|
|
8
8
|
PRODUCTION = "production"
|
|
@@ -12,7 +12,7 @@ ENVIRONMENT_DEFAULT = DEVELOPMENT
|
|
|
12
12
|
LEVEL_DEFAULT = logging.DEBUG if environment_tools.IS_DEBUG else logging.INFO
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def get_logger(name, version=None, host=
|
|
15
|
+
def get_logger(name, version=None, host=Constants.FMTR_OBS_HOST, key=None, org=Constants.ORG_NAME,
|
|
16
16
|
stream=STREAM_DEFAULT,
|
|
17
17
|
environment=ENVIRONMENT_DEFAULT, level=LEVEL_DEFAULT):
|
|
18
18
|
"""
|
|
@@ -31,7 +31,7 @@ def get_logger(name, version=None, host=ToolsConfig.FMTR_OBS_HOST, key=None, org
|
|
|
31
31
|
return logger
|
|
32
32
|
|
|
33
33
|
if key is None:
|
|
34
|
-
key = environment_tools.get(
|
|
34
|
+
key = environment_tools.get(Constants.FMTR_OBS_API_KEY_KEY)
|
|
35
35
|
url = f"https://{host}/api/{org}/v1/traces"
|
|
36
36
|
headers = f"Authorization=Basic {key},stream-name={stream}"
|
|
37
37
|
|
|
@@ -57,7 +57,7 @@ def get_logger(name, version=None, host=ToolsConfig.FMTR_OBS_HOST, key=None, org
|
|
|
57
57
|
return logger
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
logger = get_logger(name=
|
|
60
|
+
logger = get_logger(name=Constants.LIBRARY_NAME)
|
|
61
61
|
|
|
62
62
|
if __name__ == '__main__':
|
|
63
63
|
logger.info('Hello World')
|
|
@@ -6,13 +6,12 @@ from contextlib import nullcontext as NullContext
|
|
|
6
6
|
from dask.diagnostics import ProgressBar
|
|
7
7
|
from typing import List, Callable, Any, Union
|
|
8
8
|
|
|
9
|
-
from fmtr.tools.config_tools import ConfigClass
|
|
10
9
|
from fmtr.tools.iterator_tools import dict_records_to_lists
|
|
11
10
|
from fmtr.tools.logging_tools import logger
|
|
12
11
|
from fmtr.tools.path_tools import Path
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
class ParallelConfig
|
|
14
|
+
class ParallelConfig:
|
|
16
15
|
"""
|
|
17
16
|
|
|
18
17
|
Configuration values.
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import subprocess
|
|
3
|
-
from inspect import stack
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from tempfile import gettempdir
|
|
6
5
|
from typing import Union, Any
|
|
7
6
|
|
|
8
|
-
from fmtr.tools.
|
|
7
|
+
from fmtr.tools.constants import Constants
|
|
9
8
|
from fmtr.tools.platform_tools import is_wsl
|
|
10
9
|
|
|
11
10
|
WIN_PATH_PATTERN = r'''([a-z]:(\\|$)|\\\\)'''
|
|
@@ -72,8 +71,8 @@ class Path(type(Path())):
|
|
|
72
71
|
Get path to originating module (e.g. directory containing .py file).
|
|
73
72
|
|
|
74
73
|
"""
|
|
75
|
-
|
|
76
|
-
path =
|
|
74
|
+
from fmtr.tools.inspection_tools import get_call_path
|
|
75
|
+
path = get_call_path(offset=2).absolute().parent
|
|
77
76
|
return path
|
|
78
77
|
|
|
79
78
|
@classmethod
|
|
@@ -83,8 +82,8 @@ class Path(type(Path())):
|
|
|
83
82
|
Get path to originating module (i.e. .py file).
|
|
84
83
|
|
|
85
84
|
"""
|
|
86
|
-
|
|
87
|
-
path =
|
|
85
|
+
from fmtr.tools.inspection_tools import get_call_path
|
|
86
|
+
path = get_call_path(offset=2).absolute()
|
|
88
87
|
return path
|
|
89
88
|
|
|
90
89
|
@classmethod
|
|
@@ -96,29 +95,6 @@ class Path(type(Path())):
|
|
|
96
95
|
"""
|
|
97
96
|
return cls(gettempdir())
|
|
98
97
|
|
|
99
|
-
@classmethod
|
|
100
|
-
def data(cls, name='data') -> 'Path':
|
|
101
|
-
"""
|
|
102
|
-
|
|
103
|
-
Fetch canonical "data"/"artifacts" path, whether calling package is regular or namespace package.
|
|
104
|
-
|
|
105
|
-
"""
|
|
106
|
-
from fmtr.tools.inspection_tools import get_call_path
|
|
107
|
-
path = get_call_path()
|
|
108
|
-
path = path.absolute().parent.parent
|
|
109
|
-
|
|
110
|
-
path /= name
|
|
111
|
-
|
|
112
|
-
if path.exists():
|
|
113
|
-
return path
|
|
114
|
-
|
|
115
|
-
path = path.parent.parent / name
|
|
116
|
-
|
|
117
|
-
if path.exists():
|
|
118
|
-
return path
|
|
119
|
-
|
|
120
|
-
raise FileNotFoundError(f'No "{name}" directory found at "{path}"')
|
|
121
|
-
|
|
122
98
|
def write_json(self, obj) -> int:
|
|
123
99
|
"""
|
|
124
100
|
|
|
@@ -127,7 +103,7 @@ class Path(type(Path())):
|
|
|
127
103
|
"""
|
|
128
104
|
from fmtr.tools import json
|
|
129
105
|
json_str = json.to_json(obj)
|
|
130
|
-
return self.write_text(json_str, encoding=
|
|
106
|
+
return self.write_text(json_str, encoding=Constants.ENCODING)
|
|
131
107
|
|
|
132
108
|
def read_json(self) -> Any:
|
|
133
109
|
"""
|
|
@@ -136,7 +112,7 @@ class Path(type(Path())):
|
|
|
136
112
|
|
|
137
113
|
"""
|
|
138
114
|
from fmtr.tools import json
|
|
139
|
-
json_str = self.read_text(encoding=
|
|
115
|
+
json_str = self.read_text(encoding=Constants.ENCODING)
|
|
140
116
|
obj = json.from_json(json_str)
|
|
141
117
|
return obj
|
|
142
118
|
|
|
@@ -148,7 +124,7 @@ class Path(type(Path())):
|
|
|
148
124
|
"""
|
|
149
125
|
from fmtr.tools import yaml
|
|
150
126
|
yaml_str = yaml.to_yaml(obj)
|
|
151
|
-
return self.write_text(yaml_str, encoding=
|
|
127
|
+
return self.write_text(yaml_str, encoding=Constants.ENCODING)
|
|
152
128
|
|
|
153
129
|
def read_yaml(self) -> Any:
|
|
154
130
|
"""
|
|
@@ -157,7 +133,7 @@ class Path(type(Path())):
|
|
|
157
133
|
|
|
158
134
|
"""
|
|
159
135
|
from fmtr.tools import yaml
|
|
160
|
-
yaml_str = self.read_text(encoding=
|
|
136
|
+
yaml_str = self.read_text(encoding=Constants.ENCODING)
|
|
161
137
|
obj = yaml.from_yaml(yaml_str)
|
|
162
138
|
return obj
|
|
163
139
|
|
|
@@ -170,3 +146,107 @@ class Path(type(Path())):
|
|
|
170
146
|
return self.mkdir(parents=True, exist_ok=True)
|
|
171
147
|
|
|
172
148
|
|
|
149
|
+
class PackagePaths:
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
Canonical paths for a package.
|
|
153
|
+
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
FILENAME_CONFIG = 'settings.yaml'
|
|
157
|
+
DIR_NAME_ARTIFACTS = 'artifacts'
|
|
158
|
+
FILENAME_VERSION = 'version'
|
|
159
|
+
|
|
160
|
+
def __init__(self, path=None, org_singleton=None, dir_name_artifacts=DIR_NAME_ARTIFACTS, filename_config=FILENAME_CONFIG, file_version=FILENAME_VERSION):
|
|
161
|
+
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
Use calling module path as default path, if not otherwise specified.
|
|
165
|
+
|
|
166
|
+
"""
|
|
167
|
+
if not path:
|
|
168
|
+
from fmtr.tools.inspection_tools import get_call_path
|
|
169
|
+
path = get_call_path(offset=2).parent
|
|
170
|
+
|
|
171
|
+
self.path = Path(path)
|
|
172
|
+
self.org_singleton = org_singleton
|
|
173
|
+
self.dir_name_artifacts = dir_name_artifacts
|
|
174
|
+
self.filename_config = filename_config
|
|
175
|
+
self.filename_version = file_version
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def is_namespace(self) -> bool:
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
If organization is not hard-specified, then the package is a namespace.
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
return not bool(self.org_singleton)
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def name(self) -> str:
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
Name of package.
|
|
191
|
+
|
|
192
|
+
"""
|
|
193
|
+
return self.path.stem
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def org(self) -> str:
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
Name of organization.
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
if not self.is_namespace:
|
|
203
|
+
return self.org_singleton
|
|
204
|
+
else:
|
|
205
|
+
return self.path.parent.stem
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def repo(self) -> Path:
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
Path of repo (i.e. parent of package base directory).
|
|
212
|
+
|
|
213
|
+
"""
|
|
214
|
+
if self.is_namespace:
|
|
215
|
+
return self.path.parent.parent
|
|
216
|
+
else:
|
|
217
|
+
return self.path.parent
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def version(self) -> Path:
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
Path of version file.
|
|
224
|
+
|
|
225
|
+
"""
|
|
226
|
+
return self.path / self.filename_version
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def artifacts(self) -> Path:
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
Path of artifacts directory.
|
|
233
|
+
|
|
234
|
+
"""
|
|
235
|
+
return self.repo / self.dir_name_artifacts
|
|
236
|
+
|
|
237
|
+
@property
|
|
238
|
+
def settings(self) -> Path:
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
Path of settings file.
|
|
242
|
+
|
|
243
|
+
"""
|
|
244
|
+
return self.artifacts / self.filename_config
|
|
245
|
+
|
|
246
|
+
def __repr__(self) -> str:
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
Show base path in repr.
|
|
250
|
+
|
|
251
|
+
"""
|
|
252
|
+
return f'{self.__class__.__name__}("{self.path}")'
|