fmtr.tools 1.1.26__py3-none-any.whl → 1.1.28__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fmtr.tools might be problematic. Click here for more details.

fmtr/tools/constants.py CHANGED
@@ -35,3 +35,7 @@ class Constants:
35
35
  DIR_NAME_SOURCE = 'source'
36
36
  FILENAME_VERSION = 'version'
37
37
  DIR_NAME_HF = 'hf'
38
+
39
+ ENTRYPOINTS_DIR = 'entrypoints'
40
+ PACKAGE_EXCLUDE_DIRS = {'data', 'build', 'dist', '.*', '*egg-info*'}
41
+ INIT_FILENAME = '__init__.py'
@@ -1,5 +1,6 @@
1
1
  import sys
2
2
  from datetime import datetime
3
+ from fnmatch import fnmatch
3
4
  from functools import cached_property
4
5
  from itertools import chain
5
6
  from typing import List, Dict
@@ -40,20 +41,22 @@ class SetupPaths(FromCallerMixin):
40
41
  @cached_property
41
42
  def path(self):
42
43
 
43
- from fmtr.tools import setup
44
-
45
- if self.org:
44
+ if self.is_namespace:
46
45
  base = self.org
47
46
  else:
48
47
  base = self.repo
49
48
 
50
- directories = [base / dir for dir in setup.find_packages(base)]
49
+ packages = [
50
+ dir for dir in base.iterdir()
51
+ if (dir / Constants.INIT_FILENAME).is_file()
52
+ and not any(fnmatch(dir.name, pattern) for pattern in Constants.PACKAGE_EXCLUDE_DIRS)
53
+ ]
51
54
 
52
- if len(directories) != 1:
53
- dirs_str = ', '.join([str(dir) for dir in directories])
54
- raise ValueError(f'Expected exactly one directory in {self.repo}, found {dirs_str}')
55
+ if len(packages) != 1:
56
+ dirs_str = ', '.join([str(dir) for dir in packages])
57
+ raise ValueError(f'Expected exactly one package in {self.repo}, found {dirs_str}')
55
58
 
56
- package = next(iter(directories))
59
+ package = next(iter(packages))
57
60
  return package
58
61
 
59
62
  @property
@@ -65,6 +68,10 @@ class SetupPaths(FromCallerMixin):
65
68
  return False
66
69
  return org
67
70
 
71
+ @property
72
+ def entrypoints(self):
73
+ return self.path / Constants.ENTRYPOINTS_DIR
74
+
68
75
  @property
69
76
  def is_namespace(self) -> bool:
70
77
  return bool(self.org)
@@ -79,9 +86,13 @@ class Setup(FromCallerMixin):
79
86
  AUTHOR_EMAIL = 'innovative.fowler@mask.pro.fmtr.dev'
80
87
 
81
88
  REQUIREMENTS_ARG = 'requirements'
82
- SKIP_DIRS = {'data', 'build', 'dist', '.*', '*egg-info*'}
83
89
 
84
- def __init__(self, dependencies, paths=None, org=Constants.ORG_NAME, console_scripts=None, client=None, do_setup=True, **kwargs):
90
+ ENTRYPOINT_COMMAND_SEP = '-'
91
+ ENTRYPOINT_FUNCTION_SEP = '_'
92
+ ENTRYPOINT_FUNC_NAME = 'main'
93
+
94
+ def __init__(self, dependencies, paths=None, org=Constants.ORG_NAME, client=None, do_setup=True, **kwargs):
95
+
85
96
 
86
97
  self.kwargs = kwargs
87
98
 
@@ -102,7 +113,7 @@ class Setup(FromCallerMixin):
102
113
  self.paths = paths
103
114
 
104
115
  self.client = client
105
- self.console_scripts = console_scripts
116
+
106
117
 
107
118
  if do_setup:
108
119
  self.setup()
@@ -124,27 +135,26 @@ class Setup(FromCallerMixin):
124
135
  reqs = '\n'.join(reqs)
125
136
  print(reqs)
126
137
 
138
+ @property
139
+ def console_scripts(self):
127
140
 
141
+ if not self.paths.entrypoints.exists():
142
+ return {}
128
143
 
