fmtr.tools 1.0.30__py3-none-any.whl → 1.0.32__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/api_tools.py CHANGED
@@ -83,6 +83,11 @@ class ApiBase:
83
83
 
84
84
  @classmethod
85
85
  def launch(cls):
86
+ """
87
+
88
+ Initialise self and launch.
89
+
90
+ """
86
91
  self = cls()
87
92
  logger.info(f'Launching API {cls.TITLE}...')
88
93
  uvicorn.run(self.app, host=self.HOST, port=self.PORT)
@@ -1,218 +1,64 @@
1
- from time import sleep
2
- from typing import ClassVar
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
3
5
 
4
- from fmtr.tools.data_modelling_tools import Base
5
6
  from fmtr.tools.logging_tools import logger
6
- from fmtr.tools.path_tools import Path
7
7
 
8
8
 
9
- def material(name):
9
+ class Interface:
10
10
  """
11
11
 
12
- Get Material Design icon markdown
12
+ Simple interface base class.
13
13
 
14
14
  """
15
- return f":material/{name}:"
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 = '/'
16
21
 
17
-
18
- def color(name, text):
19
- """
20
-
21
- Get markdown coloured text
22
-
23
- """
24
- return f":{name}[{text}]"
25
-
26
-
27
- def get_streamlit():
28
- import streamlit
29
- return streamlit
30
-
31
- class Interface(Base):
32
- """
33
-
34
- Base for using streamlit via classes
35
-
36
- """
37
-
38
- PATH: ClassVar = __file__
39
- LAYOUT: ClassVar = 'centered'
40
- NAME: ClassVar = None
41
- IS_ASYNC: ClassVar = False
42
-
43
- parent: Base = None
44
-
45
- @property
46
- def st(self):
47
- return get_streamlit()
48
-
49
- @classmethod
50
- def get_name(cls):
51
- return cls.NAME or cls.__name__
52
-
53
- def set_title(self):
54
- """
55
-
56
- Set page title and layout when root interface
57
-
58
- """
59
-
60
- self.st.set_page_config(page_title=self.get_name(), layout=self.LAYOUT)
61
- self.st.title(self.get_name())
62
-
63
- def render(self):
64
- """
65
-
66
- Render the Interface
67
-
68
- """
69
- raise NotImplementedError()
70
-
71
- def get_key(self, seg=None):
72
- """
73
-
74
- Get a structure-friendly unique ID
75
-
76
- """
77
-
78
- suffix = f'{self.__class__.__name__}({self.get_key_self()})'
79
-
80
- if self.parent is None:
81
- base = Path(suffix)
82
- else:
83
- base = self.parent.get_key() / suffix
84
-
85
- if seg:
86
- path = base / seg
87
- else:
88
- path = base
89
-
90
- return path
91
-
92
- def get_url_data(self):
93
- """
94
-
95
- Get URL params data pertaining to the current object
96
-
97
- """
98
-
99
- if self.parent is None:
100
- data = {}
101
- else:
102
- data = self.parent.get_url_data()
103
-
104
- url_self = self.get_url_self()
105
-
106
- if url_self:
107
- data |= {self.__class__.__name__.lower(): url_self}
108
-
109
- return data
110
-
111
- def get_url_self(self):
112
- """
113
-
114
- Get URL params ID pertaining to the current object
115
-
116
- """
117
- return str(id(self))
118
-
119
- def get_key_self(self):
22
+ def render(self, page: ft.Page):
120
23
  """
121
24
 
122
- Get a streamlit key pertaining to the current object
123
-
124
- """
125
- return str(id(self))
25
+ Interface entry point.
126
26
 
127
- def get_url(self):
128
27
  """
129
28
 
130
- Get URL string suffix pertaining to the current object
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)
131
32
 
132
- """
133
- import urllib
134
- return urllib.parse.urlencode(self.get_url_data())
33
+ page.go(self.ROUTE_ROOT)
135
34
 
136
- def to_tabs(self, *classes):
35
+ def route(self, page: ft.Page, event: Event):
137
36
  """
138
37
 
139
- Add tabs from a list of interface classes
38
+ Overridable router.
140
39
 
141
40
  """
142
- tab_names = [cls.get_name() for cls in classes]
143
- tabs = st.tabs(tab_names)
144
-
145
- for cls, tab in zip(classes, tabs):
146
- with tab:
147
- cls()
41
+ raise NotImplementedError
148
42
 
149
- @classmethod
150
- def is_streamlit(cls):
43
+ def pop(self, page: ft.Page, view: View):
151
44
  """
152
45
 
153
- Infer whether we are running within StreamLit
46
+ Overridable view pop.
154
47
 
155
48
  """
