fmtr.tools 1.3.22__py3-none-any.whl → 1.3.24__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/__init__.py CHANGED
@@ -18,6 +18,7 @@ import fmtr.tools.setup_tools as setup
18
18
  import fmtr.tools.string_tools as string
19
19
  from fmtr.tools import ai_tools as ai
20
20
  from fmtr.tools import dns_tools as dns
21
+ from fmtr.tools import interface_tools as interface
21
22
  from fmtr.tools import version_tools as version
22
23
  from fmtr.tools.constants import Constants
23
24
  from fmtr.tools.import_tools import MissingExtraMockModule
@@ -120,11 +121,6 @@ try:
120
121
  except ImportError as exception:
121
122
  html = MissingExtraMockModule('html', exception)
122
123
 
123
- try:
124
- from fmtr.tools import interface_tools as interface
125
- except ImportError as exception:
126
- interface = MissingExtraMockModule('interface', exception)
127
-
128
124
  try:
129
125
  from fmtr.tools import openai_tools as openai
130
126
  except ImportError as exception:
@@ -0,0 +1,7 @@
1
+ from fmtr.tools.import_tools import MissingExtraMockModule
2
+
3
+ try:
4
+ from fmtr.tools.interface_tools.interface_tools import Interface, update
5
+ from fmtr.tools.interface_tools import controls
6
+ except ImportError as exception:
7
+ Interface = update = controls = MissingExtraMockModule('interface', exception)
@@ -0,0 +1,73 @@
1
+ import flet as ft
2
+
3
+
4
+ class ContextRing(ft.ProgressRing):
5
+ """
6
+
7
+ Context manager progress ring.
8
+
9
+ """
10
+
11
+ def __init__(self, *args, **kwargs):
12
+ """
13
+
14
+ Start out not visible.
15
+
16
+ """
17
+ super().__init__(*args, **kwargs, visible=False)
18
+
19
+ def start(self):
20
+ """
21
+
22
+ Update to visible when in context.
23
+
24
+ """
25
+ self.visible = True
26
+ self.page.update()
27
+
28
+ def stop(self):
29
+ """
30
+
31
+ Update to not visible when exiting context.
32
+
33
+ """
34
+ self.visible = False
35
+ self.page.update()
36
+
37
+ def context(self, func):
38
+ """
39
+
40
+ Context manager decorator.
41
+
42
+ """
43
+
44
+ def wrapped(*args, **kwargs):
45
+ with self:
46
+ func(*args, **kwargs)
47
+
48
+ return wrapped
49
+
50
+ def __enter__(self):
51
+ self.start()
52
+ return self
53
+
54
+ def __exit__(self, exc_type, exc_val, exc_tb):
55
+ self.stop()
56
+
57
+
58
+ class ProgressButton(ft.Button):
59
+ """
60
+
61
+ Button with progress ring.
62
+
63
+ """
64
+
65
+ def __init__(self, *args, on_click=None, **kwargs):
66
+ """
67
+
68
+ Run on_click in run context manager
69
+
70
+ """
71
+ self.ring = ContextRing()
72
+ super().__init__(*args, content=self.ring, on_click=self.ring.context(on_click), **kwargs)
73
+ self.context = self.ring.context
@@ -0,0 +1,102 @@
1
+ import flet as ft
2
+ from flet.core.types import AppView
3
+ from flet.core.view import View
4
+
5
+ from fmtr.tools.logging_tools import logger
6
+
7
+
8
+ def update(func):
9
+ """
10
+
11
+ Page update decorator
12
+
13
+ """
14
+
15
+ def wrapped(*args, **kwargs):
16
+ func(*args, **kwargs)
17
+ func.__self__.page.update()
18
+
19
+ return wrapped
20
+
21
+ class Interface(ft.Column):
22
+ """
23
+
24
+ Simple interface base class.
25
+
26
+ """
27
+ TITLE = 'Base Interface'
28
+ HOST = '0.0.0.0'
29
+ PORT = 8080
30
+ URL = None
31
+ APPVIEW = AppView.WEB_BROWSER
32
+ PATH_ASSETS = None
33
+ ROUTE_ROOT = '/'
34
+
35
+ THEME = ft.Theme(color_scheme=ft.ColorScheme(primary=ft.Colors.PINK))
36
+
37
+ @classmethod
38
+ def render(cls, page: ft.Page):
39
+ """
40
+
41
+ Interface entry point. Set relevant callbacks, and add instantiated self to page views
42
+
43
+ """
44
+ if not page.on_route_change:
45
+ page.theme = cls.THEME
46
+ page.views.clear()
47
+ page.views.append(cls())
48
+
49
+ page.on_route_change = cls.route
50
+ page.on_view_pop = cls.pop
51
+
52
+ page.go(cls.ROUTE_ROOT)
53
+
54
+ @classmethod
55
+ def route(cls, event: ft.RouteChangeEvent):
56
+ """
57
+
58
+ Overridable router.
59
+
60
+ """
61
+ logger.debug(f'Route change: {event=}')
62
+
63
+ @classmethod
64
+ def pop(cls, view: View, page: ft.Page):
65
+ """
66
+
67
+ Overridable view pop.
68
+
69
+ """
70
+ logger.debug(f'View popped: {page.route=} {len(page.views)=} {view=}')
71
+
72
+ @classmethod
73
+ def launch(cls):
74
+ """
75
+
76
+ Launch via render method
77
+
78
+ """
79
+
80
+ if cls.URL:
81
+ url = cls.URL
82
+ else:
83
+ url = f'http://{cls.HOST}:{cls.PORT}'
84
+
85
+ logger.info(f"Launching {cls.TITLE} at {url}")
86
+ ft.app(cls.render, view=cls.APPVIEW, host=cls.HOST, port=cls.PORT, assets_dir=cls.PATH_ASSETS)
87
+
88
+
89
+ class Test(Interface):
90
+ """
91
+
92
+ Simple test interface.
93
+
94
+ """
95
+ TITLE = 'Test Interface'
96
+
97
+ def __init__(self):
98
+ controls = [ft.Text(self.TITLE)]
99
+ super().__init__(controls=controls)
100
+
101
+ if __name__ == "__main__":
102
+ Test.launch()
fmtr/tools/version CHANGED
@@ -1 +1 @@
1
- 1.3.22
1
+ 1.3.24
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmtr.tools
3
- Version: 1.3.22
3
+ Version: 1.3.24
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
@@ -126,61 +126,61 @@ Requires-Dist: logfire[httpx]; extra == "http"
126
126
  Provides-Extra: setup