129
- def get_entrypoint_path(self, key, value):
130
- if value:
131
- return f'{self.name}.{value}:{key}'
132
- else:
133
- return f'{self.name}:{key}'
144
+ names_mods = [path.stem for path in self.paths.entrypoints.iterdir() if path.is_file() and not path.stem.startswith('_')]
145
+ command_prefix = self.name.replace('.', self.ENTRYPOINT_COMMAND_SEP)
146
+ command_suffixes = [name_mod.replace(self.ENTRYPOINT_FUNCTION_SEP, self.ENTRYPOINT_COMMAND_SEP) for name_mod in names_mods]
147
+ commands = [f'{command_prefix}-{command_suffix}' for command_suffix in command_suffixes]
148
+ paths = [f'{self.name}.{Constants.ENTRYPOINTS_DIR}.{name_mod}:{self.ENTRYPOINT_FUNC_NAME}' for name_mod in names_mods]
134
149
 
135
- @property
136
- def entrypoints(self):
137
- if self.console_scripts:
138
- return dict(
139
- console_scripts=[f'{key} = {self.get_entrypoint_path(key, value)}' for key, value in self.console_scripts.items()],
140
- )
141
- else:
142
- return dict()
150
+ console_scripts = [f'{command} = {path}' for command, path in zip(commands, paths)]
151
+
152
+ return console_scripts
143
153
 
144
154
  @property
145
155
  def name(self):
146
156
  if self.paths.is_namespace:
147
- return f'{self.paths.org}.{self.paths.name}'
157
+ return f'{self.paths.org_name}.{self.paths.name}'
148
158
  return self.paths.name
149
159
 
150
160
  @property
@@ -180,9 +190,7 @@ class Setup(FromCallerMixin):
180
190
 
181
191
  @property
182
192
  def packages(self):
183
-
184
- excludes = list(self.SKIP_DIRS) + [f'{name}.*' for name in self.SKIP_DIRS if '*' not in name]
185
-
193
+ excludes = list(Constants.PACKAGE_EXCLUDE_DIRS) + [f'{name}.*' for name in Constants.PACKAGE_EXCLUDE_DIRS if '*' not in name]
186
194
  packages = self.find(where=str(self.paths.repo), exclude=excludes)
187
195
  return packages
188
196
 
@@ -199,7 +207,7 @@ class Setup(FromCallerMixin):
199
207
 
200
208
  @property
201
209
  def url(self):
202
- return f'https://github.com/{self.paths.org}/{self.paths.name}'
210
+ return f'https://github.com/{self.org}/{self.paths.name}'
203
211
 
204
212
  @property
205
213
  def data(self):
@@ -215,7 +223,9 @@ class Setup(FromCallerMixin):
215
223
  packages=self.packages,
216
224
  package_dir=self.package_dir,
217
225
  package_data=self.package_data,
218
- entry_points=self.entrypoints,
226
+ entry_points=dict(
227
+ console_scripts=self.console_scripts,
228
+ ),
219
229
  install_requires=self.dependencies.install,
220
230
  extras_require=self.dependencies.extras,
221
231
  ) | self.kwargs
@@ -280,7 +290,10 @@ class Dependencies:
280
290
 
281
291
  @cached_property
282
292
  def install(self):
283
- return self.resolve_values(self.INSTALL)
293
+ if self.INSTALL in self.dependencies:
294
+ return self.resolve_values(self.INSTALL)
295
+ else:
296
+ return []
284
297
 
285
298
 
286
299
  if __name__ == '__main__':
fmtr/tools/version CHANGED
@@ -1 +1 @@
1
- 1.1.26
1
+ 1.1.28
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.1.26
3
+ Version: 1.1.28
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
@@ -9,60 +9,60 @@ License: Copyright © 2025 Frontmatter. All rights reserved.
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Provides-Extra: test
12
+ Requires-Dist: setuptools; extra == "test"
13
+ Requires-Dist: httpx_retries; extra == "test"
14
+ Requires-Dist: flet-webview; extra == "test"
15
+ Requires-Dist: filetype; extra == "test"
16
+ Requires-Dist: httpx; extra == "test"
17
+ Requires-Dist: bokeh; extra == "test"
18
+ Requires-Dist: fastapi; extra == "test"
19
+ Requires-Dist: tabulate; extra == "test"
20
+ Requires-Dist: flet-video; extra == "test"
21
+ Requires-Dist: uvicorn[standard]; extra == "test"
22
+ Requires-Dist: logfire[httpx]; extra == "test"
23
+ Requires-Dist: logfire; extra == "test"
12
24
  Requires-Dist: torchaudio; extra == "test"
