composeui 0.1.0__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.
Files changed (97) hide show
  1. composeui/__init__.py +11 -0
  2. composeui/core/__init__.py +0 -0
  3. composeui/core/application.py +368 -0
  4. composeui/core/chartcolors.py +23 -0
  5. composeui/core/chartimage.py +336 -0
  6. composeui/core/dataframesource.py +307 -0
  7. composeui/core/jobs.py +426 -0
  8. composeui/core/model.py +66 -0
  9. composeui/core/registry.py +66 -0
  10. composeui/core/reload.py +476 -0
  11. composeui/core/renderer.py +193 -0
  12. composeui/core/signal.py +358 -0
  13. composeui/core/sqlitemodel.py +1183 -0
  14. composeui/core/study.py +121 -0
  15. composeui/core/translation.py +221 -0
  16. composeui/core/translationcheck.py +254 -0
  17. composeui/core/view.py +5508 -0
  18. composeui/images/composeui.svg +15 -0
  19. composeui/locales/fr.json +73 -0
  20. composeui/mypy.py +46 -0
  21. composeui/py.typed +0 -0
  22. composeui/qtcore/__init__.py +0 -0
  23. composeui/qtcore/maprenderer.py +115 -0
  24. composeui/qtcore/qtapplication.py +222 -0
  25. composeui/qtcore/qtrenderer.py +2862 -0
  26. composeui/qtcore/widgets/__init__.py +0 -0
  27. composeui/qtcore/widgets/map.qml +123 -0
  28. composeui/qtcore/widgets/qchart.py +393 -0
  29. composeui/qtcore/widgets/qdatefield.py +101 -0
  30. composeui/qtcore/widgets/qexpander.py +60 -0
  31. composeui/qtcore/widgets/qfilepathfield.py +34 -0
  32. composeui/qtcore/widgets/qfiltertable.py +394 -0
  33. composeui/qtcore/widgets/qformdialog.py +64 -0
  34. composeui/qtcore/widgets/qformlabel.py +53 -0
  35. composeui/qtcore/widgets/qmap.py +68 -0
  36. composeui/qtcore/widgets/qmarkicon.py +37 -0
  37. composeui/qtcore/widgets/qmetric.py +44 -0
  38. composeui/qtcore/widgets/qplaintext.py +29 -0
  39. composeui/qtcore/widgets/qradiogroup.py +57 -0
  40. composeui/qtcore/widgets/qsidebar.py +116 -0
  41. composeui/qtcore/widgets/qsourcetable.py +216 -0
  42. composeui/qtcore/widgets/qsplitter.py +69 -0
  43. composeui/qtcore/widgets/qtexttable.py +703 -0
  44. composeui/qtcore/widgets/qvaluecombobox.py +41 -0
  45. composeui/qtcore/widgets/qvalueslider.py +64 -0
  46. composeui/qtcore/widgets/qwindowrelease.py +32 -0
  47. composeui/textualcore/__init__.py +0 -0
  48. composeui/textualcore/textualapplication.py +121 -0
  49. composeui/textualcore/textualrenderer.py +2893 -0
  50. composeui/textualcore/widgets/__init__.py +0 -0
  51. composeui/textualcore/widgets/composebutton.py +17 -0
  52. composeui/textualcore/widgets/composechart.py +212 -0
  53. composeui/textualcore/widgets/composecheckbox.py +35 -0
  54. composeui/textualcore/widgets/composecollapsible.py +41 -0
  55. composeui/textualcore/widgets/composecombobox.py +54 -0
  56. composeui/textualcore/widgets/composedateinput.py +325 -0
  57. composeui/textualcore/widgets/composedialog.py +90 -0
  58. composeui/textualcore/widgets/composefilepathinput.py +85 -0
  59. composeui/textualcore/widgets/composefiltertable.py +367 -0
  60. composeui/textualcore/widgets/composeformdialog.py +86 -0
  61. composeui/textualcore/widgets/composeinput.py +50 -0
  62. composeui/textualcore/widgets/composelist.py +20 -0
  63. composeui/textualcore/widgets/composemarkdown.py +17 -0
  64. composeui/textualcore/widgets/composemetric.py +60 -0
  65. composeui/textualcore/widgets/composeradioset.py +54 -0
  66. composeui/textualcore/widgets/composesidebar.py +111 -0
  67. composeui/textualcore/widgets/composeslider.py +144 -0
  68. composeui/textualcore/widgets/composesourcetable.py +288 -0
  69. composeui/textualcore/widgets/composesplitter.py +211 -0
  70. composeui/textualcore/widgets/composetabbedcontent.py +35 -0
  71. composeui/textualcore/widgets/composetable.py +476 -0
  72. composeui/textualcore/widgets/composetoolbar.py +62 -0
  73. composeui/textualcore/widgets/composetree.py +139 -0
  74. composeui/webcore/__init__.py +0 -0
  75. composeui/webcore/headers.py +57 -0
  76. composeui/webcore/icons.py +58 -0
  77. composeui/webcore/limits.py +55 -0
  78. composeui/webcore/origin.py +63 -0
  79. composeui/webcore/page.py +146 -0
  80. composeui/webcore/routes.py +303 -0
  81. composeui/webcore/session.py +436 -0
  82. composeui/webcore/static/app.css +2 -0
  83. composeui/webcore/static/cally.js +1312 -0
  84. composeui/webcore/static/daisyui.LICENSE +21 -0
  85. composeui/webcore/static/deckgl.LICENSE +19 -0
  86. composeui/webcore/static/deckgl.min.js +6423 -0
  87. composeui/webcore/static/htmx.min.js +1 -0
  88. composeui/webcore/static/page.js +1175 -0
  89. composeui/webcore/static/uPlot.LICENSE +21 -0
  90. composeui/webcore/static/uPlot.iife.min.js +2 -0
  91. composeui/webcore/webapplication.py +495 -0
  92. composeui/webcore/webrenderer.py +5113 -0
  93. composeui-0.1.0.dist-info/METADATA +222 -0
  94. composeui-0.1.0.dist-info/RECORD +97 -0
  95. composeui-0.1.0.dist-info/WHEEL +5 -0
  96. composeui-0.1.0.dist-info/licenses/LICENSE +9 -0
  97. composeui-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,222 @@
