fmtr.tools 1.3.48__tar.gz → 1.3.50__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.48 → fmtr_tools-1.3.50}/PKG-INFO +53 -49
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/database_tools/document.py +4 -3
- fmtr_tools-1.3.50/fmtr/tools/datetime_tools.py +31 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/iterator_tools.py +9 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/path_tools/path_tools.py +26 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/pdf_tools.py +14 -0
- fmtr_tools-1.3.50/fmtr/tools/tabular_tools.py +68 -0
- fmtr_tools-1.3.50/fmtr/tools/version +1 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr.tools.egg-info/PKG-INFO +53 -49
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr.tools.egg-info/requires.txt +52 -48
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/setup.py +1 -1
- fmtr_tools-1.3.48/fmtr/tools/datetime_tools.py +0 -5
- fmtr_tools-1.3.48/fmtr/tools/tabular_tools.py +0 -7
- fmtr_tools-1.3.48/fmtr/tools/version +0 -1
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/LICENSE +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/README.md +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/ai_tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/ai_tools/agentic_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/ai_tools/inference_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/api_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/async_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/augmentation_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/caching_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/constants.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/context_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/data_modelling_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/database_tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/dataclass_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/datatype_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/debugging_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/dns_tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/dns_tools/client.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/dns_tools/dm.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/dns_tools/proxy.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/dns_tools/server.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/docker_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/entrypoints/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/entrypoints/cache_hfh.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/entrypoints/ep_test.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/entrypoints/install_yamlscript.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/entrypoints/remote_debug_test.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/entrypoints/shell_debug.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/environment_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/function_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/google_api_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/hash_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/hfh_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/html_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/http_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/import_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/inherit_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/inspection_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/interface_tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/interface_tools/context.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/interface_tools/controls.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/interface_tools/interface_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/json_fix_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/json_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/logging_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/merging_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/metric_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/name_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/netrc_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/openai_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/packaging_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/parallel_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/path_tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/path_tools/app_path_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/path_tools/type_path_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/pattern_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/platform_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/process_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/profiling_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/random_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/semantic_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/settings_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/setup_tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/setup_tools/setup_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/spaces_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/string_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/conftest.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/helpers.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/test_datatype.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/test_environment.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/test_json.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/test_path.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tests/test_yaml.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tokenization_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/unicode_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/version_tools/__init__.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/version_tools/version_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/webhook_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr/tools/yaml_tools.py +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr.tools.egg-info/SOURCES.txt +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr.tools.egg-info/dependency_links.txt +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr.tools.egg-info/entry_points.txt +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/fmtr.tools.egg-info/top_level.txt +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/pyproject.toml +0 -0
- {fmtr_tools-1.3.48 → fmtr_tools-1.3.50}/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.50
|
|
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
|
|
@@ -81,16 +81,19 @@ Requires-Dist: pandas; extra == "semantic"
|
|
|
81
81
|
Requires-Dist: tabulate; extra == "semantic"
|
|
82
82
|
Requires-Dist: openpyxl; extra == "semantic"
|
|
83
83
|
Requires-Dist: odfpy; extra == "semantic"
|
|
84
|
+
Requires-Dist: deepdiff; extra == "semantic"
|
|
84
85
|
Provides-Extra: metric
|
|
85
86
|
Requires-Dist: pandas; extra == "metric"
|
|
86
87
|
Requires-Dist: tabulate; extra == "metric"
|
|
87
88
|
Requires-Dist: openpyxl; extra == "metric"
|
|
88
89
|
Requires-Dist: odfpy; extra == "metric"
|
|
90
|
+
Requires-Dist: deepdiff; extra == "metric"
|
|
89
91
|
Provides-Extra: tabular
|
|
90
92
|
Requires-Dist: pandas; extra == "tabular"
|
|
91
93
|
Requires-Dist: tabulate; extra == "tabular"
|
|
92
94
|
Requires-Dist: openpyxl; extra == "tabular"
|
|
93
95
|
Requires-Dist: odfpy; extra == "tabular"
|
|
96
|
+
Requires-Dist: deepdiff; extra == "tabular"
|
|
94
97
|
Provides-Extra: html
|
|
95
98
|
Requires-Dist: html2text; extra == "html"
|
|
96
99
|
Provides-Extra: interface
|
|
@@ -151,67 +154,68 @@ Provides-Extra: db-document
|
|
|
151
154
|
Requires-Dist: beanie[odm]; extra == "db-document"
|
|
152
155
|
Requires-Dist: motor; extra == "db-document"
|
|
153
156
|
Provides-Extra: all
|
|
154
|
-
Requires-Dist:
|
|
155
|
-
Requires-Dist:
|
|
156
|
-
Requires-Dist:
|
|
157
|
-
Requires-Dist:
|
|
157
|
+
Requires-Dist: flet[all]; extra == "all"
|
|
158
|
+
Requires-Dist: regex; extra == "all"
|
|
159
|
+
Requires-Dist: distributed; extra == "all"
|
|
160
|
+
Requires-Dist: tokenizers; extra == "all"
|
|
161
|
+
Requires-Dist: pydantic-extra-types; extra == "all"
|
|
162
|
+
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
158
163
|
Requires-Dist: sentence_transformers; extra == "all"
|
|
159
|
-
Requires-Dist: motor; extra == "all"
|
|
160
|
-
Requires-Dist: torchvision; extra == "all"
|
|
161
|
-
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
162
164
|
Requires-Dist: json_repair; extra == "all"
|
|
165
|
+
Requires-Dist: Unidecode; extra == "all"
|
|
166
|
+
Requires-Dist: google-auth; extra == "all"
|
|
167
|
+
Requires-Dist: pydantic-settings; extra == "all"
|
|
163
168
|
Requires-Dist: flet-video; extra == "all"
|
|
169
|
+
Requires-Dist: fastapi; extra == "all"
|
|
170
|
+
Requires-Dist: pyyaml; extra == "all"
|
|
171
|
+
Requires-Dist: huggingface_hub; extra == "all"
|
|
172
|
+
Requires-Dist: dnspython[doh]; extra == "all"
|
|
173
|
+
Requires-Dist: motor; extra == "all"
|
|
174
|
+
Requires-Dist: semver; extra == "all"
|
|
175
|
+
Requires-Dist: openai; extra == "all"
|
|
176
|
+
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
177
|
+
Requires-Dist: pandas; extra == "all"
|
|
178
|
+
Requires-Dist: diskcache; extra == "all"
|
|
179
|
+
Requires-Dist: bokeh; extra == "all"
|
|
180
|
+
Requires-Dist: google-api-python-client; extra == "all"
|
|
181
|
+
Requires-Dist: deepmerge; extra == "all"
|
|
182
|
+
Requires-Dist: torchaudio; extra == "all"
|
|
183
|
+
Requires-Dist: contexttimer; extra == "all"
|
|
164
184
|
Requires-Dist: pycountry; extra == "all"
|
|
165
|
-
Requires-Dist:
|
|
185
|
+
Requires-Dist: pymupdf; extra == "all"
|
|
186
|
+
Requires-Dist: logfire; extra == "all"
|
|
187
|
+
Requires-Dist: httpx_retries; extra == "all"
|
|
166
188
|
Requires-Dist: beanie[odm]; extra == "all"
|
|
167
|
-
Requires-Dist: yamlscript; extra == "all"
|
|
168
|
-
Requires-Dist: appdirs; extra == "all"
|
|
169
|
-
Requires-Dist: pydantic-settings; extra == "all"
|
|
170
189
|
Requires-Dist: httpx; extra == "all"
|
|
171
|
-
Requires-Dist:
|
|
172
|
-
Requires-Dist:
|
|
173
|
-
Requires-Dist:
|
|
174
|
-
Requires-Dist:
|
|
175
|
-
Requires-Dist:
|
|
176
|
-
Requires-Dist:
|
|
177
|
-
Requires-Dist:
|
|
190
|
+
Requires-Dist: deepdiff; extra == "all"
|
|
191
|
+
Requires-Dist: ollama; extra == "all"
|
|
192
|
+
Requires-Dist: filetype; extra == "all"
|
|
193
|
+
Requires-Dist: torchvision; extra == "all"
|
|
194
|
+
Requires-Dist: sre_yield; extra == "all"
|
|
195
|
+
Requires-Dist: appdirs; extra == "all"
|
|
196
|
+
Requires-Dist: setuptools; extra == "all"
|
|
197
|
+
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
|
|
198
|
+
Requires-Dist: yamlscript; extra == "all"
|
|
178
199
|
Requires-Dist: tinynetrc; extra == "all"
|
|
179
|
-
Requires-Dist:
|
|
180
|
-
Requires-Dist:
|
|
181
|
-
Requires-Dist: distributed; extra == "all"
|
|
182
|
-
Requires-Dist: flet[all]; extra == "all"
|
|
183
|
-
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
184
|
-
Requires-Dist: diskcache; extra == "all"
|
|
185
|
-
Requires-Dist: peft; extra == "all"
|
|
200
|
+
Requires-Dist: faker; extra == "all"
|
|
201
|
+
Requires-Dist: flet-webview; extra == "all"
|
|
186
202
|
Requires-Dist: pytest-cov; extra == "all"
|
|
187
|
-
Requires-Dist: pandas; extra == "all"
|
|
188
203
|
Requires-Dist: logfire[httpx]; extra == "all"
|
|
189
|
-
Requires-Dist:
|
|
190
|
-
Requires-Dist: google-auth; extra == "all"
|
|
191
|
-
Requires-Dist: pyyaml; extra == "all"
|
|
192
|
-
Requires-Dist: pymupdf4llm; extra == "all"
|
|
193
|
-
Requires-Dist: ollama; extra == "all"
|
|
194
|
-
Requires-Dist: openai; extra == "all"
|
|
195
|
-
Requires-Dist: tokenizers; extra == "all"
|
|
196
|
-
Requires-Dist: pymupdf; extra == "all"
|
|
197
|
-
Requires-Dist: httpx_retries; extra == "all"
|
|
198
|
-
Requires-Dist: pydantic-extra-types; extra == "all"
|
|
199
|
-
Requires-Dist: Unidecode; extra == "all"
|
|
204
|
+
Requires-Dist: dask[bag]; extra == "all"
|
|
200
205
|
Requires-Dist: openpyxl; extra == "all"
|
|
201
|
-
Requires-Dist:
|
|
206
|
+
Requires-Dist: playwright; extra == "all"
|
|
207
|
+
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
208
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
209
|
+
Requires-Dist: peft; extra == "all"
|
|
210
|
+
Requires-Dist: docker; extra == "all"
|
|
211
|
+
Requires-Dist: pydantic; extra == "all"
|
|
202
212
|
Requires-Dist: odfpy; extra == "all"
|
|
213
|
+
Requires-Dist: pymupdf4llm; extra == "all"
|
|
203
214
|
Requires-Dist: cachetools; extra == "all"
|
|
204
|
-
Requires-Dist: dask[bag]; extra == "all"
|
|
205
|
-
Requires-Dist: deepmerge; extra == "all"
|
|
206
|
-
Requires-Dist: fastapi; extra == "all"
|
|
207
|
-
Requires-Dist: google-api-python-client; extra == "all"
|
|
208
|
-
Requires-Dist: semver; extra == "all"
|
|
209
|
-
Requires-Dist: tabulate; extra == "all"
|
|
210
|
-
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
211
|
-
Requires-Dist: setuptools; extra == "all"
|
|
212
|
-
Requires-Dist: docker; extra == "all"
|
|
213
|
-
Requires-Dist: playwright; extra == "all"
|
|
214
215
|
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
216
|
+
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
217
|
+
Requires-Dist: html2text; extra == "all"
|
|
218
|
+
Requires-Dist: tabulate; extra == "all"
|
|
215
219
|
Dynamic: author
|
|
216
220
|
Dynamic: author-email
|
|
217
221
|
Dynamic: description
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import beanie
|
|
2
1
|
from functools import cached_property
|
|
3
|
-
from motor.motor_asyncio import AsyncIOMotorClient
|
|
4
2
|
from typing import List
|
|
5
3
|
|
|
4
|
+
import beanie
|
|
5
|
+
from motor.motor_asyncio import AsyncIOMotorClient
|
|
6
|
+
|
|
6
7
|
from fmtr.tools.constants import Constants
|
|
7
8
|
|
|
8
9
|
|
|
@@ -22,7 +23,7 @@ class Client:
|
|
|
22
23
|
self.port = port
|
|
23
24
|
self.documents = documents
|
|
24
25
|
|
|
25
|
-
self.client = AsyncIOMotorClient(self.uri)
|
|
26
|
+
self.client = AsyncIOMotorClient(self.uri, tz_aware=True)
|
|
26
27
|
self.db = self.client[self.name]
|
|
27
28
|
|
|
28
29
|
@cached_property
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
from functools import lru_cache
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def now() -> datetime:
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
Now UTC
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
return datetime.now(tz=timezone.utc)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@lru_cache
|
|
15
|
+
def min() -> datetime:
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
Min UTC
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
return now().min
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@lru_cache
|
|
25
|
+
def max():
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
Max UTC
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
return now().max
|
|
@@ -145,6 +145,32 @@ class Path(type(Path())):
|
|
|
145
145
|
"""
|
|
146
146
|
return self.mkdir(parents=True, exist_ok=True)
|
|
147
147
|
|
|
148
|
+
def with_suffix(self, suffix: str) -> 'Path':
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
Pathlib doesn't add a dot prefix, but then errors if you don't provide one, which feels rather obnoxious.
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
if not suffix.startswith('.'):
|
|
155
|
+
suffix = f'.{suffix}'
|
|
156
|
+
return super().with_suffix(suffix)
|
|
157
|
+
|
|
158
|
+
def get_conversion_path(self, suffix: str) -> 'Path':
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
Fetch the equivalent path for a different format in the standard conversion directory structure.
|
|
162
|
+
.../xyz/filename.xyx -> ../abc/filename.abc
|
|
163
|
+
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
old_dir = self.parent.name
|
|
167
|
+
|
|
168
|
+
if old_dir != self.suffix.removeprefix('.'):
|
|
169
|
+
raise ValueError(f"Expected parent directory '{old_dir}' to match file extension '{suffix}'")
|
|
170
|
+
|
|
171
|
+
new = self.parent.parent / suffix / f'{self.stem}.{suffix}'
|
|
172
|
+
return new
|
|
173
|
+
|
|
148
174
|
@property
|
|
149
175
|
def exist(self):
|
|
150
176
|
"""
|
|
@@ -179,6 +179,20 @@ class Document(pm.Document):
|
|
|
179
179
|
"""
|
|
180
180
|
return pymupdf4llm.to_markdown(self, **kwargs)
|
|
181
181
|
|
|
182
|
+
def to_text(self):
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
Simple text output.
|
|
186
|
+
|
|
187
|
+
"""
|
|
188
|
+
lines = []
|
|
189
|
+
for page in self:
|
|
190
|
+
text = page.get_text()
|
|
191
|
+
lines.append(text)
|
|
192
|
+
|
|
193
|
+
text = '\n'.join(lines)
|
|
194
|
+
return text
|
|
195
|
+
|
|
182
196
|
|
|
183
197
|
if __name__ == '__main__':
|
|
184
198
|
from fmtr.tools.path_tools import Path
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import deepdiff
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
from fmtr.tools.iterator_tools import dedupe
|
|
6
|
+
|
|
7
|
+
Table = DataFrame = pd.DataFrame
|
|
8
|
+
Series = pd.Series
|
|
9
|
+
|
|
10
|
+
nan = np.nan
|
|
11
|
+
|
|
12
|
+
CONCAT_HORIZONTALLY = 1
|
|
13
|
+
CONCAT_VERTICALLY = 0
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def normalize_nan(df, value=np.nan):
|
|
17
|
+
return df.replace({pd.NA: value, None: value, np.nan: value})
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Differ:
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
Diff two dataframes via DeepDiff, after shape normalization, datatype simplification, etc.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, left: Table, right: Table):
|
|
28
|
+
|
|
29
|
+
self.cols = dedupe(left.columns.tolist() + right.columns.tolist())
|
|
30
|
+
self.rows = dedupe(left.index.values.tolist() + right.index.values.tolist())
|
|
31
|
+
self.left = self.process(left)
|
|
32
|
+
self.right = self.process(right)
|
|
33
|
+
self.dfs = [self.left, self.right]
|
|
34
|
+
|
|
35
|
+
def process(self, df: Table) -> Table:
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
Ensure same rows/columns, plus simplify datatypes via JSON round-robin.
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
df_rows = set(df.index.values.tolist())
|
|
43
|
+
for row in self.rows:
|
|
44
|
+
if row in df_rows:
|
|
45
|
+
continue
|
|
46
|
+
df.loc[len(df)] = None
|
|
47
|
+
|
|
48
|
+
df_cols = set(df.columns.tolist())
|
|
49
|
+
for col in self.cols:
|
|
50
|
+
if col in df_cols:
|
|
51
|
+
continue
|
|
52
|
+
df[col] = None
|
|
53
|
+
|
|
54
|
+
df = pd.read_json(df.to_json(date_format='iso'))
|
|
55
|
+
df = normalize_nan(df, value=None)
|
|
56
|
+
|
|
57
|
+
return df
|
|
58
|
+
|
|
59
|
+
def get_diff(self) -> deepdiff.DeepDiff:
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
Cast to dicts and get diff
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
dicts = [df.to_dict(orient='index') for df in self.dfs]
|
|
67
|
+
diff = deepdiff.DeepDiff(*dicts, ignore_order=True)
|
|
68
|
+
return diff
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.3.50
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmtr.tools
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.50
|
|
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
|
|
@@ -81,16 +81,19 @@ Requires-Dist: pandas; extra == "semantic"
|
|
|
81
81
|
Requires-Dist: tabulate; extra == "semantic"
|
|
82
82
|
Requires-Dist: openpyxl; extra == "semantic"
|
|
83
83
|
Requires-Dist: odfpy; extra == "semantic"
|
|
84
|
+
Requires-Dist: deepdiff; extra == "semantic"
|
|
84
85
|
Provides-Extra: metric
|
|
85
86
|
Requires-Dist: pandas; extra == "metric"
|
|
86
87
|
Requires-Dist: tabulate; extra == "metric"
|
|
87
88
|
Requires-Dist: openpyxl; extra == "metric"
|
|
88
89
|
Requires-Dist: odfpy; extra == "metric"
|
|
90
|
+
Requires-Dist: deepdiff; extra == "metric"
|
|
89
91
|
Provides-Extra: tabular
|
|
90
92
|
Requires-Dist: pandas; extra == "tabular"
|
|
91
93
|
Requires-Dist: tabulate; extra == "tabular"
|
|
92
94
|
Requires-Dist: openpyxl; extra == "tabular"
|
|
93
95
|
Requires-Dist: odfpy; extra == "tabular"
|
|
96
|
+
Requires-Dist: deepdiff; extra == "tabular"
|
|
94
97
|
Provides-Extra: html
|
|
95
98
|
Requires-Dist: html2text; extra == "html"
|
|
96
99
|
Provides-Extra: interface
|
|
@@ -151,67 +154,68 @@ Provides-Extra: db-document
|
|
|
151
154
|
Requires-Dist: beanie[odm]; extra == "db-document"
|
|
152
155
|
Requires-Dist: motor; extra == "db-document"
|
|
153
156
|
Provides-Extra: all
|
|
154
|
-
Requires-Dist:
|
|
155
|
-
Requires-Dist:
|
|
156
|
-
Requires-Dist:
|
|
157
|
-
Requires-Dist:
|
|
157
|
+
Requires-Dist: flet[all]; extra == "all"
|
|
158
|
+
Requires-Dist: regex; extra == "all"
|
|
159
|
+
Requires-Dist: distributed; extra == "all"
|
|
160
|
+
Requires-Dist: tokenizers; extra == "all"
|
|
161
|
+
Requires-Dist: pydantic-extra-types; extra == "all"
|
|
162
|
+
Requires-Dist: transformers[sentencepiece]; extra == "all"
|
|
158
163
|
Requires-Dist: sentence_transformers; extra == "all"
|
|
159
|
-
Requires-Dist: motor; extra == "all"
|
|
160
|
-
Requires-Dist: torchvision; extra == "all"
|
|
161
|
-
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
162
164
|
Requires-Dist: json_repair; extra == "all"
|
|
165
|
+
Requires-Dist: Unidecode; extra == "all"
|
|
166
|
+
Requires-Dist: google-auth; extra == "all"
|
|
167
|
+
Requires-Dist: pydantic-settings; extra == "all"
|
|
163
168
|
Requires-Dist: flet-video; extra == "all"
|
|
169
|
+
Requires-Dist: fastapi; extra == "all"
|
|
170
|
+
Requires-Dist: pyyaml; extra == "all"
|
|
171
|
+
Requires-Dist: huggingface_hub; extra == "all"
|
|
172
|
+
Requires-Dist: dnspython[doh]; extra == "all"
|
|
173
|
+
Requires-Dist: motor; extra == "all"
|
|
174
|
+
Requires-Dist: semver; extra == "all"
|
|
175
|
+
Requires-Dist: openai; extra == "all"
|
|
176
|
+
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
177
|
+
Requires-Dist: pandas; extra == "all"
|
|
178
|
+
Requires-Dist: diskcache; extra == "all"
|
|
179
|
+
Requires-Dist: bokeh; extra == "all"
|
|
180
|
+
Requires-Dist: google-api-python-client; extra == "all"
|
|
181
|
+
Requires-Dist: deepmerge; extra == "all"
|
|
182
|
+
Requires-Dist: torchaudio; extra == "all"
|
|
183
|
+
Requires-Dist: contexttimer; extra == "all"
|
|
164
184
|
Requires-Dist: pycountry; extra == "all"
|
|
165
|
-
Requires-Dist:
|
|
185
|
+
Requires-Dist: pymupdf; extra == "all"
|
|
186
|
+
Requires-Dist: logfire; extra == "all"
|
|
187
|
+
Requires-Dist: httpx_retries; extra == "all"
|
|
166
188
|
Requires-Dist: beanie[odm]; extra == "all"
|
|
167
|
-
Requires-Dist: yamlscript; extra == "all"
|
|
168
|
-
Requires-Dist: appdirs; extra == "all"
|
|
169
|
-
Requires-Dist: pydantic-settings; extra == "all"
|
|
170
189
|
Requires-Dist: httpx; extra == "all"
|
|
171
|
-
Requires-Dist:
|
|
172
|
-
Requires-Dist:
|
|
173
|
-
Requires-Dist:
|
|
174
|
-
Requires-Dist:
|
|
175
|
-
Requires-Dist:
|
|
176
|
-
Requires-Dist:
|
|
177
|
-
Requires-Dist:
|
|
190
|
+
Requires-Dist: deepdiff; extra == "all"
|
|
191
|
+
Requires-Dist: ollama; extra == "all"
|
|
192
|
+
Requires-Dist: filetype; extra == "all"
|
|
193
|
+
Requires-Dist: torchvision; extra == "all"
|
|
194
|
+
Requires-Dist: sre_yield; extra == "all"
|
|
195
|
+
Requires-Dist: appdirs; extra == "all"
|
|
196
|
+
Requires-Dist: setuptools; extra == "all"
|
|
197
|
+
Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
|
|
198
|
+
Requires-Dist: yamlscript; extra == "all"
|
|
178
199
|
Requires-Dist: tinynetrc; extra == "all"
|
|
179
|
-
Requires-Dist:
|
|
180
|
-
Requires-Dist:
|
|
181
|
-
Requires-Dist: distributed; extra == "all"
|
|
182
|
-
Requires-Dist: flet[all]; extra == "all"
|
|
183
|
-
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
184
|
-
Requires-Dist: diskcache; extra == "all"
|
|
185
|
-
Requires-Dist: peft; extra == "all"
|
|
200
|
+
Requires-Dist: faker; extra == "all"
|
|
201
|
+
Requires-Dist: flet-webview; extra == "all"
|
|
186
202
|
Requires-Dist: pytest-cov; extra == "all"
|
|
187
|
-
Requires-Dist: pandas; extra == "all"
|
|
188
203
|
Requires-Dist: logfire[httpx]; extra == "all"
|
|
189
|
-
Requires-Dist:
|
|
190
|
-
Requires-Dist: google-auth; extra == "all"
|
|
191
|
-
Requires-Dist: pyyaml; extra == "all"
|
|
192
|
-
Requires-Dist: pymupdf4llm; extra == "all"
|
|
193
|
-
Requires-Dist: ollama; extra == "all"
|
|
194
|
-
Requires-Dist: openai; extra == "all"
|
|
195
|
-
Requires-Dist: tokenizers; extra == "all"
|
|
196
|
-
Requires-Dist: pymupdf; extra == "all"
|
|
197
|
-
Requires-Dist: httpx_retries; extra == "all"
|
|
198
|
-
Requires-Dist: pydantic-extra-types; extra == "all"
|
|
199
|
-
Requires-Dist: Unidecode; extra == "all"
|
|
204
|
+
Requires-Dist: dask[bag]; extra == "all"
|
|
200
205
|
Requires-Dist: openpyxl; extra == "all"
|
|
201
|
-
Requires-Dist:
|
|
206
|
+
Requires-Dist: playwright; extra == "all"
|
|
207
|
+
Requires-Dist: google-auth-httplib2; extra == "all"
|
|
208
|
+
Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
|
|
209
|
+
Requires-Dist: peft; extra == "all"
|
|
210
|
+
Requires-Dist: docker; extra == "all"
|
|
211
|
+
Requires-Dist: pydantic; extra == "all"
|
|
202
212
|
Requires-Dist: odfpy; extra == "all"
|
|
213
|
+
Requires-Dist: pymupdf4llm; extra == "all"
|
|
203
214
|
Requires-Dist: cachetools; extra == "all"
|
|
204
|
-
Requires-Dist: dask[bag]; extra == "all"
|
|
205
|
-
Requires-Dist: deepmerge; extra == "all"
|
|
206
|
-
Requires-Dist: fastapi; extra == "all"
|
|
207
|
-
Requires-Dist: google-api-python-client; extra == "all"
|
|
208
|
-
Requires-Dist: semver; extra == "all"
|
|
209
|
-
Requires-Dist: tabulate; extra == "all"
|
|
210
|
-
Requires-Dist: logfire[fastapi]; extra == "all"
|
|
211
|
-
Requires-Dist: setuptools; extra == "all"
|
|
212
|
-
Requires-Dist: docker; extra == "all"
|
|
213
|
-
Requires-Dist: playwright; extra == "all"
|
|
214
215
|
Requires-Dist: uvicorn[standard]; extra == "all"
|
|
216
|
+
Requires-Dist: google-auth-oauthlib; extra == "all"
|
|
217
|
+
Requires-Dist: html2text; extra == "all"
|
|
218
|
+
Requires-Dist: tabulate; extra == "all"
|
|
215
219
|
Dynamic: author
|
|
216
220
|
Dynamic: author-email
|
|
217
221
|
Dynamic: description
|
|
@@ -18,67 +18,68 @@ pydantic-ai[logfire,openai]
|
|
|
18
18
|
ollama
|
|
19
19
|
|
|
20
20
|
[all]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
flet[all]
|
|
22
|
+
regex
|
|
23
|
+
distributed
|
|
24
|
+
tokenizers
|
|
25
|
+
pydantic-extra-types
|
|
26
|
+
transformers[sentencepiece]
|
|
25
27
|
sentence_transformers
|
|
26
|
-
motor
|
|
27
|
-
torchvision
|
|
28
|
-
google-auth-oauthlib
|
|
29
28
|
json_repair
|
|
29
|
+
Unidecode
|
|
30
|
+
google-auth
|
|
31
|
+
pydantic-settings
|
|
30
32
|
flet-video
|
|
33
|
+
fastapi
|
|
34
|
+
pyyaml
|
|
35
|
+
huggingface_hub
|
|
36
|
+
dnspython[doh]
|
|
37
|
+
motor
|
|
38
|
+
semver
|
|
39
|
+
openai
|
|
40
|
+
logfire[fastapi]
|
|
41
|
+
pandas
|
|
42
|
+
diskcache
|
|
43
|
+
bokeh
|
|
44
|
+
google-api-python-client
|
|
45
|
+
deepmerge
|
|
46
|
+
torchaudio
|
|
47
|
+
contexttimer
|
|
31
48
|
pycountry
|
|
32
|
-
|
|
49
|
+
pymupdf
|
|
50
|
+
logfire
|
|
51
|
+
httpx_retries
|
|
33
52
|
beanie[odm]
|
|
34
|
-
yamlscript
|
|
35
|
-
appdirs
|
|
36
|
-
pydantic-settings
|
|
37
53
|
httpx
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
54
|
+
deepdiff
|
|
55
|
+
ollama
|
|
56
|
+
filetype
|
|
57
|
+
torchvision
|
|
58
|
+
sre_yield
|
|
59
|
+
appdirs
|
|
60
|
+
setuptools
|
|
61
|
+
pydevd-pycharm~=251.25410.159
|
|
62
|
+
yamlscript
|
|
45
63
|
tinynetrc
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
distributed
|
|
49
|
-
flet[all]
|
|
50
|
-
pydantic-ai[logfire,openai]
|
|
51
|
-
diskcache
|
|
52
|
-
peft
|
|
64
|
+
faker
|
|
65
|
+
flet-webview
|
|
53
66
|
pytest-cov
|
|
54
|
-
pandas
|
|
55
67
|
logfire[httpx]
|
|
56
|
-
|
|
57
|
-
google-auth
|
|
58
|
-
pyyaml
|
|
59
|
-
pymupdf4llm
|
|
60
|
-
ollama
|
|
61
|
-
openai
|
|
62
|
-
tokenizers
|
|
63
|
-
pymupdf
|
|
64
|
-
httpx_retries
|
|
65
|
-
pydantic-extra-types
|
|
66
|
-
Unidecode
|
|
68
|
+
dask[bag]
|
|
67
69
|
openpyxl
|
|
68
|
-
|
|
70
|
+
playwright
|
|
71
|
+
google-auth-httplib2
|
|
72
|
+
pydantic-ai[logfire,openai]
|
|
73
|
+
peft
|
|
74
|
+
docker
|
|
75
|
+
pydantic
|
|
69
76
|
odfpy
|
|
77
|
+
pymupdf4llm
|
|
70
78
|
cachetools
|
|
71
|
-
dask[bag]
|
|
72
|
-
deepmerge
|
|
73
|
-
fastapi
|
|
74
|
-
google-api-python-client
|
|
75
|
-
semver
|
|
76
|
-
tabulate
|
|
77
|
-
logfire[fastapi]
|
|
78
|
-
setuptools
|
|
79
|
-
docker
|
|
80
|
-
playwright
|
|
81
79
|
uvicorn[standard]
|
|
80
|
+
google-auth-oauthlib
|
|
81
|
+
html2text
|
|
82
|
+
tabulate
|
|
82
83
|
|
|
83
84
|
[api]
|
|
84
85
|
fastapi
|
|
@@ -161,6 +162,7 @@ pandas
|
|
|
161
162
|
tabulate
|
|
162
163
|
openpyxl
|
|
163
164
|
odfpy
|
|
165
|
+
deepdiff
|
|
164
166
|
|
|
165
167
|
[netrc]
|
|
166
168
|
tinynetrc
|
|
@@ -201,6 +203,7 @@ pandas
|
|
|
201
203
|
tabulate
|
|
202
204
|
openpyxl
|
|
203
205
|
odfpy
|
|
206
|
+
deepdiff
|
|
204
207
|
|
|
205
208
|
[sets]
|
|
206
209
|
pydantic-settings
|
|
@@ -221,6 +224,7 @@ pandas
|
|
|
221
224
|
tabulate
|
|
222
225
|
openpyxl
|
|
223
226
|
odfpy
|
|
227
|
+
deepdiff
|
|
224
228
|
|
|
225
229
|
[test]
|
|
226
230
|
pytest-cov
|
|
@@ -26,7 +26,7 @@ DEPENDENCIES = {
|
|
|
26
26
|
'json-fix': ['json_repair'],
|
|
27
27
|
'semantic': ['sentence_transformers', 'metric'],
|
|
28
28
|
'metric': ['tabular'],
|
|
29
|
-
'tabular': ['pandas', 'tabulate', 'openpyxl', 'odfpy'],
|
|
29
|
+
'tabular': ['pandas', 'tabulate', 'openpyxl', 'odfpy', 'deepdiff'],
|
|
30
30
|
'html': ['html2text'],
|
|
31
31
|
'interface': ['flet[all]', 'flet-video', 'flet-webview'],
|
|
32
32
|
'google.api': ['google-auth', 'google-auth-oauthlib', 'google-auth-httplib2', 'google-api-python-client'],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.3.48
|
|
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
|