25
+ Requires-Dist: google-api-python-client; extra == "test"
26
+ Requires-Dist: yamlscript; extra == "test"
27
+ Requires-Dist: pydantic-ai[logfire,openai]; extra == "test"
13
28
  Requires-Dist: semver; extra == "test"
14
- Requires-Dist: docker; extra == "test"
15
- Requires-Dist: logfire; extra == "test"
29
+ Requires-Dist: html2text; extra == "test"
30
+ Requires-Dist: dnspython[doh]; extra == "test"
31
+ Requires-Dist: pydantic; extra == "test"
32
+ Requires-Dist: tokenizers; extra == "test"
33
+ Requires-Dist: deepmerge; extra == "test"
16
34
  Requires-Dist: ollama; extra == "test"
17
- Requires-Dist: openpyxl; extra == "test"
18
- Requires-Dist: flet[all]; extra == "test"
19
35
  Requires-Dist: diskcache; extra == "test"
36
+ Requires-Dist: google-auth-httplib2; extra == "test"
20
37
  Requires-Dist: pymupdf; extra == "test"
21
- Requires-Dist: pydevd-pycharm; extra == "test"
22
- Requires-Dist: filetype; extra == "test"
23
- Requires-Dist: sentence_transformers; extra == "test"
24
- Requires-Dist: peft; extra == "test"
25
- Requires-Dist: flet-video; extra == "test"
26
- Requires-Dist: appdirs; extra == "test"
27
- Requires-Dist: huggingface_hub; extra == "test"
28
- Requires-Dist: flet-webview; extra == "test"
29
- Requires-Dist: httpx; extra == "test"
30
- Requires-Dist: deepmerge; extra == "test"
38
+ Requires-Dist: tinynetrc; extra == "test"
31
39
  Requires-Dist: pytest-cov; extra == "test"
32
- Requires-Dist: dnspython[doh]; extra == "test"
33
40
  Requires-Dist: regex; extra == "test"
34
- Requires-Dist: openai; extra == "test"
35
- Requires-Dist: html2text; extra == "test"
36
- Requires-Dist: yamlscript; extra == "test"
37
- Requires-Dist: pydantic-settings; extra == "test"
38
- Requires-Dist: dask[bag]; extra == "test"
39
- Requires-Dist: tinynetrc; extra == "test"
40
- Requires-Dist: pandas; extra == "test"
41
- Requires-Dist: bokeh; extra == "test"
42
- Requires-Dist: uvicorn[standard]; extra == "test"
43
- Requires-Dist: torchvision; extra == "test"
44
- Requires-Dist: logfire[fastapi]; extra == "test"
45
- Requires-Dist: Unidecode; extra == "test"
46
- Requires-Dist: tabulate; extra == "test"
47
- Requires-Dist: distributed; extra == "test"
48
- Requires-Dist: tokenizers; extra == "test"
49
41
  Requires-Dist: faker; extra == "test"
50
- Requires-Dist: contexttimer; extra == "test"
51
- Requires-Dist: google-auth-oauthlib; extra == "test"
52
- Requires-Dist: fastapi; extra == "test"
53
- Requires-Dist: google-api-python-client; extra == "test"
54
- Requires-Dist: logfire[httpx]; extra == "test"
55
- Requires-Dist: json_repair; extra == "test"
56
- Requires-Dist: pymupdf4llm; extra == "test"
42
+ Requires-Dist: pydevd-pycharm; extra == "test"
57
43
  Requires-Dist: sre_yield; extra == "test"
58
- Requires-Dist: setuptools; extra == "test"
44
+ Requires-Dist: Unidecode; extra == "test"
45
+ Requires-Dist: pyyaml; extra == "test"
46
+ Requires-Dist: peft; extra == "test"
47
+ Requires-Dist: pymupdf4llm; extra == "test"
48
+ Requires-Dist: distributed; extra == "test"
59
49
  Requires-Dist: transformers[sentencepiece]; extra == "test"