127
127
  Requires-Dist: setuptools; extra == "setup"
128
128
  Provides-Extra: all
129
- Requires-Dist: contexttimer; extra == "all"
130
- Requires-Dist: httpx; extra == "all"
131
- Requires-Dist: huggingface_hub; extra == "all"
129
+ Requires-Dist: httpx_retries; extra == "all"
130
+ Requires-Dist: fastapi; extra == "all"
131
+ Requires-Dist: ollama; extra == "all"
132
132
  Requires-Dist: tinynetrc; extra == "all"
133
- Requires-Dist: json_repair; extra == "all"
134
- Requires-Dist: google-auth-httplib2; extra == "all"
135
- Requires-Dist: distributed; extra == "all"
136
- Requires-Dist: yamlscript; extra == "all"
137
- Requires-Dist: flet-video; extra == "all"
133
+ Requires-Dist: sentence_transformers; extra == "all"
138
134
  Requires-Dist: pandas; extra == "all"
139
- Requires-Dist: filetype; extra == "all"
140
- Requires-Dist: logfire; extra == "all"
141
- Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
142
- Requires-Dist: regex; extra == "all"
143
- Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
135
+ Requires-Dist: google-auth; extra == "all"
136
+ Requires-Dist: bokeh; extra == "all"
144
137
  Requires-Dist: logfire[fastapi]; extra == "all"
145
- Requires-Dist: pydantic-settings; extra == "all"
138
+ Requires-Dist: docker; extra == "all"
139
+ Requires-Dist: pymupdf; extra == "all"
140
+ Requires-Dist: regex; extra == "all"
141
+ Requires-Dist: torchaudio; extra == "all"
146
142
  Requires-Dist: torchvision; extra == "all"
147
- Requires-Dist: openai; extra == "all"
148
- Requires-Dist: sre_yield; extra == "all"
149
143
  Requires-Dist: logfire[httpx]; extra == "all"
150
- Requires-Dist: pymupdf4llm; extra == "all"
151
- Requires-Dist: pymupdf; extra == "all"
152
- Requires-Dist: faker; extra == "all"
153
- Requires-Dist: uvicorn[standard]; extra == "all"
154
- Requires-Dist: pytest-cov; extra == "all"
155
- Requires-Dist: google-auth; extra == "all"
156
- Requires-Dist: appdirs; extra == "all"
157
- Requires-Dist: google-api-python-client; extra == "all"
158
- Requires-Dist: docker; extra == "all"
159
144
  Requires-Dist: dnspython[doh]; extra == "all"