1
+ Metadata-Version: 2.4
2
+ Name: composeui
3
+ Version: 0.1.0
4
+ Summary: A framework-agnostic MVVM layer for Python UIs: one app for Qt, Textual and the web
5
+ Author-email: El Hadi Moussi <50993404+ehmoussi@users.noreply.github.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/ehmoussi/composeui
8
+ Project-URL: Documentation, https://ehmoussi.github.io/composeui/
9
+ Project-URL: Source, https://github.com/ehmoussi/composeui
10
+ Project-URL: Issues, https://github.com/ehmoussi/composeui/issues
11
+ Project-URL: Changelog, https://github.com/ehmoussi/composeui/blob/main/CHANGELOG.md
12
+ Keywords: mvvm,gui,qt,pyside6,textual,tui,web,htmx,attrs,cattrs,reactive
13
+ Classifier: Development Status :: 2 - Pre-Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Environment :: Console
24
+ Classifier: Environment :: Web Environment
25
+ Classifier: Environment :: X11 Applications :: Qt
26
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
27
+ Classifier: Topic :: Software Development :: User Interfaces
28
+ Classifier: Typing :: Typed
29
+ Requires-Python: >=3.9
30
+ Description-Content-Type: text/markdown
31
+ License-File: LICENSE
32
+ Requires-Dist: attrs>=26.1.0
33
+ Requires-Dist: cattrs>=25.3.0
34
+ Requires-Dist: typing-extensions>=4.15.0
35
+ Provides-Extra: pyside6
36
+ Requires-Dist: pyqtgraph>=0.13.7; extra == "pyside6"
37
+ Requires-Dist: pyside6>=6.10.3; extra == "pyside6"
38
+ Requires-Dist: qtpy>=2.4.3; extra == "pyside6"
39
+ Provides-Extra: tui
40
+ Requires-Dist: textual>=8.2.8; extra == "tui"
41
+ Requires-Dist: textual-fspicker>=0.6.0; extra == "tui"
42
+ Requires-Dist: textual-plotext>=1.0.1; extra == "tui"
43
+ Provides-Extra: web
44
+ Requires-Dist: itsdangerous>=2.2.0; extra == "web"
45
+ Requires-Dist: markdown-it-py>=3.0.0; extra == "web"
46
+ Requires-Dist: markupsafe>=3.0.2; extra == "web"
47
+ Requires-Dist: python-multipart>=0.0.20; extra == "web"
48
+ Requires-Dist: starlette>=0.49.3; extra == "web"
49
+ Requires-Dist: uvicorn>=0.39.0; extra == "web"
50
+ Provides-Extra: report
51
+ Requires-Dist: matplotlib>=3.9; extra == "report"
52
+ Provides-Extra: reload
53
+ Requires-Dist: watchfiles>=1.1.1; extra == "reload"
54
+ Provides-Extra: dataframe
55
+ Requires-Dist: narwhals>=2.21.0; extra == "dataframe"
56
+ Dynamic: license-file
57
+
58
+ <h1>
59
+ <picture>
60
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/ehmoussi/composeui/main/docs/_static/composeui-logo-dark.svg">
61
+ <img alt="ComposeUI" src="https://raw.githubusercontent.com/ehmoussi/composeui/main/docs/_static/composeui-logo-light.svg" width="268" height="64">
62
+ </picture>
63
+ </h1>
64
+
65
+ A small, framework-agnostic MVVM layer for building UIs in Python. You declare views as typed
66
+ [`attrs`](https://www.attrs.org/) classes. They hold the state of the UI, but no toolkit code: in
67
+ MVVM terms, they are the view-models
68
+ ([how ComposeUI maps to MVVM](https://ehmoussi.github.io/composeui/user-guide/core-concepts.html#how-composeui-maps-to-mvvm)).
69
+ A `Renderer` binds each view to a toolkit widget, which plays the View role of MVVM:
70
+
71
+ - a desktop window with [Qt](https://pypi.org/project/QtPy/), through `qtpy`;
72
+ - a terminal with [Textual](https://textual.textualize.io/);
73
+ - a web page served with [Starlette](https://www.starlette.io/) and [htmx](https://htmx.org/).
74
+
75
+ `Signal` objects carry events between view, model, and application code.
76
+
77
+ > **Status:** early-stage / pre-alpha. The API is small and still moving.
78
+
79
+ ## Why
80
+
81
+ - **Declarative views.** A view is an `attrs` class with typed fields. You don't build
82
+ widgets or wire their signals by hand.
83
+ - **Reactive by construction.** When you set an attribute of a view (`view.text = "..."`),
84
+ the view pushes the change to its renderer. Normal state changes need no `update()` or
85
+ `refresh()` calls.
86
+ - **Toolkit-agnostic core.** `composeui.core` doesn't import Qt, Textual, or Starlette
87
+ when Python imports it. Each backend is imported only when a view renders with it.
88
+ - **Typed callback injection.** `Signal.connect` and `Application.connect` read the
89
+ parameter names of a callback. They inject `view`, `main_view`, or `model` when the
90
+ callback asks for them. So callbacks stay short, without manual lookups.
91
+
92
+ ## When to use it
93
+
94
+ - **Choose ComposeUI** when one app must show as a desktop window, in a terminal, and in a
95
+ browser, or may move from one to another later. It also suits an app whose state must be
96
+ typed, saved as a file, and tested without a UI
97
+ ([Testing your app](https://ehmoussi.github.io/composeui/user-guide/testing.html)).
98
+ - **Compared with Streamlit,** the views are explicit classes that keep their state, and
99
+ nothing runs the script again on each change. The same app also runs as a desktop
100
+ window or in a terminal.
101
+ - **Compared with Qt, Textual, or a web framework alone,** the app gives up the widgets
102
+ that only one toolkit has, and keeps one code base for the three.
103
+ - **Not yet** for an app that needs a stable API, or a widget that is still missing, such
104
+ as a context menu or a wizard (see
105
+ [`ROADMAP.md`](https://github.com/ehmoussi/composeui/blob/main/ROADMAP.md)).
106
+
107
+ ## Installation
108
+
109
+ Requires Python >= 3.9. Install ComposeUI from PyPI with the extras of the backends that you
110
+ want, for example the web and Qt backends:
111
+
112
+ ```bash
113
+ uv add "composeui[web,pyside6]" # or: pip install "composeui[web,pyside6]"
114
+ ```
115
+
116
+ Each extra adds a backend or a feature:
117
+
118
+ | Extra | Installs | For |
119
+ | --- | --- | --- |
120
+ | `web` | Starlette, uvicorn | The web backend, the default |
121
+ | `pyside6` | PySide6 | The Qt backend, a desktop window |
122
+ | `tui` | Textual | The Textual backend, a terminal |
123
+ | `report` | matplotlib | The report images of charts |
124
+ | `dataframe` | narwhals | A large table of a pandas, Polars, or PyArrow frame |
125
+ | `reload` | watchfiles | A faster `--reload` in development |
126
+
127
+ To try ComposeUI and its example apps, clone the repository and install every extra:
128
+
129
+ ```bash
130
+ git clone https://github.com/ehmoussi/composeui
131
+ cd composeui
132
+ uv sync --all-extras
133
+ ```
134
+
135
+ To choose extras, give them all in one command, for example
136
+ `uv sync --extra web --extra pyside6`. Each `uv sync` removes the extras that it does not
137
+ name, so a second `uv sync --extra tui` would remove the web and Qt backends.
138
+
139
+ ## Quickstart
140
+
141
+ A minimal window with a text input. As you type your name, the status bar greets you:
142
+
143
+ ```python
144
+ from attrs import Factory
145
+
146
+ from composeui.core.application import run
147
+ from composeui.core.view import InputView, MainView, define_view
148
+
149
+
150
+ @define_view
151
+ class GreetingInputView(InputView):
152
+ def __attrs_post_init__(self) -> None:
153
+ super().__attrs_post_init__()
154
+ self.placeholder = "Type your name..."
155
+ self.text_edited.connect(self._on_name_changed)
156
+
157
+ # `main_view` is injected automatically because it's a requested parameter.
158
+ def _on_name_changed(self, text: str, *, main_view: MainView) -> None:
159
+ main_view.status_bar.show_message(f"Hello, {text}!" if text else "")
160
+
161
+
162
+ @define_view
163
+ class HelloMainView(MainView):
164
+ app_title = "Hello ComposeUI"
165
+ extension = ".hello" # the file type of its studies, which the File menu saves
166
+
167
+ greeting: GreetingInputView = Factory(GreetingInputView)
168
+
169
+
170
+ if __name__ == "__main__":
171
+ run(HelloMainView)
172
+ ```
173
+
174
+ Run it with one of the backends. Each backend needs its extra:
175
+
176
+ ```bash
177
+ uv run python hello.py --backend qt # a window: the pyside6 extra
178
+ uv run python hello.py --backend textual # a terminal: the tui extra
179
+ uv run python hello.py # a web page, the default: the web extra
180
+ ```
181
+
182
+ The web backend serves the page at http://127.0.0.1:8000. `run` imports only the backend
183
+ that you choose, and leaves the rest of the command line to the app (`--help` lists it).
184
+
185
+ <img alt="The quickstart on the web: a text field holds Ada, and the status bar says Hello, Ada!" src="https://raw.githubusercontent.com/ehmoussi/composeui/main/docs/images/quickstart-web.png" width="600">
186
+
187
+ ### Next steps
188
+
189
+ 1. Read the [core concepts](https://ehmoussi.github.io/composeui/user-guide/core-concepts.html)
190
+ of the user guide: views, signals, the model, and studies.
191
+ 2. Build a form with its layout and its checks, in
192
+ [Building views](https://ehmoussi.github.io/composeui/user-guide/building-views.html).
193
+ 3. Run the example apps, in the order of the
194
+ [examples guide](https://ehmoussi.github.io/composeui/examples-guide.html#where-to-start).
195
+ The first,
196
+ [`src/examples/pipeform.py`](https://github.com/ehmoussi/composeui/blob/main/src/examples/pipeform.py),
197
+ has forms, radio groups, a check box, a read-only table, checks, and a File menu that
198
+ saves and opens:
199
+ `uv run python -m examples.pipeform --backend qt`, or `textual`, or `web`.
200
+
201
+ ## Documentation
202
+
203
+ The documentation site, at https://ehmoussi.github.io/composeui/, has the guides below, a
204
+ widget catalog, and the API reference.
205
+
206
+ - The [user guide](https://ehmoussi.github.io/composeui/user-guide.html) explains how to build an app: the
207
+ views, their layout, forms and their checks, the widgets, pages, tabs, dialogs, tables,
208
+ charts, [maps](https://ehmoussi.github.io/composeui/user-guide/maps.html), threads, SQLite models, CSV
209
+ imports, translations, the differences between the backends, testing an app, and a skill
210
+ for coding agents.
211
+ - The [examples guide](https://ehmoussi.github.io/composeui/examples-guide.html) says what each example app
212
+ shows, and how to run it.
213
+ - The [technical guide](https://ehmoussi.github.io/composeui/technical-guide.html) explains how ComposeUI
214
+ works inside, and how to develop it: the architecture, how to add a widget or a backend,
215
+ the tests, and the checks.
216
+ - [`CHANGELOG.md`](https://github.com/ehmoussi/composeui/blob/main/CHANGELOG.md) lists the changes of each
217
+ release.
218
+ - [`ROADMAP.md`](https://github.com/ehmoussi/composeui/blob/main/ROADMAP.md) lists the work that is left.
219
+
220
+ ## License
221
+
222
+ MIT, see [`LICENSE`](https://github.com/ehmoussi/composeui/blob/main/LICENSE).
@@ -0,0 +1,97 @@
1
+ composeui/__init__.py,sha256=UB8dn-CJ-nSFXzpWnfRwqFaE4F7RNlUTSrS99LFZXIg,341
2
+ composeui/mypy.py,sha256=ZrBCifwxkeWGX9px9y3_QT9fryuME0zk0y16teuLn5s,1883
3
+ composeui/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ composeui/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ composeui/core/application.py,sha256=kYP2rjCTwDSymvYsANUAJQgpPo0s7qX9f5Wzamzkbh8,14191
6
+ composeui/core/chartcolors.py,sha256=onjsKYpWJHgCZi6OtyX5_-uHzHVUP2mIha6Bgyz8fWA,916
7
+ composeui/core/chartimage.py,sha256=HE0B26iSu9CWqiZsdNEDbiglxolugufln6nYSuQ2_us,11884
8
+ composeui/core/dataframesource.py,sha256=q42uJ3acPenDJeNW3ruhlXKmMt2f-VB7SUi1nyJzHys,11576
9
+ composeui/core/jobs.py,sha256=Xdf3YvHKnqw4CHPrZk2gy7PklTv5Ej73M37E4fBJd3Q,17492
10
+ composeui/core/model.py,sha256=0AswlNgdL6UqiT2cUvgLhwABbzBl_GrdaXkxtXvAWK0,2355
11
+ composeui/core/registry.py,sha256=fqYIUm0rP7mSj6ewr-l2Zj_2myvQiPvJ9e4qfydAaV8,2245
12
+ composeui/core/reload.py,sha256=X9GAjmquxVvgDtqVCRsWVc4HNJ39TUqqI5C51KtM8uc,19257
13
+ composeui/core/renderer.py,sha256=7p8kMMEu3Gd88ScQakNK3wvabsi9jWFfp8OpSdjNzkg,7111
14
+ composeui/core/signal.py,sha256=N6Wpkh05F7VQweq22nxwJrELEGeInldnoSoBqfF3OiA,14105
15
+ composeui/core/sqlitemodel.py,sha256=-S2kNPuDhSwAX53KkODY9evgzTiHKaKDoG2mIMKXXG4,50152
16
+ composeui/core/study.py,sha256=LiP3BAaKpM9hPxj-ZNlqoKeIy_5QrZKy6WmpGpT2hLQ,5466
17
+ composeui/core/translation.py,sha256=GXyyBA5ER9otESrELgQ2y5P1yGtUhlpDeOkt3hM2W-Y,8158
18
+ composeui/core/translationcheck.py,sha256=wc3rPSs64WycQBKOEA8zVj_IQsxlf2wEx-NRDKwLS_k,9539
19
+ composeui/core/view.py,sha256=YBQfs5xZVkF31PAj5_nAsbwWyy_nO0DkVpO7zwD9XLA,226161
20
+ composeui/images/composeui.svg,sha256=jKQ_2oK59xCnI-wIlm7fST5og3v6yoCsVdb2Yv-_eQY,820
21
+ composeui/locales/fr.json,sha256=Ujww7htQlGbGoVmmEQujmwPRhv7WOrwLuRJASezi8PQ,2724
22
+ composeui/qtcore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ composeui/qtcore/maprenderer.py,sha256=ZUk5LK6mtjwKGg_2awUsrCUzsGL8s3G_K2ZEfRJ7MnY,4303
24
+ composeui/qtcore/qtapplication.py,sha256=d3Q0nxfEmur5QVIruZyJ7w9qd4SuDJrb57EEJPyzvIg,7803
25
+ composeui/qtcore/qtrenderer.py,sha256=zel2Xr0mRojbHYIprNHXcwcgezPzN4ltagxasxrftEk,114176
26
+ composeui/qtcore/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ composeui/qtcore/widgets/map.qml,sha256=eCqqoh2vm6xNvjqN9xVTPEIAcuR7hlacJ9sgMOAeJaw,4569
28
+ composeui/qtcore/widgets/qchart.py,sha256=3-TspCjwtELvLol0DQamtmaxh4b5P4-sdAarU-0gBjM,17750
29
+ composeui/qtcore/widgets/qdatefield.py,sha256=s_EAj40VF6o2w_YYVpTYHclDzFcTpvVkl7Byo4TRM7M,4140
30
+ composeui/qtcore/widgets/qexpander.py,sha256=6v7zdxPDv-FdAUmJdnJ8CkK3cJN4T8wzjoQvmO5bMng,2618
31
+ composeui/qtcore/widgets/qfilepathfield.py,sha256=hmmloSznorj3CTcs-_QkJQz05ta6YJ7OPoa7EQZMyq4,1364
32
+ composeui/qtcore/widgets/qfiltertable.py,sha256=kWqxoRGRnGMl0oVmj86b1EvYP2idqAvq2VZl6Gxan8k,16120
33
+ composeui/qtcore/widgets/qformdialog.py,sha256=_frY4nh-M8sL46zVIgAUQGYrGMc307xlcv8o8tjx-1M,2142
34
+ composeui/qtcore/widgets/qformlabel.py,sha256=TVudhzpZryvBOXlAzigj0hI91j58P2-hBxhU2i5OxHY,1951
35
+ composeui/qtcore/widgets/qmap.py,sha256=UXghRtSpFfZECsnK1VvorbyzmamiZRrLSdpny-X3S64,2498
36
+ composeui/qtcore/widgets/qmarkicon.py,sha256=p_hEFZ3XDj5uozoUji1i2C_28ZdXrtl5LJj5YjnJvSA,1316
37
+ composeui/qtcore/widgets/qmetric.py,sha256=pi29U1kaOevvwYkQGsC22vxEVWNHODtqddrbepXOLuw,1781
38
+ composeui/qtcore/widgets/qplaintext.py,sha256=UkGzKXTy_ANfnwLQcP9N1OU9bAQ63f6t5NramncDukI,870
39
+ composeui/qtcore/widgets/qradiogroup.py,sha256=_SmfoEC4auHA0JmVE5tARWghysc1IdFdqyFxMb5E0pc,2192
40
+ composeui/qtcore/widgets/qsidebar.py,sha256=wW-BMJ2Lwd8V8ZNJdhRgWmZwrkl38E0jRwEVckVrfyc,5058
41
+ composeui/qtcore/widgets/qsourcetable.py,sha256=W3M8fvtV0Hs8PCeJ_3b7wnU2gy4fvmw5mBiwh5ZMZI8,9359
42
+ composeui/qtcore/widgets/qsplitter.py,sha256=l4GJdk9c-oDkcT9tm5xcnyv35TKM5Lvx_OoBa1WzTlw,2568
43
+ composeui/qtcore/widgets/qtexttable.py,sha256=6p1GcJ3CNTzE5lT_SaHYW3ROizZwzyvnE65OtcxcIHU,30194
44
+ composeui/qtcore/widgets/qvaluecombobox.py,sha256=3ErfHV9_4oVtWLWPX_phUG1MuFRkDccFJ_UcdHHuyOA,1539
45
+ composeui/qtcore/widgets/qvalueslider.py,sha256=C99kn_aJEPvhv_LxS2iyJzrsgzaFTl2On8wPmv8NJwo,2669
46
+ composeui/qtcore/widgets/qwindowrelease.py,sha256=joxvMJfQgw6RwhB8W95wToFhYedbhdBDvZjYcjY26dY,1342
47
+ composeui/textualcore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ composeui/textualcore/textualapplication.py,sha256=7hGPBzvufKBqc0il0aJrDeNmleoMVYmN2lHRDfKbOns,3859
49
+ composeui/textualcore/textualrenderer.py,sha256=0XI7viMgLzIM9FE24q3c3t_vA3N6MMBE6UtV_zHOBUw,114360
50
+ composeui/textualcore/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ composeui/textualcore/widgets/composebutton.py,sha256=Ch3oHoXeuQLwLTcievg95kKSR8TVYLmhbt5Mn7ZSJHY,438
52
+ composeui/textualcore/widgets/composechart.py,sha256=E7oRYGKZ0a2hjG6UbgupKoSZ3B0AA0qLagOhNHPfz1Q,8361
53
+ composeui/textualcore/widgets/composecheckbox.py,sha256=uwZYQWcCksXbq_bOhS5Gw_iJqqn_nbHKe3rBgnpA3CY,1068
54
+ composeui/textualcore/widgets/composecollapsible.py,sha256=nIJen27SXCC0umT6rX9-UwfUpC90w2V9yF2KjghFX7Q,1520
55
+ composeui/textualcore/widgets/composecombobox.py,sha256=WxMrLwOL_hODoPUQueiU6amfYpnh2rljSzAvQ999e-E,1812
56
+ composeui/textualcore/widgets/composedateinput.py,sha256=Vq_9iishEGTVW53ml29QvOHEBY2jUQUHQBM6dZeJRbo,11393
57
+ composeui/textualcore/widgets/composedialog.py,sha256=UtdX6I0bSdChEMLQIAiaUq6tUoYlOjJi0aKPrrGmG-g,2791
58
+ composeui/textualcore/widgets/composefilepathinput.py,sha256=p5fCqLXS9Mou7p_6LJLtqxg00LUDi8ijjvcs_fHCerg,2988
59
+ composeui/textualcore/widgets/composefiltertable.py,sha256=UsH_ZZEMU1slBZa3NIrJUQ8k9xdktDU_8G4kF0Q1Los,13379
60
+ composeui/textualcore/widgets/composeformdialog.py,sha256=by4bQrjssnajplR3Eeh9nfkLpojfvqgheLeIslBPcfc,2844
61
+ composeui/textualcore/widgets/composeinput.py,sha256=NFWCOrESvK4x81ewOxrkaPPL66NnvGyXOcZwiaWuir8,1728
62
+ composeui/textualcore/widgets/composelist.py,sha256=xdz7RvmVbn5C5yj4V1lQFCEACoC5iCwC3KRCo3pa_IU,511
63
+ composeui/textualcore/widgets/composemarkdown.py,sha256=qyBOplO0wpjtMpH0ROZqD845BkVhURdLp_nTA5P5JAs,533
64
+ composeui/textualcore/widgets/composemetric.py,sha256=METhAPxbiFaYLRn3vW6_m3K_5Y0w7y0IrfOdV7xhAe8,1666
65
+ composeui/textualcore/widgets/composeradioset.py,sha256=AExRKZNVmsFIKj1E23W92yetdkzEtRZJm1kykvrE1sY,2035
66
+ composeui/textualcore/widgets/composesidebar.py,sha256=3Lvn8VTi2zSWaCkdLzeRgLDntkixLwJS9oTd6FiV7n4,3455
67
+ composeui/textualcore/widgets/composeslider.py,sha256=Gzy7MdiVBrqO3_GMxyfJeVGT3k4dyk8GT6ugTsOxfG0,5183
68
+ composeui/textualcore/widgets/composesourcetable.py,sha256=9DXqY6E5nqoW69ofG6EQj51FWhhoWSkYuKjEV2wSTWg,11556
69
+ composeui/textualcore/widgets/composesplitter.py,sha256=49v51kaEhFVgfL_wf-wQDGcgw4f2bpZMajKB9xaQihc,8225
70
+ composeui/textualcore/widgets/composetabbedcontent.py,sha256=8xy_BmB7rukR_EwSJoTX-aAbEjZWziAh03dCqtiVuQU,1494
71
+ composeui/textualcore/widgets/composetable.py,sha256=_0Uda7ibYWruBJ1HmXZCozv2dpjnmLVfyX0EJadx1BM,19903
72
+ composeui/textualcore/widgets/composetoolbar.py,sha256=aiQ137RmbFUX7ZvQv4hTGCsPhD3U94HSmulxPyWR0x8,1472
73
+ composeui/textualcore/widgets/composetree.py,sha256=2ZSxfpqVwRbJIl6BbBTqnUmhxCUn5wIPudXDaZ-vHfE,5349
74
+ composeui/webcore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
+ composeui/webcore/headers.py,sha256=Fod-rj4eG3VW2xE9bWznGh5pXFebW3IRcxtyTzowKeQ,2579
76
+ composeui/webcore/icons.py,sha256=1pwHPPr3nSEn7ZgiubUy2saqJwI8mcKIIS678hIuCwY,2053
77
+ composeui/webcore/limits.py,sha256=Vh3tpLU0KyxgwFsCuqZRHoEugEw1ifIZSf1wXr73ibA,2295
78
+ composeui/webcore/origin.py,sha256=7RyCvs-uiZrhJaCpX0ygtei6I1h9FbihqUVHUxHtjjU,2328
79
+ composeui/webcore/page.py,sha256=uMRENCDO09GTgfctqKtEMQShgdoaSxTrMVC6zDRTikg,5532
80
+ composeui/webcore/routes.py,sha256=ql_tCIfnLa2yoAZfepf3DyhcDxfNVz0NW0Wl-RPHKcE,12489
81
+ composeui/webcore/session.py,sha256=LZLyZy1fWxazonj6c-4PO7pLnRKByMUo_yLBKNB1e6I,19035
82
+ composeui/webcore/webapplication.py,sha256=k-jlMOstBSwplTxNdX7zxGZXZprzy7pJ97Ciglg59cQ,21060
83
+ composeui/webcore/webrenderer.py,sha256=-TuppI9DZh5wE35GlrLXk8mDQkTSzbLioK1DzxKGm10,217744
84
+ composeui/webcore/static/app.css,sha256=721zkPu7Yv2ksycAMy-biEwGR0z3JHJY4q04tATcDnA,147685
85
+ composeui/webcore/static/cally.js,sha256=2unIU0C1mxkbYSMXaCMMs8EEOj55AFU4sj1iZM9AHTo,39533
86
+ composeui/webcore/static/daisyui.LICENSE,sha256=hwnjrGXIRjfEItyAgriT2Zl_zgk3Ucd7LxmDvynb-eo,1071
87
+ composeui/webcore/static/deckgl.LICENSE,sha256=5Jmiwro7n6q-kf3930PjKUOSYyZLcUjlVI0OxgXM6fI,1055
88
+ composeui/webcore/static/deckgl.min.js,sha256=I04K-XppG45a6mxsqecDp7pSBv0fU9qp9nDkHbCJ3i0,1701208
89
+ composeui/webcore/static/htmx.min.js,sha256=cepnGFv6jJjDnTFxfG_OXYUjcPzf0SnbRUN3TTFFwN4,51238
90
+ composeui/webcore/static/page.js,sha256=oa5PTfk2uzqQJfutU-1R1A6lmtemqA9H-iTMEuAF7hI,51934
91
+ composeui/webcore/static/uPlot.LICENSE,sha256=j5iSKWmbT-LxoEMtDp7cM4qKkR4lDi0bAezXcKX1sb0,1078
92
+ composeui/webcore/static/uPlot.iife.min.js,sha256=GcjUxq2Ikpp59K5J1vcWFWbf0Lo9FcxJXpdPeH63jx8,51081
93
+ composeui-0.1.0.dist-info/licenses/LICENSE,sha256=fq_-yLY-RBFbGOKX1GUAGrd97hKh8qHpkrqzh6vHtaA,1080
94
+ composeui-0.1.0.dist-info/METADATA,sha256=lP_3NfrCH5Osedncfgzpa07SE4BJxHiQX-AWSueSzzo,10191
95
+ composeui-0.1.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
96
+ composeui-0.1.0.dist-info/top_level.txt,sha256=ohPTnCpCKa1CeDEmGab38AN2WcE3aLJP9ajuiYSwnh8,10
97
+ composeui-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 El Hadi Moussi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ composeui