60
- Requires-Dist: pydantic-ai[logfire,openai]; extra == "test"
61
- Requires-Dist: pydantic; extra == "test"
50
+ Requires-Dist: json_repair; extra == "test"
51
+ Requires-Dist: torchvision; extra == "test"
52
+ Requires-Dist: sentence_transformers; extra == "test"
62
53
  Requires-Dist: google-auth; extra == "test"
63
- Requires-Dist: pyyaml; extra == "test"
64
- Requires-Dist: google-auth-httplib2; extra == "test"
65
- Requires-Dist: httpx_retries; extra == "test"
54
+ Requires-Dist: google-auth-oauthlib; extra == "test"
55
+ Requires-Dist: pydantic-settings; extra == "test"
56
+ Requires-Dist: docker; extra == "test"
57
+ Requires-Dist: flet[all]; extra == "test"
58
+ Requires-Dist: contexttimer; extra == "test"
59
+ Requires-Dist: huggingface_hub; extra == "test"
60
+ Requires-Dist: pandas; extra == "test"
61
+ Requires-Dist: openai; extra == "test"
62
+ Requires-Dist: appdirs; extra == "test"
63
+ Requires-Dist: dask[bag]; extra == "test"
64
+ Requires-Dist: openpyxl; extra == "test"
65
+ Requires-Dist: logfire[fastapi]; extra == "test"
66
66
  Provides-Extra: yaml
67
67
  Requires-Dist: yamlscript; extra == "yaml"
68
68
  Requires-Dist: pyyaml; extra == "yaml"
@@ -4,7 +4,7 @@ fmtr/tools/async_tools.py,sha256=ewz757WcveQJd-G5SVr2JDOQVbdLGecCgl-tsBGVZz4,284
4
4
  fmtr/tools/augmentation_tools.py,sha256=-6ESbO4CDlKqVOV1J1V6qBeoBMzbFIinkDHRHnCBej0,55
5
5
  fmtr/tools/caching_tools.py,sha256=UOCYUNvLQ-NofR_dhqBmZF96-HRPf4At5MmxVk3gAIk,2943
6
6
  fmtr/tools/console_script_tools.py,sha256=7KVO0WI3Z7d7EZcmvTVS-O4OMxYYMZuA_7s0eubv76E,328
7
- fmtr/tools/constants.py,sha256=6RvZLlj0jrej0X7yz-03uu-ELSYWFGknjmb-iOcozm0,1208
7
+ fmtr/tools/constants.py,sha256=FOHvjovW_pHIvym9OXKZnztPvPVvudyG5S01i7XtXKE,1352
8
8
  fmtr/tools/data_modelling_tools.py,sha256=0BFm-F_cYzVTxftWQwORkPd0FM2BTLVh9-s0-rTTFoo,1744
9
9
  fmtr/tools/dataclass_tools.py,sha256=0Gt6KeLhtPgubo_2tYkIVqB8oQ91Qzag8OAGZDdjvMU,1209
10
10
  fmtr/tools/datatype_tools.py,sha256=3P4AWIFGkJ-UqvXlj0Jc9IvkIIgTOE9jRrOk3NVbpH8,1508
@@ -46,7 +46,7 @@ fmtr/tools/tabular_tools.py,sha256=tpIpZzYku1HcJrHZJL6BC39LmN3WUWVhFbK2N7nDVmE,1
46
46
  fmtr/tools/tokenization_tools.py,sha256=me-IBzSLyNYejLybwjO9CNB6Mj2NYfKPaOVThXyaGNg,4268
47
47
  fmtr/tools/tools.py,sha256=CAsApa1YwVdNE6H66Vjivs_mXYvOas3rh7fPELAnTpk,795
48
48
  fmtr/tools/unicode_tools.py,sha256=yS_9wpu8ogNoiIL7s1G_8bETFFO_YQlo4LNPv1NLDeY,52