160
- Requires-Dist: transformers[sentencepiece]; extra == "all"
161
- Requires-Dist: dask[bag]; extra == "all"
162
- Requires-Dist: flet-webview; extra == "all"
163
- Requires-Dist: diskcache; extra == "all"
164
- Requires-Dist: tokenizers; extra == "all"
165
- Requires-Dist: httpx_retries; extra == "all"
166
- Requires-Dist: Unidecode; extra == "all"
167
- Requires-Dist: cachetools; extra == "all"
168
- Requires-Dist: openpyxl; extra == "all"
145
+ Requires-Dist: httpx; extra == "all"
146
+ Requires-Dist: logfire; extra == "all"
147
+ Requires-Dist: google-auth-httplib2; extra == "all"
148
+ Requires-Dist: contexttimer; extra == "all"
169
149
  Requires-Dist: tabulate; extra == "all"
150
+ Requires-Dist: transformers[sentencepiece]; extra == "all"
151
+ Requires-Dist: uvicorn[standard]; extra == "all"
152
+ Requires-Dist: google-auth-oauthlib; extra == "all"
153
+ Requires-Dist: google-api-python-client; extra == "all"
170
154
  Requires-Dist: peft; extra == "all"
171
- Requires-Dist: semver; extra == "all"
172
155
  Requires-Dist: deepmerge; extra == "all"
173
- Requires-Dist: fastapi; extra == "all"
156
+ Requires-Dist: json_repair; extra == "all"
157
+ Requires-Dist: Unidecode; extra == "all"
174
158
  Requires-Dist: flet[all]; extra == "all"
175
- Requires-Dist: sentence_transformers; extra == "all"
176
- Requires-Dist: bokeh; extra == "all"
177
- Requires-Dist: torchaudio; extra == "all"
178
- Requires-Dist: pyyaml; extra == "all"
159
+ Requires-Dist: flet-video; extra == "all"
160
+ Requires-Dist: flet-webview; extra == "all"
161
+ Requires-Dist: yamlscript; extra == "all"
179
162
  Requires-Dist: setuptools; extra == "all"
163
+ Requires-Dist: pydantic-settings; extra == "all"
164
+ Requires-Dist: sre_yield; extra == "all"
165
+ Requires-Dist: pytest-cov; extra == "all"
166
+ Requires-Dist: diskcache; extra == "all"
167
+ Requires-Dist: faker; extra == "all"
168
+ Requires-Dist: openpyxl; extra == "all"
169
+ Requires-Dist: distributed; extra == "all"
170
+ Requires-Dist: semver; extra == "all"
171
+ Requires-Dist: dask[bag]; extra == "all"
172
+ Requires-Dist: pydevd-pycharm~=251.25410.159; extra == "all"
180
173
  Requires-Dist: pydantic; extra == "all"
174
+ Requires-Dist: tokenizers; extra == "all"
175
+ Requires-Dist: pymupdf4llm; extra == "all"
176
+ Requires-Dist: pydantic-ai[logfire,openai]; extra == "all"
177
+ Requires-Dist: huggingface_hub; extra == "all"
178
+ Requires-Dist: filetype; extra == "all"
181
179
  Requires-Dist: html2text; extra == "all"
182
- Requires-Dist: ollama; extra == "all"
183
- Requires-Dist: google-auth-oauthlib; extra == "all"
180
+ Requires-Dist: pyyaml; extra == "all"
181
+ Requires-Dist: openai; extra == "all"
182
+ Requires-Dist: appdirs; extra == "all"
183
+ Requires-Dist: cachetools; extra == "all"
184
184
  Dynamic: author
185
185
  Dynamic: author-email
186
186
  Dynamic: description
@@ -1,4 +1,4 @@
1
- fmtr/tools/__init__.py,sha256=sjXo4eRDOPp20zlLpJqaB48h7RQXKJd_RwR3fwD6oGk,5731
1
+ fmtr/tools/__init__.py,sha256=9wmfLcYMilcfMS5NfOnaxUn7qxT4YZJ0MFwzOxeh-cQ,5625
2
2
  fmtr/tools/api_tools.py,sha256=RyZUlTefSQozfl-8feZGauyUkwcFd-jU0KtKHFxHea4,2272
3
3
  fmtr/tools/async_tools.py,sha256=ewz757WcveQJd-G5SVr2JDOQVbdLGecCgl-tsBGVZz4,284