156
- return bool(get_streamlit().context.headers)
157
-
158
- @classmethod
159
- def get_state(cls):
160
- """
161
-
162
- Initialise this Interface and keep cached. This needs to be a cached_resource to avoid serialisation/copying.
163
- This is global, so session handling needs to happen downstream.
164
-
165
- """
166
- msg = f'Initialising State "{cls.get_name()}"...'
167
- logger.info(msg)
168
- self = cls()
169
- return self
49
+ raise NotImplementedError
170
50
 
171
51
  @classmethod
172
52
  def launch(cls):
173
53
  """
174
54
 
175
- Launch StreamLit, if not already running - otherwise get self from cache and render
55
+ Initialise self and launch.
176
56
 
177
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)
178
61
 
179
- st = get_streamlit()
180
-
181
- if cls.is_streamlit():
182
-
183
- if cls.IS_ASYNC:
184
- from fmtr.tools import async_tools
185
- async_tools.ensure_loop()
186
-
187
- self = st.cache_resource(show_spinner=False)(cls.get_state)()
188
- logger.debug(f'Rendering Interface "{self.get_name()}" with state: {st.session_state}...')
189
- self.set_title()
190
- self.render()
191
- else:
192
- logger.info(f'Launching Streamlit interface "{cls.get_name()}"...')
193
- from streamlit.web import bootstrap
194
- bootstrap.run(cls.PATH, False, [], {})
195
-
196
-
197
- class InterfaceTest(Interface):
198
- NAME: ClassVar = 'Test Interface'
199
-
200
- parent: Base = None
201
-
202
- def render(self):
203
- """
204
-
205
- Render the Interface
206
-
207
- """
208
- if not self.st.button('Run Test'):
209
- return
210
- msg = 'Running test...'
211
- with self.st.spinner(msg):
212
- sleep(3)
213
- self.st.success("Success!")
214
-
215
-
216
- if __name__ == '__main__':
217
- InterfaceTest.launch()
218
62
 
63
+ if __name__ == "__main__":
64
+ Interface.launch()
fmtr/tools/path_tools.py CHANGED
@@ -96,6 +96,29 @@ class Path(type(Path())):
96
96
  """
97
97
  return cls(gettempdir())
98
98
 
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
+
99
122
  def write_json(self, obj) -> int:
100
123
  """
101
124
 
@@ -145,3 +145,10 @@ class Mask:
145
145
  return text
146
146
  except (KeyError, IndexError):
147
147
  return self
148
+
149
+
150
+ if __name__ == '__main__':
151
+ import numpy as np
152
+
153
+ st = join([1, None, 'test', np.nan, 0, '', 'yeah'])
154
+ st
fmtr/tools/version CHANGED
@@ -1 +1 @@
1
- 1.0.30
1
+ 1.0.32
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fmtr.tools
3
- Version: 1.0.30
3
+ Version: 1.0.32
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
@@ -46,8 +46,10 @@ Requires-Dist: huggingface-hub ; extra == 'hfh'
46
46
  Provides-Extra: html
47
47
  Requires-Dist: html2text ; extra == 'html'
48
48
  Provides-Extra: interface
49
+ Requires-Dist: flet-video ; extra == 'interface'
50
+ Requires-Dist: flet-webview ; extra == 'interface'
51
+ Requires-Dist: flet[all] ; extra == 'interface'
49
52
  Requires-Dist: pydantic ; extra == 'interface'
50
- Requires-Dist: streamlit ; extra == 'interface'
51
53
  Provides-Extra: json-fix
52
54
  Requires-Dist: json-repair ; extra == 'json-fix'
53
55
  Provides-Extra: logging
@@ -86,6 +88,9 @@ Requires-Dist: distributed ; extra == 'test'
86
88
  Requires-Dist: docker ; extra == 'test'
87
89
  Requires-Dist: faker ; extra == 'test'
88
90
  Requires-Dist: fastapi ; extra == 'test'
91
+ Requires-Dist: flet-video ; extra == 'test'
92
+ Requires-Dist: flet-webview ; extra == 'test'
93
+ Requires-Dist: flet[all] ; extra == 'test'
89
94
  Requires-Dist: google-api-python-client ; extra == 'test'
90
95
  Requires-Dist: google-auth ; extra == 'test'
91
96
  Requires-Dist: google-auth-httplib2 ; extra == 'test'
@@ -105,7 +110,6 @@ Requires-Dist: pyyaml ; extra == 'test'
105
110
  Requires-Dist: semver ; extra == 'test'
106
111
  Requires-Dist: sentence-transformers ; extra == 'test'
107
112
  Requires-Dist: sre-yield ; extra == 'test'
108
- Requires-Dist: streamlit ; extra == 'test'
109
113
  Requires-Dist: tinynetrc ; extra == 'test'
110
114
  Requires-Dist: tokenizers ; extra == 'test'
111
115
  Requires-Dist: torchaudio ; extra == 'test'
@@ -225,7 +229,7 @@ The included modules, plus any extra requirements, are as follows:
225
229
  - Extras: `hfh`
226
230
  - `tools.html`: Utilities for converting HTML documents to plain text.
227
231
  - Extras: `html`
228
- - `tools.interface`: Provides a base class for building Streamlit interfaces with a class-based structure.
232
+ - `tools.interface`: Provides a base class for building Flutter/Flet apps.
229
233
  - Extras: `interface`
230
234
  - `tools.iterator`: Pivoting/unpivoting data structures
231
235
  - Extras: None
@@ -1,6 +1,6 @@
1
1
  fmtr/tools/__init__.py,sha256=imKjjZg5HypnRy5bD4Xe6HBkQhavg6BOkwIeFzItG_8,5052
2
2
  fmtr/tools/ai_tools.py,sha256=hN7DzuATXfurCDHugaluUsbmF_PzeKu3BTc2WXhG59g,11806
3
- fmtr/tools/api_tools.py,sha256=KU_qetI7WQRZijZ0l1nCKjPcRbseMMCWj0W8n_NTJCM,2027
3
+ fmtr/tools/api_tools.py,sha256=u5YEdKyKto8MKY8legULLU7xeJ7lY2Bgyaep_xa8iZg,2089
4
4
  fmtr/tools/async_tools.py,sha256=ewz757WcveQJd-G5SVr2JDOQVbdLGecCgl-tsBGVZz4,284
5
5
  fmtr/tools/augmentation_tools.py,sha256=-6ESbO4CDlKqVOV1J1V6qBeoBMzbFIinkDHRHnCBej0,55
6
6
  fmtr/tools/caching_tools.py,sha256=UOCYUNvLQ-NofR_dhqBmZF96-HRPf4At5MmxVk3gAIk,2943
@@ -19,7 +19,7 @@ fmtr/tools/hfh_tools.py,sha256=DCDIWuWlhtmIGCtp9cLcOTTEw_4yN_NocLX8w5NZsbk,2384
19
19
  fmtr/tools/html_tools.py,sha256=0nN8Nz5HtG9bXyApYfHSKEivLlxjsm3Gn6Mg2TK0brI,394
20
20
  fmtr/tools/import_tools.py,sha256=XJmiWLukRncJAcaGReDn4jIz1_IpVBjfYCQHH1hIg7c,588
21
21
  fmtr/tools/inspection_tools.py,sha256=tLTRvzy9XVomQPi0dfnF_cgwc7KiDVZAr7gPTk4S_bQ,278
22
- fmtr/tools/interface_tools.py,sha256=fi0KW0veB2NQCmVmCA9iJUL_03gz0MD-gJ4OK-QUBVA,4481
22
+ fmtr/tools/interface_tools.py,sha256=JVYUV7wuMr24BORuUtNaBlTeBFt8VDGJ3HPRajd7Y_4,1341
23
23
  fmtr/tools/iterator_tools.py,sha256=xj5f0c7LgLK53dddRRRJxBoLaBzlZoQS3_GfmpDPMoo,1311
24
24
  fmtr/tools/json_fix_tools.py,sha256=vNSlswVQnujPmKEqDjFJcO901mjMyv59q3awsT7mlhs,477
25
25
  fmtr/tools/json_tools.py,sha256=IKmrANhcftIz2msCZeItidJ1PcpY_tnbfxbRDnta-c0,349
@@ -30,18 +30,18 @@ fmtr/tools/name_tools.py,sha256=5CB_phqhHjl66iI8oLxOGPF2odC1apdul-M8Fv2xBhs,5514
30
30
  fmtr/tools/netrc_tools.py,sha256=PpNpz_mWlQi6VHGromKwFfTyLpHUXsd4LY6-OKLCbeI,376
31
31
  fmtr/tools/openai_tools.py,sha256=6SUgejgzUzmlKKct2_ePXntvMegu3FJgfk9x7aqtqYc,742
32
32
  fmtr/tools/parallel_tools.py,sha256=G__ZbLRRx4cP5OyqY1hKwnE-VI3m5prYABB0tnZHnes,3132
33
- fmtr/tools/path_tools.py,sha256=iNIG-nxBX-uiyfyOapJZaUiS4pI8sHsxm6WhVHixQ0M,3700
33
+ fmtr/tools/path_tools.py,sha256=1GeWXdhV5rH99IfLI5ZFEnOJfs4Q4mYTT2R-rA791iQ,4273
34
34
  fmtr/tools/platform_tools.py,sha256=7p69CmAHe_sF68Fx9uVhns1k5EewTHTWgUYzkl6ZQKA,308
35
35
  fmtr/tools/process_tools.py,sha256=Ysh5Dk2QFBhXQerArjKdt7xZd3JrN5Ho02AaOjH0Nnw,1425
36
36
  fmtr/tools/profiling_tools.py,sha256=jpXVjaNKPydTasEQVNXvxzGtMhXPit08AnJddkU8uIc,46
37
37
  fmtr/tools/random_tools.py,sha256=4VlQdk5THbR8ka4pZaLbk_ZO_4yy6PF_lHZes_rgenY,2223
38
38
  fmtr/tools/semantic_tools.py,sha256=cxY9NSAHWj4nEc6Oj4qA1omR3dWbl2OuH7_PkINc6_E,1386
39
39
  fmtr/tools/spaces_tools.py,sha256=D_he3mve6DruB3OPS6QyzqD05ChHnRTb4buViKPe7To,1099
40
- fmtr/tools/string_tools.py,sha256=w0lw70bgzJ8tAHj_4lMrjtMyefE5kELgpCBgGzGcalo,3117
40
+ fmtr/tools/string_tools.py,sha256=U2EptMWR6KDOP22ZQ4ReUHV4i25SP7xwCmZScI1sy4M,3233
41
41
  fmtr/tools/tokenization_tools.py,sha256=9FP5vgPufWv0XA961eVKObFll0d_2mM0W3ut3rtZyeo,4329
42
42
  fmtr/tools/tools.py,sha256=xnfUrOnrT4OxFYez6vV5tAhydzCICJFiGVnviiZDEQo,796
43
43
  fmtr/tools/unicode_tools.py,sha256=yS_9wpu8ogNoiIL7s1G_8bETFFO_YQlo4LNPv1NLDeY,52
44
- fmtr/tools/version,sha256=KqCSJDZneRpdDeee96Q2BTV-S_j2zzKb31hTn-S4o9E,6
44
+ fmtr/tools/version,sha256=lJlaFE-y4dFjsYr6jbTGb5uzUQ_dp_LO5e9G4R2TeMk,6
45
45
  fmtr/tools/version_tools.py,sha256=axzzHBS9V1n6YuSacsDKG3VfAvRqR8qr6aENCibR8vs,1248
46
46
  fmtr/tools/yaml_tools.py,sha256=Ol43ZwbnSXGnn1K98Uxx61KPGSqfC4axE-X2q1LKMwk,349
47
47
  fmtr/tools/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -52,9 +52,9 @@ fmtr/tools/tests/test_environment.py,sha256=iHaiMQfECYZPkPKwfuIZV9uHuWe3aE-p_dN_
52
52
  fmtr/tools/tests/test_json.py,sha256=IeSP4ziPvRcmS8kq7k9tHonC9rN5YYq9GSNT2ul6Msk,287
53
53
  fmtr/tools/tests/test_path.py,sha256=AkZQa6_8BQ-VaCyL_J-iKmdf2ZaM-xFYR37Kun3k4_g,2188
54
54
  fmtr/tools/tests/test_yaml.py,sha256=jc0TwwKu9eC0LvFGNMERdgBue591xwLxYXFbtsRwXVM,287
55
- fmtr.tools-1.0.30.dist-info/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
56
- fmtr.tools-1.0.30.dist-info/METADATA,sha256=DI1kVQoW1YTrWGUSknWyCbVtPvThmbgJDwrEJ-_oTP4,13049
57
- fmtr.tools-1.0.30.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
58
- fmtr.tools-1.0.30.dist-info/entry_points.txt,sha256=CEStVkwJ1mTFvhN1WV5RdW83SkNW1d5Syj-KZ6A19ng,72
59
- fmtr.tools-1.0.30.dist-info/top_level.txt,sha256=t5341a8ii3n4RFizwTeXGmcq_pf4GqL1h9ylE5LIWRk,12
60
- fmtr.tools-1.0.30.dist-info/RECORD,,
55
+ fmtr.tools-1.0.32.dist-info/LICENSE,sha256=FW9aa6vVN5IjRQWLT43hs4_koYSmpcbIovlKeAJ0_cI,10757
56
+ fmtr.tools-1.0.32.dist-info/METADATA,sha256=iPCoZOCJ1UbUM0x2NVVcWQiEg-Co8RZNSQIy1cgHErQ,13207
57
+ fmtr.tools-1.0.32.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
58
+ fmtr.tools-1.0.32.dist-info/entry_points.txt,sha256=CEStVkwJ1mTFvhN1WV5RdW83SkNW1d5Syj-KZ6A19ng,72
59
+ fmtr.tools-1.0.32.dist-info/top_level.txt,sha256=t5341a8ii3n4RFizwTeXGmcq_pf4GqL1h9ylE5LIWRk,12
60
+ fmtr.tools-1.0.32.dist-info/RECORD,,