49
- fmtr/tools/version,sha256=qdONjQrKG26HBKWvtcv7oRITgNwT9_551G27tbp2pgI,6
49
+ fmtr/tools/version,sha256=KZLQYWcj6yTAXH4Eaz7K860XWssMDypvIyHOQjYOv80,6
50
50
  fmtr/tools/version_tools.py,sha256=yNs_CGqWpqE4jbK9wsPIi14peJVXYbhIcMqHAFOw3yE,1480
51
51
  fmtr/tools/yaml_tools.py,sha256=9kuYChqJelWQIjGlSnK4iDdOWWH06P0gp9jIcRrC3UI,1903
52
52
  fmtr/tools/ai_tools/__init__.py,sha256=JZrLuOFNV1A3wvJgonxOgz_4WS-7MfCuowGWA5uYCjs,372
@@ -57,7 +57,7 @@ fmtr/tools/path_tools/app_path_tools.py,sha256=JrJvtTDd_gkCKcZtBCDTMktsM77PZwGV_
57
57
  fmtr/tools/path_tools/path_tools.py,sha256=8WBzNctpds5tVT1-FcizAORrBCGlkUbPcfOel-Js7ps,7878
58
58
  fmtr/tools/path_tools/type_path_tools.py,sha256=Zgs-ek-GXRKDIlVDGdg3muB0PIxTg2ba0NeHw6y8FWQ,40
59
59
  fmtr/tools/setup_tools/__init__.py,sha256=fUCjzyE4JBPEOZhC4B--VPj_eOCkQb1QG5PIgiGj03U,386
60
- fmtr/tools/setup_tools/setup_tools.py,sha256=A70uc80HrfvTh41LOizC14jQEY6N-ol4O-PkxYIJNBQ,7803
60
+ fmtr/tools/setup_tools/setup_tools.py,sha256=-BqbfiexUPhs71WBynpupGc_FD5MFLfD7FzT4XwlR9c,8540
61
61
  fmtr/tools/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  fmtr/tools/tests/conftest.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  fmtr/tools/tests/helpers.py,sha256=N5sf9YoZV93a7tf_UxpLeyQ9vp6Ec0teNIimFDvc054,1091
@@ -66,9 +66,9 @@ fmtr/tools/tests/test_environment.py,sha256=iHaiMQfECYZPkPKwfuIZV9uHuWe3aE-p_dN_
66
66
  fmtr/tools/tests/test_json.py,sha256=IeSP4ziPvRcmS8kq7k9tHonC9rN5YYq9GSNT2ul6Msk,287
67
67
  fmtr/tools/tests/test_path.py,sha256=AkZQa6_8BQ-VaCyL_J-iKmdf2ZaM-xFYR37Kun3k4_g,2188
68
68
  fmtr/tools/tests/test_yaml.py,sha256=jc0TwwKu9eC0LvFGNMERdgBue591xwLxYXFbtsRwXVM,287
69
- fmtr_tools-1.1.26.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
70
- fmtr_tools-1.1.26.dist-info/METADATA,sha256=FtJBsmBvoK7KrRHHybQWVULi5JeFwzjcz0H5QxlqF8Q,15735
71
- fmtr_tools-1.1.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- fmtr_tools-1.1.26.dist-info/entry_points.txt,sha256=e-eOW1Ml13tbxHC6Er1MnVOEDePeWw7DKwlE-l-gCY0,205
73
- fmtr_tools-1.1.26.dist-info/top_level.txt,sha256=LXem9xCgNOD72tE2gRKESdiQTL902mfFkwWb6-dlwEE,5
74
- fmtr_tools-1.1.26.dist-info/RECORD,,
69
+ fmtr_tools-1.1.28.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
70
+ fmtr_tools-1.1.28.dist-info/METADATA,sha256=VZ1GCYGE62S_ek4EqQv_4TtDS-cSfCA4xxCcfWP5lwU,15735
71
+ fmtr_tools-1.1.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
+ fmtr_tools-1.1.28.dist-info/entry_points.txt,sha256=e-eOW1Ml13tbxHC6Er1MnVOEDePeWw7DKwlE-l-gCY0,205
73
+ fmtr_tools-1.1.28.dist-info/top_level.txt,sha256=LXem9xCgNOD72tE2gRKESdiQTL902mfFkwWb6-dlwEE,5
74
+ fmtr_tools-1.1.28.dist-info/RECORD,,