4
4
  fmtr/tools/augmentation_tools.py,sha256=-6ESbO4CDlKqVOV1J1V6qBeoBMzbFIinkDHRHnCBej0,55
@@ -18,7 +18,6 @@ fmtr/tools/html_tools.py,sha256=0nN8Nz5HtG9bXyApYfHSKEivLlxjsm3Gn6Mg2TK0brI,394
18
18
  fmtr/tools/http_tools.py,sha256=RVwGrBNMyjfbpgAPCSnxEkXfSzXXWARb3ayq981ONQE,464
19
19
  fmtr/tools/import_tools.py,sha256=XJmiWLukRncJAcaGReDn4jIz1_IpVBjfYCQHH1hIg7c,588
20
20
  fmtr/tools/inspection_tools.py,sha256=tLTRvzy9XVomQPi0dfnF_cgwc7KiDVZAr7gPTk4S_bQ,278
21
- fmtr/tools/interface_tools.py,sha256=JVYUV7wuMr24BORuUtNaBlTeBFt8VDGJ3HPRajd7Y_4,1341
22
21
  fmtr/tools/iterator_tools.py,sha256=xj5f0c7LgLK53dddRRRJxBoLaBzlZoQS3_GfmpDPMoo,1311
23
22
  fmtr/tools/json_fix_tools.py,sha256=vNSlswVQnujPmKEqDjFJcO901mjMyv59q3awsT7mlhs,477
24
23
  fmtr/tools/json_tools.py,sha256=WkFc5q7oqMtcFejhN1K5zQFULa9TdLOup83Fr0saDRY,348
@@ -44,7 +43,7 @@ fmtr/tools/tabular_tools.py,sha256=tpIpZzYku1HcJrHZJL6BC39LmN3WUWVhFbK2N7nDVmE,1
44
43
  fmtr/tools/tokenization_tools.py,sha256=me-IBzSLyNYejLybwjO9CNB6Mj2NYfKPaOVThXyaGNg,4268
45
44
  fmtr/tools/tools.py,sha256=CAsApa1YwVdNE6H66Vjivs_mXYvOas3rh7fPELAnTpk,795
46
45
  fmtr/tools/unicode_tools.py,sha256=yS_9wpu8ogNoiIL7s1G_8bETFFO_YQlo4LNPv1NLDeY,52
47
- fmtr/tools/version,sha256=1S8waPxV74wCdn2itKFyhvvnbb7aVuX28-VkRL33YZg,6
46
+ fmtr/tools/version,sha256=6y8OlusXXRQ5CPOH7-e5z_iU7cHYXzBXhelkUzwZ9A4,6
48
47
  fmtr/tools/yaml_tools.py,sha256=Bhhyd6GQVKO72Lp8ky7bAUjIB_65Hdh0Q45SKIEe6S8,1901
49
48
  fmtr/tools/ai_tools/__init__.py,sha256=JZrLuOFNV1A3wvJgonxOgz_4WS-7MfCuowGWA5uYCjs,372
50
49
  fmtr/tools/ai_tools/agentic_tools.py,sha256=acSEPFS-aguDXanWGs3fAAlRyJSYPZW7L-Kb2qDLm-I,4300
@@ -60,6 +59,9 @@ fmtr/tools/entrypoints/ep_test.py,sha256=B8HfWISfSgw_xVX475CbJGh_QnpOe9MH65H8qGj
60
59
  fmtr/tools/entrypoints/install_yamlscript.py,sha256=D9-QET4uPkwMvOBQJAgzn1fYb7Z7VAgZzFdHSAXc3Qc,116
61
60
  fmtr/tools/entrypoints/remote_debug_test.py,sha256=wmKg9o2pQq7eqeHmaO8oviujNgtnsCVEXOdXLIcQWs4,123
62
61
  fmtr/tools/entrypoints/shell_debug.py,sha256=0No3tAg9Ri4_vvSlQCUtAY-11HR0nE45i0VVtiAViwY,106
62
+ fmtr/tools/interface_tools/__init__.py,sha256=RBg-QC7OO-PdAbFBadzHTzgjASchrKavAqdVbmBq4nM,310
63
+ fmtr/tools/interface_tools/controls.py,sha256=6C-estOVk4sHCyOFVJfMg3gcqhFADecI3jfxjBfHvg4,1305
64
+ fmtr/tools/interface_tools/interface_tools.py,sha256=3FJRlQfJFztQezBdGZ_izO1Az3jk3INrN4A75jatAlo,2056
63
65
  fmtr/tools/path_tools/__init__.py,sha256=v5CpmzXq5Ii90FtcmxAJKiLxmguZMrPnQ_HdT872Np0,443
64
66
  fmtr/tools/path_tools/app_path_tools.py,sha256=JrJvtTDd_gkCKcZtBCDTMktsM77PZwGV_hzQX0g5GU8,1722
65
67
  fmtr/tools/path_tools/path_tools.py,sha256=eh30PpmH0wopy0wNWuPT84cmXY1EvqsTSDT7AV_GPOY,8034
@@ -76,9 +78,9 @@ fmtr/tools/tests/test_path.py,sha256=AkZQa6_8BQ-VaCyL_J-iKmdf2ZaM-xFYR37Kun3k4_g
76
78
  fmtr/tools/tests/test_yaml.py,sha256=jc0TwwKu9eC0LvFGNMERdgBue591xwLxYXFbtsRwXVM,287
77
79
  fmtr/tools/version_tools/__init__.py,sha256=pg4iLtmIr5HtyEW_j0fMFoIdzqi_w9xH8-grQaXLB28,318
78
80
  fmtr/tools/version_tools/version_tools.py,sha256=Hcc6yferZS1hHbugRTdiHhSNmXEEG0hjCiTTXKna-YY,1127
79
- fmtr_tools-1.3.22.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
80
- fmtr_tools-1.3.22.dist-info/METADATA,sha256=yUEzCAR0OIWjGPaYvZVbZiGY52sHLyz2rPXQgMVlWxM,15938
81
- fmtr_tools-1.3.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
- fmtr_tools-1.3.22.dist-info/entry_points.txt,sha256=h-r__Xh5njtFqreMLg6cGuTFS4Qh-QqJPU1HB-_BS-Q,357
83
- fmtr_tools-1.3.22.dist-info/top_level.txt,sha256=LXem9xCgNOD72tE2gRKESdiQTL902mfFkwWb6-dlwEE,5
84
- fmtr_tools-1.3.22.dist-info/RECORD,,
81
+ fmtr_tools-1.3.24.dist-info/licenses/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
82
+ fmtr_tools-1.3.24.dist-info/METADATA,sha256=9rp92m_r7Ir_xQIhKccZpv_YSQgQcH4YK2TWjc1XEBo,15938
83
+ fmtr_tools-1.3.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
84
+ fmtr_tools-1.3.24.dist-info/entry_points.txt,sha256=h-r__Xh5njtFqreMLg6cGuTFS4Qh-QqJPU1HB-_BS-Q,357
85
+ fmtr_tools-1.3.24.dist-info/top_level.txt,sha256=LXem9xCgNOD72tE2gRKESdiQTL902mfFkwWb6-dlwEE,5
86
+ fmtr_tools-1.3.24.dist-info/RECORD,,
@@ -1,64 +0,0 @@
1
- import flet as ft
2
- from flet.core.event import Event
3
- from flet.core.types import AppView
4
- from flet.core.view import View
5
-
6
- from fmtr.tools.logging_tools import logger
7
-
8
-
9
- class Interface:
10
- """
11
-
12
- Simple interface base class.
13
-
14
- """
15
- TITLE = 'Base Interface'
16
- HOST = '0.0.0.0'
17
- PORT = 8080
18
- APPVIEW = AppView.WEB_BROWSER
19
- PATH_ASSETS = None
20
- ROUTE_ROOT = '/'
21
-
22
- def render(self, page: ft.Page):
23
- """
24
-
25
- Interface entry point.
26
-
27
- """
28
-
29
- if not page.on_route_change:
30
- page.on_route_change = lambda e, page=page: self.route(page, e)
31
- page.on_view_pop = lambda view, page=page: self.pop(page, view)
32
-
33
- page.go(self.ROUTE_ROOT)
34
-
35
- def route(self, page: ft.Page, event: Event):
36
- """
37
-
38
- Overridable router.
39
-
40
- """
41
- raise NotImplementedError
42
-
43
- def pop(self, page: ft.Page, view: View):
44
- """
45
-
46
- Overridable view pop.
47
-
48
- """
49
- raise NotImplementedError
50
-
51
- @classmethod
52
- def launch(cls):
53
- """
54
-
55
- Initialise self and launch.
56
-
57
- """
58
- self = cls()
59
- logger.info(f"Launching {self.TITLE} at http://{self.HOST}:{self.PORT}")
60
- ft.app(self.render, view=self.APPVIEW, host=self.HOST, port=self.PORT, assets_dir=self.PATH_ASSETS)
61
-
62
-
63
- if __name__ == "__main__":
64
- Interface.launch()