bootstack 0.1.0a1__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 (419) hide show
  1. bootstack/__init__.py +249 -0
  2. bootstack/__main__.py +5 -0
  3. bootstack/api/__init__.py +127 -0
  4. bootstack/api/app.py +30 -0
  5. bootstack/api/constants.py +3 -0
  6. bootstack/api/data.py +23 -0
  7. bootstack/api/dialogs.py +44 -0
  8. bootstack/api/i18n.py +17 -0
  9. bootstack/api/localization.py +16 -0
  10. bootstack/api/menu.py +7 -0
  11. bootstack/api/style.py +23 -0
  12. bootstack/api/utils.py +24 -0
  13. bootstack/api/widgets.py +137 -0
  14. bootstack/assets/__init__.py +24 -0
  15. bootstack/assets/bootstack-transparent.png +0 -0
  16. bootstack/assets/bootstack.ico +0 -0
  17. bootstack/assets/bootstack.png +0 -0
  18. bootstack/assets/elements/__init__.py +0 -0
  19. bootstack/assets/elements/badge-pill.png +0 -0
  20. bootstack/assets/elements/badge-square.png +0 -0
  21. bootstack/assets/elements/border.png +0 -0
  22. bootstack/assets/elements/button-compact.png +0 -0
  23. bootstack/assets/elements/button-default.png +0 -0
  24. bootstack/assets/elements/button-group-horizontal-after-compact.png +0 -0
  25. bootstack/assets/elements/button-group-horizontal-after-default.png +0 -0
  26. bootstack/assets/elements/button-group-horizontal-before-compact.png +0 -0
  27. bootstack/assets/elements/button-group-horizontal-before-default.png +0 -0
  28. bootstack/assets/elements/button-group-horizontal-center-compact.png +0 -0
  29. bootstack/assets/elements/button-group-horizontal-center-default.png +0 -0
  30. bootstack/assets/elements/button-group-vertical-after-compact.png +0 -0
  31. bootstack/assets/elements/button-group-vertical-after-default.png +0 -0
  32. bootstack/assets/elements/button-group-vertical-before-compact.png +0 -0
  33. bootstack/assets/elements/button-group-vertical-before-default.png +0 -0
  34. bootstack/assets/elements/button-group-vertical-center-compact.png +0 -0
  35. bootstack/assets/elements/button-group-vertical-center-default.png +0 -0
  36. bootstack/assets/elements/checkbox-checked.png +0 -0
  37. bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  38. bootstack/assets/elements/checkbox-unchecked.png +0 -0
  39. bootstack/assets/elements/field.png +0 -0
  40. bootstack/assets/elements/input-after-compact.png +0 -0
  41. bootstack/assets/elements/input-after-default.png +0 -0
  42. bootstack/assets/elements/input-before-compact.png +0 -0
  43. bootstack/assets/elements/input-before-default.png +0 -0
  44. bootstack/assets/elements/input-compact.png +0 -0
  45. bootstack/assets/elements/input-default.png +0 -0
  46. bootstack/assets/elements/list-item-separated.png +0 -0
  47. bootstack/assets/elements/list-item.png +0 -0
  48. bootstack/assets/elements/manifest.toml +480 -0
  49. bootstack/assets/elements/menu-item.png +0 -0
  50. bootstack/assets/elements/nav-button-compact.png +0 -0
  51. bootstack/assets/elements/nav-button-default.png +0 -0
  52. bootstack/assets/elements/nav-icon-button-compact.png +0 -0
  53. bootstack/assets/elements/nav-icon-button-default.png +0 -0
  54. bootstack/assets/elements/notebook-client-border.png +0 -0
  55. bootstack/assets/elements/notebook-tab-active.png +0 -0
  56. bootstack/assets/elements/notebook-tab-bar.png +0 -0
  57. bootstack/assets/elements/notebook-tab-normal.png +0 -0
  58. bootstack/assets/elements/notebook-tab-pill.png +0 -0
  59. bootstack/assets/elements/progress-bar-horizontal-striped.png +0 -0
  60. bootstack/assets/elements/progress-bar-solid.png +0 -0
  61. bootstack/assets/elements/progress-bar-thin.png +0 -0
  62. bootstack/assets/elements/progress-bar-vertical-striped.png +0 -0
  63. bootstack/assets/elements/radio-selected.png +0 -0
  64. bootstack/assets/elements/radio-unselected.png +0 -0
  65. bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  66. bootstack/assets/elements/scrollbar-vertical.png +0 -0
  67. bootstack/assets/elements/slider-handle-focus.png +0 -0
  68. bootstack/assets/elements/slider-handle.png +0 -0
  69. bootstack/assets/elements/slider-track-horizontal.png +0 -0
  70. bootstack/assets/elements/slider-track-vertical.png +0 -0
  71. bootstack/assets/elements/switch-off.png +0 -0
  72. bootstack/assets/elements/switch-on.png +0 -0
  73. bootstack/assets/elements/tabs-bar-horizontal.png +0 -0
  74. bootstack/assets/elements/tabs-bar-vertical.png +0 -0
  75. bootstack/assets/elements/tabs-pill.png +0 -0
  76. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  77. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +853 -0
  78. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +875 -0
  79. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  80. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +853 -0
  81. bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  82. bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +853 -0
  83. bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  84. bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +853 -0
  85. bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  86. bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +875 -0
  87. bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  88. bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +853 -0
  89. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  90. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +853 -0
  91. bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  92. bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +851 -0
  93. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  94. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +842 -0
  95. bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  96. bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +841 -0
  97. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  98. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +914 -0
  99. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  100. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +842 -0
  101. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  102. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +841 -0
  103. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  104. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +841 -0
  105. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  106. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +842 -0
  107. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  108. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +842 -0
  109. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  110. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +842 -0
  111. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  112. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +842 -0
  113. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  114. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +842 -0
  115. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  116. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +842 -0
  117. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  118. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +842 -0
  119. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  120. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +842 -0
  121. bootstack/assets/themes/__init__.py +0 -0
  122. bootstack/assets/themes/amber-dark.json +32 -0
  123. bootstack/assets/themes/amber-light.json +32 -0
  124. bootstack/assets/themes/aurora-dark.json +32 -0
  125. bootstack/assets/themes/aurora-light.json +32 -0
  126. bootstack/assets/themes/bootstrap-dark.json +32 -0
  127. bootstack/assets/themes/bootstrap-light.json +32 -0
  128. bootstack/assets/themes/classic-dark.json +32 -0
  129. bootstack/assets/themes/classic-light.json +32 -0
  130. bootstack/assets/themes/docs-dark.json +32 -0
  131. bootstack/assets/themes/docs-light.json +32 -0
  132. bootstack/assets/themes/forest-dark.json +32 -0
  133. bootstack/assets/themes/forest-light.json +32 -0
  134. bootstack/assets/themes/ocean-dark.json +32 -0
  135. bootstack/assets/themes/ocean-light.json +32 -0
  136. bootstack/assets/themes/rose-dark.json +32 -0
  137. bootstack/assets/themes/rose-light.json +32 -0
  138. bootstack/assets/widgets/__init__.py +0 -0
  139. bootstack/assets/widgets/badge-default.png +0 -0
  140. bootstack/assets/widgets/badge-pill.png +0 -0
  141. bootstack/assets/widgets/border.png +0 -0
  142. bootstack/assets/widgets/button-group-horizontal-after.png +0 -0
  143. bootstack/assets/widgets/button-group-horizontal-before.png +0 -0
  144. bootstack/assets/widgets/button-group-horizontal-center.png +0 -0
  145. bootstack/assets/widgets/button-group-vertical-after.png +0 -0
  146. bootstack/assets/widgets/button-group-vertical-before.png +0 -0
  147. bootstack/assets/widgets/button-group-vertical-center.png +0 -0
  148. bootstack/assets/widgets/button.png +0 -0
  149. bootstack/assets/widgets/checkbox-checked.png +0 -0
  150. bootstack/assets/widgets/checkbox-indeterminate.png +0 -0
  151. bootstack/assets/widgets/checkbox-unchecked.png +0 -0
  152. bootstack/assets/widgets/field.png +0 -0
  153. bootstack/assets/widgets/icon-button.png +0 -0
  154. bootstack/assets/widgets/input-inner.png +0 -0
  155. bootstack/assets/widgets/input-prefix.png +0 -0
  156. bootstack/assets/widgets/input-suffix.png +0 -0
  157. bootstack/assets/widgets/input.png +0 -0
  158. bootstack/assets/widgets/list-item-focus.png +0 -0
  159. bootstack/assets/widgets/list-item-separated.png +0 -0
  160. bootstack/assets/widgets/menu-item-separated.png +0 -0
  161. bootstack/assets/widgets/notebook-client-border.png +0 -0
  162. bootstack/assets/widgets/notebook-pill-active.png +0 -0
  163. bootstack/assets/widgets/notebook-pill-inactive.png +0 -0
  164. bootstack/assets/widgets/notebook-tab-active.png +0 -0
  165. bootstack/assets/widgets/notebook-tab-border.png +0 -0
  166. bootstack/assets/widgets/notebook-tab-normal.png +0 -0
  167. bootstack/assets/widgets/notebook-underline.png +0 -0
  168. bootstack/assets/widgets/progress-bar-horizontal-default.png +0 -0
  169. bootstack/assets/widgets/progress-bar-horizontal-striped.png +0 -0
  170. bootstack/assets/widgets/progress-bar-vertical-default.png +0 -0
  171. bootstack/assets/widgets/progress-bar-vertical-striped.png +0 -0
  172. bootstack/assets/widgets/progress-trough-horizontal.png +0 -0
  173. bootstack/assets/widgets/progress-trough-vertical.png +0 -0
  174. bootstack/assets/widgets/radio-selected.png +0 -0
  175. bootstack/assets/widgets/radio-unselected.png +0 -0
  176. bootstack/assets/widgets/scrollbar-horizontal-rounded.png +0 -0
  177. bootstack/assets/widgets/scrollbar-vertical-rounded.png +0 -0
  178. bootstack/assets/widgets/separator-horizontal.png +0 -0
  179. bootstack/assets/widgets/separator-vertical.png +0 -0
  180. bootstack/assets/widgets/slider-handle-focus.png +0 -0
  181. bootstack/assets/widgets/slider-handle.png +0 -0
  182. bootstack/assets/widgets/slider-track-horizontal.png +0 -0
  183. bootstack/assets/widgets/slider-track-vertical.png +0 -0
  184. bootstack/assets/widgets/switch-off.png +0 -0
  185. bootstack/assets/widgets/switch-on.png +0 -0
  186. bootstack/assets/widgets/tabs-bar-horizontal.png +0 -0
  187. bootstack/assets/widgets/tabs-bar-vertical.png +0 -0
  188. bootstack/assets/widgets/tabs-pill.png +0 -0
  189. bootstack/cli/__init__.py +124 -0
  190. bootstack/cli/__main__.py +6 -0
  191. bootstack/cli/add.py +439 -0
  192. bootstack/cli/build.py +115 -0
  193. bootstack/cli/config.py +287 -0
  194. bootstack/cli/demo.py +1267 -0
  195. bootstack/cli/doctor.py +195 -0
  196. bootstack/cli/list_cmd.py +71 -0
  197. bootstack/cli/promote.py +120 -0
  198. bootstack/cli/pyinstaller.py +246 -0
  199. bootstack/cli/run.py +99 -0
  200. bootstack/cli/start.py +105 -0
  201. bootstack/cli/templates/__init__.py +861 -0
  202. bootstack/constants.py +325 -0
  203. bootstack/core/__init__.py +34 -0
  204. bootstack/core/capabilities/__init__.py +45 -0
  205. bootstack/core/capabilities/after.py +103 -0
  206. bootstack/core/capabilities/bind.py +154 -0
  207. bootstack/core/capabilities/bindtags.py +112 -0
  208. bootstack/core/capabilities/busy.py +61 -0
  209. bootstack/core/capabilities/clipboard.py +88 -0
  210. bootstack/core/capabilities/focus.py +118 -0
  211. bootstack/core/capabilities/grab.py +65 -0
  212. bootstack/core/capabilities/grid.py +188 -0
  213. bootstack/core/capabilities/localization.py +231 -0
  214. bootstack/core/capabilities/pack.py +119 -0
  215. bootstack/core/capabilities/place.py +92 -0
  216. bootstack/core/capabilities/selection.py +136 -0
  217. bootstack/core/capabilities/signals.py +242 -0
  218. bootstack/core/capabilities/winfo.py +315 -0
  219. bootstack/core/colorutils.py +234 -0
  220. bootstack/core/exceptions.py +95 -0
  221. bootstack/core/images.py +283 -0
  222. bootstack/core/localization/README.md +90 -0
  223. bootstack/core/localization/__init__.py +13 -0
  224. bootstack/core/localization/intl_format.py +580 -0
  225. bootstack/core/localization/msgcat.py +425 -0
  226. bootstack/core/localization/specs.py +143 -0
  227. bootstack/core/mixins/__init__.py +1 -0
  228. bootstack/core/mixins/ttk_state.py +35 -0
  229. bootstack/core/mixins/widget.py +132 -0
  230. bootstack/core/publisher.py +147 -0
  231. bootstack/core/signals/README.md +112 -0
  232. bootstack/core/signals/__init__.py +8 -0
  233. bootstack/core/signals/integration.py +100 -0
  234. bootstack/core/signals/signal.py +317 -0
  235. bootstack/core/signals/types.py +4 -0
  236. bootstack/core/validation/__init__.py +5 -0
  237. bootstack/core/validation/types.py +13 -0
  238. bootstack/core/validation/validation_result.py +17 -0
  239. bootstack/core/validation/validation_rules.py +112 -0
  240. bootstack/core/variables.py +62 -0
  241. bootstack/datasource/README.md +607 -0
  242. bootstack/datasource/__init__.py +51 -0
  243. bootstack/datasource/base.py +474 -0
  244. bootstack/datasource/file_source.py +541 -0
  245. bootstack/datasource/memory_source.py +482 -0
  246. bootstack/datasource/sqlite_source.py +453 -0
  247. bootstack/datasource/types.py +259 -0
  248. bootstack/dialogs/__init__.py +56 -0
  249. bootstack/dialogs/colorchooser.py +674 -0
  250. bootstack/dialogs/colordropper.py +257 -0
  251. bootstack/dialogs/datedialog.py +404 -0
  252. bootstack/dialogs/dialog.py +514 -0
  253. bootstack/dialogs/filterdialog.py +358 -0
  254. bootstack/dialogs/fontdialog.py +339 -0
  255. bootstack/dialogs/formdialog.py +541 -0
  256. bootstack/dialogs/message.py +489 -0
  257. bootstack/dialogs/query.py +561 -0
  258. bootstack/py.typed +1 -0
  259. bootstack/runtime/__init__.py +3 -0
  260. bootstack/runtime/app.py +879 -0
  261. bootstack/runtime/base_window.py +786 -0
  262. bootstack/runtime/events.py +399 -0
  263. bootstack/runtime/menu.py +510 -0
  264. bootstack/runtime/shortcuts.py +423 -0
  265. bootstack/runtime/tk_patch.py +31 -0
  266. bootstack/runtime/toplevel.py +131 -0
  267. bootstack/runtime/utility.py +371 -0
  268. bootstack/runtime/visual_focus.py +228 -0
  269. bootstack/runtime/window_utilities.py +1043 -0
  270. bootstack/style/__init__.py +5498 -0
  271. bootstack/style/bootstyle.py +507 -0
  272. bootstack/style/bootstyle_builder_base.py +752 -0
  273. bootstack/style/bootstyle_builder_mixed.py +93 -0
  274. bootstack/style/bootstyle_builder_tk.py +109 -0
  275. bootstack/style/bootstyle_builder_ttk.py +354 -0
  276. bootstack/style/builders/__init__.py +51 -0
  277. bootstack/style/builders/badge.py +44 -0
  278. bootstack/style/builders/button.py +453 -0
  279. bootstack/style/builders/buttongroup.py +344 -0
  280. bootstack/style/builders/calendar.py +271 -0
  281. bootstack/style/builders/checkbutton.py +95 -0
  282. bootstack/style/builders/combobox.py +112 -0
  283. bootstack/style/builders/contextmenu.py +268 -0
  284. bootstack/style/builders/entry.py +83 -0
  285. bootstack/style/builders/expander.py +171 -0
  286. bootstack/style/builders/field.py +312 -0
  287. bootstack/style/builders/frame.py +27 -0
  288. bootstack/style/builders/label.py +28 -0
  289. bootstack/style/builders/labelframe.py +41 -0
  290. bootstack/style/builders/listview.py +267 -0
  291. bootstack/style/builders/menubar.py +74 -0
  292. bootstack/style/builders/menubutton.py +408 -0
  293. bootstack/style/builders/notebook.py +316 -0
  294. bootstack/style/builders/panedwindow.py +25 -0
  295. bootstack/style/builders/progressbar.py +71 -0
  296. bootstack/style/builders/radiobutton.py +68 -0
  297. bootstack/style/builders/scale.py +66 -0
  298. bootstack/style/builders/scrollbar.py +360 -0
  299. bootstack/style/builders/separator.py +45 -0
  300. bootstack/style/builders/sidenav.py +313 -0
  301. bootstack/style/builders/sizegrip.py +15 -0
  302. bootstack/style/builders/spinbox.py +119 -0
  303. bootstack/style/builders/switch.py +67 -0
  304. bootstack/style/builders/tabitem.py +205 -0
  305. bootstack/style/builders/toolbutton.py +260 -0
  306. bootstack/style/builders/tooltip.py +26 -0
  307. bootstack/style/builders/treeview.py +269 -0
  308. bootstack/style/builders/utils.py +404 -0
  309. bootstack/style/builders_tk/__init__.py +16 -0
  310. bootstack/style/builders_tk/defaults.py +229 -0
  311. bootstack/style/element.py +173 -0
  312. bootstack/style/style.py +499 -0
  313. bootstack/style/theme_provider.py +449 -0
  314. bootstack/style/tk_patch.py +5 -0
  315. bootstack/style/token_maps.py +42 -0
  316. bootstack/style/types.py +32 -0
  317. bootstack/style/typography.py +527 -0
  318. bootstack/style/utility.py +696 -0
  319. bootstack/themes/__init__.py +12 -0
  320. bootstack/themes/standard.py +415 -0
  321. bootstack/themes/user.py +45 -0
  322. bootstack/widgets/__init__.py +53 -0
  323. bootstack/widgets/composites/__init__.py +38 -0
  324. bootstack/widgets/composites/accordion.py +385 -0
  325. bootstack/widgets/composites/appshell.py +445 -0
  326. bootstack/widgets/composites/buttongroup.py +391 -0
  327. bootstack/widgets/composites/calendar.py +914 -0
  328. bootstack/widgets/composites/compositeframe.py +282 -0
  329. bootstack/widgets/composites/contextmenu.py +1754 -0
  330. bootstack/widgets/composites/dateentry.py +261 -0
  331. bootstack/widgets/composites/dropdownbutton.py +190 -0
  332. bootstack/widgets/composites/expander.py +508 -0
  333. bootstack/widgets/composites/field.py +448 -0
  334. bootstack/widgets/composites/floodgauge.py +434 -0
  335. bootstack/widgets/composites/form.py +983 -0
  336. bootstack/widgets/composites/labeledscale.py +209 -0
  337. bootstack/widgets/composites/list/__init__.py +15 -0
  338. bootstack/widgets/composites/list/listitem.py +733 -0
  339. bootstack/widgets/composites/list/listview.py +1507 -0
  340. bootstack/widgets/composites/menubar.py +303 -0
  341. bootstack/widgets/composites/meter.py +882 -0
  342. bootstack/widgets/composites/numericentry.py +183 -0
  343. bootstack/widgets/composites/pagestack.py +330 -0
  344. bootstack/widgets/composites/passwordentry.py +149 -0
  345. bootstack/widgets/composites/pathentry.py +223 -0
  346. bootstack/widgets/composites/radiogroup.py +466 -0
  347. bootstack/widgets/composites/scrolledtext.py +388 -0
  348. bootstack/widgets/composites/scrolledtext.pyi +186 -0
  349. bootstack/widgets/composites/scrollview.py +675 -0
  350. bootstack/widgets/composites/selectbox.py +544 -0
  351. bootstack/widgets/composites/sidenav/__init__.py +24 -0
  352. bootstack/widgets/composites/sidenav/group.py +485 -0
  353. bootstack/widgets/composites/sidenav/header.py +83 -0
  354. bootstack/widgets/composites/sidenav/item.py +413 -0
  355. bootstack/widgets/composites/sidenav/separator.py +51 -0
  356. bootstack/widgets/composites/sidenav/view.py +919 -0
  357. bootstack/widgets/composites/spinnerentry.py +232 -0
  358. bootstack/widgets/composites/tableview/__init__.py +5 -0
  359. bootstack/widgets/composites/tableview/tableview.py +2254 -0
  360. bootstack/widgets/composites/tableview/types.py +169 -0
  361. bootstack/widgets/composites/tabs/__init__.py +6 -0
  362. bootstack/widgets/composites/tabs/tabitem.py +372 -0
  363. bootstack/widgets/composites/tabs/tabs.py +478 -0
  364. bootstack/widgets/composites/tabs/tabview.py +352 -0
  365. bootstack/widgets/composites/textentry.py +90 -0
  366. bootstack/widgets/composites/timeentry.py +189 -0
  367. bootstack/widgets/composites/toast.py +364 -0
  368. bootstack/widgets/composites/togglegroup.py +382 -0
  369. bootstack/widgets/composites/toolbar.py +393 -0
  370. bootstack/widgets/composites/tooltip.py +404 -0
  371. bootstack/widgets/internal/__init__.py +0 -0
  372. bootstack/widgets/internal/wrapper_base.py +304 -0
  373. bootstack/widgets/mixins/__init__.py +25 -0
  374. bootstack/widgets/mixins/configure_mixin.py +186 -0
  375. bootstack/widgets/mixins/entry_mixin.py +70 -0
  376. bootstack/widgets/mixins/font_mixin.py +346 -0
  377. bootstack/widgets/mixins/icon_mixin.py +38 -0
  378. bootstack/widgets/mixins/localization_mixin.py +255 -0
  379. bootstack/widgets/mixins/signal_mixin.py +272 -0
  380. bootstack/widgets/mixins/validation_mixin.py +204 -0
  381. bootstack/widgets/parts/__init__.py +11 -0
  382. bootstack/widgets/parts/numberentry_part.py +345 -0
  383. bootstack/widgets/parts/spinnerentry_part.py +394 -0
  384. bootstack/widgets/parts/textentry_part.py +344 -0
  385. bootstack/widgets/primitives/__init__.py +55 -0
  386. bootstack/widgets/primitives/badge.py +44 -0
  387. bootstack/widgets/primitives/button.py +89 -0
  388. bootstack/widgets/primitives/card.py +66 -0
  389. bootstack/widgets/primitives/checkbutton.py +124 -0
  390. bootstack/widgets/primitives/checktoggle.py +53 -0
  391. bootstack/widgets/primitives/combobox.py +165 -0
  392. bootstack/widgets/primitives/entry.py +98 -0
  393. bootstack/widgets/primitives/frame.py +206 -0
  394. bootstack/widgets/primitives/gridframe.py +479 -0
  395. bootstack/widgets/primitives/label.py +95 -0
  396. bootstack/widgets/primitives/labelframe.py +63 -0
  397. bootstack/widgets/primitives/menubutton.py +118 -0
  398. bootstack/widgets/primitives/notebook.py +551 -0
  399. bootstack/widgets/primitives/optionmenu.py +248 -0
  400. bootstack/widgets/primitives/packframe.py +228 -0
  401. bootstack/widgets/primitives/panedwindow.py +58 -0
  402. bootstack/widgets/primitives/progressbar.py +95 -0
  403. bootstack/widgets/primitives/radiobutton.py +115 -0
  404. bootstack/widgets/primitives/radiotoggle.py +50 -0
  405. bootstack/widgets/primitives/scale.py +85 -0
  406. bootstack/widgets/primitives/scrollbar.py +56 -0
  407. bootstack/widgets/primitives/separator.py +56 -0
  408. bootstack/widgets/primitives/sizegrip.py +47 -0
  409. bootstack/widgets/primitives/spinbox.py +91 -0
  410. bootstack/widgets/primitives/switch.py +41 -0
  411. bootstack/widgets/primitives/treeview.py +77 -0
  412. bootstack/widgets/types.py +20 -0
  413. bootstack-0.1.0a1.dist-info/METADATA +196 -0
  414. bootstack-0.1.0a1.dist-info/RECORD +419 -0
  415. bootstack-0.1.0a1.dist-info/WHEEL +5 -0
  416. bootstack-0.1.0a1.dist-info/entry_points.txt +2 -0
  417. bootstack-0.1.0a1.dist-info/licenses/LICENSE +22 -0
  418. bootstack-0.1.0a1.dist-info/licenses/NOTICE +10 -0
  419. bootstack-0.1.0a1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,474 @@
1
+ """Abstract base class for datasource implementations.
2
+
3
+ Provides a common foundation for all datasource implementations with:
4
+ - Abstract method definitions enforcing the DataSourceProtocol interface
5
+ - Shared utility methods for type inference, literal parsing, and validation
6
+ - Template methods for common operations
7
+ - Hook methods for extensibility
8
+
9
+ Subclasses must implement storage-specific operations (set_data, get_page, CRUD, etc.)
10
+ while inheriting common utilities and patterns.
11
+
12
+ This base class makes it easier to:
13
+ - Create custom datasource implementations
14
+ - Reduce code duplication across implementations
15
+ - Ensure consistent behavior across all datasources
16
+ - Extend datasource functionality through hooks
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from abc import ABC, abstractmethod
22
+ from typing import Any, Dict, List, Optional, Sequence, Mapping
23
+
24
+ from bootstack.datasource.types import Primitive, Record
25
+
26
+
27
+ class BaseDataSource(ABC):
28
+ """Abstract base class for datasource implementations.
29
+
30
+ Provides shared utilities and enforces the DataSourceProtocol interface through
31
+ abstract methods. Subclasses implement storage-specific logic while inheriting
32
+ common functionality.
33
+
34
+ Args:
35
+ page_size(int): Number of records per page (default: 10)
36
+
37
+ Attributes:
38
+ page_size: Current page size setting
39
+
40
+ Example:
41
+ ```python
42
+ class RedisDataSource(BaseDataSource):
43
+ def __init__(self, redis_client, page_size=10):
44
+ super().__init__(page_size)
45
+ self.redis = redis_client
46
+
47
+ def set_data(self, records):
48
+ pass # Redis-specific implementation
49
+
50
+ def get_page(self, page=None):
51
+ pass # Redis-specific implementation
52
+ ```
53
+ """
54
+
55
+ def __init__(self, page_size: int = 10):
56
+ """Initialize base datasource with pagination settings.
57
+
58
+ Args:
59
+ page_size: Number of records returned per page when paginating.
60
+ """
61
+ self.page_size = page_size
62
+ self._page = 0
63
+
64
+ # ========== ABSTRACT METHODS - MUST BE IMPLEMENTED ==========
65
+
66
+ # Data & View Configuration
67
+ @abstractmethod
68
+ def set_data(self, records: Sequence[Primitive] | Sequence[Mapping[str, Any]]) -> 'BaseDataSource':
69
+ """Load data records into the datasource.
70
+
71
+ Args:
72
+ records: Sequence of records (dicts) or primitives (auto-wrapped)
73
+
74
+ Returns:
75
+ Self for method chaining
76
+ """
77
+ ...
78
+
79
+ @abstractmethod
80
+ def set_filter(self, where_sql: str = "") -> None:
81
+ """Apply SQL-like WHERE clause filter to data.
82
+
83
+ Args:
84
+ where_sql: SQL WHERE condition (e.g., "age > 25 AND status = 'active'")
85
+ """
86
+ ...
87
+
88
+ @abstractmethod
89
+ def set_sort(self, order_by_sql: str = "") -> None:
90
+ """Apply SQL-like ORDER BY clause to data.
91
+
92
+ Args:
93
+ order_by_sql: SQL ORDER BY clause (e.g., "name ASC, age DESC")
94
+ """
95
+ ...
96
+
97
+ # Pagination
98
+ @abstractmethod
99
+ def get_page(self, page: Optional[int] = None) -> List[Record]:
100
+ """Get records for specified page (or current page if None).
101
+
102
+ Args:
103
+ page: Page number (0-indexed); updates current page if provided
104
+
105
+ Returns:
106
+ List of record dictionaries for the page
107
+ """
108
+ ...
109
+
110
+ @abstractmethod
111
+ def next_page(self) -> List[Record]:
112
+ """Advance to next page and return its records.
113
+
114
+ Returns:
115
+ List of record dictionaries for the new page
116
+ """
117
+ ...
118
+
119
+ @abstractmethod
120
+ def prev_page(self) -> List[Record]:
121
+ """Move to previous page and return its records.
122
+
123
+ Returns:
124
+ List of record dictionaries for the new page
125
+ """
126
+ ...
127
+
128
+ @abstractmethod
129
+ def has_next_page(self) -> bool:
130
+ """Check if more pages exist after current page.
131
+
132
+ Returns:
133
+ True if next page exists, False otherwise
134
+ """
135
+ ...
136
+
137
+ @abstractmethod
138
+ def total_count(self) -> int:
139
+ """Get total number of records matching current filter.
140
+
141
+ Returns:
142
+ Total record count (respects active filter)
143
+ """
144
+ ...
145
+
146
+ # CRUD Operations
147
+ @abstractmethod
148
+ def create_record(self, record: Dict[str, Any]) -> int:
149
+ """Create new record and return its ID.
150
+
151
+ Args:
152
+ record: Dictionary with record data
153
+
154
+ Returns:
155
+ The ID assigned to the new record
156
+ """
157
+ ...
158
+
159
+ @abstractmethod
160
+ def read_record(self, record_id: Any) -> Optional[Record]:
161
+ """Retrieve single record by ID.
162
+
163
+ Args:
164
+ record_id: Unique identifier of the record
165
+
166
+ Returns:
167
+ Record dictionary or None if not found
168
+ """
169
+ ...
170
+
171
+ @abstractmethod
172
+ def update_record(self, record_id: Any, updates: Dict[str, Any]) -> bool:
173
+ """Update record fields by ID.
174
+
175
+ Args:
176
+ record_id: Unique identifier of the record
177
+ updates: Dictionary with fields to update
178
+
179
+ Returns:
180
+ True if record was updated, False if not found
181
+ """
182
+ ...
183
+
184
+ @abstractmethod
185
+ def delete_record(self, record_id: Any) -> bool:
186
+ """Delete record by ID.
187
+
188
+ Args:
189
+ record_id: Unique identifier of the record
190
+
191
+ Returns:
192
+ True if record was deleted, False if not found
193
+ """
194
+ ...
195
+
196
+ # Selection Management
197
+ @abstractmethod
198
+ def select_record(self, record_id: Any) -> bool:
199
+ """Mark record as selected.
200
+
201
+ Args:
202
+ record_id: Unique identifier of the record
203
+
204
+ Returns:
205
+ True if record was selected, False if not found
206
+ """
207
+ ...
208
+
209
+ @abstractmethod
210
+ def unselect_record(self, record_id: Any) -> bool:
211
+ """Mark record as unselected.
212
+
213
+ Args:
214
+ record_id: Unique identifier of the record
215
+
216
+ Returns:
217
+ True if record was unselected, False if not found
218
+ """
219
+ ...
220
+
221
+ @abstractmethod
222
+ def select_all(self, current_page_only: bool = False) -> int:
223
+ """Select all records (optionally only current page).
224
+
225
+ Args:
226
+ current_page_only: If True, select only records on current page
227
+
228
+ Returns:
229
+ Number of records selected
230
+ """
231
+ ...
232
+
233
+ @abstractmethod
234
+ def unselect_all(self, current_page_only: bool = False) -> int:
235
+ """Unselect all records (optionally only current page).
236
+
237
+ Args:
238
+ current_page_only: If True, unselect only records on current page
239
+
240
+ Returns:
241
+ Number of records unselected
242
+ """
243
+ ...
244
+
245
+ @abstractmethod
246
+ def get_selected(self, page: Optional[int] = None) -> List[Record]:
247
+ """Get selected records, optionally paginated.
248
+
249
+ Args:
250
+ page: Optional page number for paginating selected records
251
+
252
+ Returns:
253
+ List of selected record dictionaries
254
+ """
255
+ ...
256
+
257
+ @abstractmethod
258
+ def selected_count(self) -> int:
259
+ """Get total number of selected records.
260
+
261
+ Returns:
262
+ Count of selected records
263
+ """
264
+ ...
265
+
266
+ # Export
267
+ @abstractmethod
268
+ def export_to_csv(self, filepath: str, include_all: bool = True) -> None:
269
+ """Export records to CSV file.
270
+
271
+ Args:
272
+ filepath: Path to output CSV file
273
+ include_all: If True, export all records; if False, export only selected
274
+ """
275
+ ...
276
+
277
+ # Index-based Access
278
+ @abstractmethod
279
+ def get_page_from_index(self, start_index: int, count: int) -> List[Record]:
280
+ """Get records by start index and count (respects filter/sort).
281
+
282
+ Args:
283
+ start_index: Starting record index
284
+ count: Number of records to retrieve
285
+
286
+ Returns:
287
+ List of record dictionaries
288
+ """
289
+ ...
290
+
291
+ # ========== SHARED UTILITY METHODS ==========
292
+
293
+ @staticmethod
294
+ def _infer_type(value: Any) -> str:
295
+ """Infer SQL-compatible type from Python value.
296
+
297
+ Args:
298
+ value: Python value to infer type from
299
+
300
+ Returns:
301
+ SQL type string ('INTEGER', 'REAL', 'BLOB', or 'TEXT')
302
+
303
+ Examples:
304
+ >>> BaseDataSource._infer_type(42)
305
+ 'INTEGER'
306
+ >>> BaseDataSource._infer_type(3.14)
307
+ 'REAL'
308
+ >>> BaseDataSource._infer_type("hello")
309
+ 'TEXT'
310
+ """
311
+ if isinstance(value, int):
312
+ return "INTEGER"
313
+ elif isinstance(value, float):
314
+ return "REAL"
315
+ elif isinstance(value, (bytes, bytearray)):
316
+ return "BLOB"
317
+ return "TEXT"
318
+
319
+ @staticmethod
320
+ def _is_mapping(x: Any) -> bool:
321
+ """Check if value is a mapping (dict-like).
322
+
323
+ Args:
324
+ x: Value to check
325
+
326
+ Returns:
327
+ True if value is a mapping, False otherwise
328
+
329
+ Examples:
330
+ >>> BaseDataSource._is_mapping({'a': 1})
331
+ True
332
+ >>> BaseDataSource._is_mapping([1, 2, 3])
333
+ False
334
+ """
335
+ return isinstance(x, Mapping)
336
+
337
+ @staticmethod
338
+ def _coerce_literal(s: str) -> Any:
339
+ """Parse string literal into Python value (int, float, bool, None, or str).
340
+
341
+ Converts SQL/JSON-like literal strings into appropriate Python types:
342
+ - Quoted strings ('foo', "bar") -> str
343
+ - true/false -> bool
344
+ - null/none -> None
345
+ - Numeric strings -> int or float
346
+ - Everything else -> str
347
+
348
+ Args:
349
+ s: String literal to parse
350
+
351
+ Returns:
352
+ Parsed Python value
353
+
354
+ Examples:
355
+ >>> BaseDataSource._coerce_literal("'hello'")
356
+ 'hello'
357
+ >>> BaseDataSource._coerce_literal("42")
358
+ 42
359
+ >>> BaseDataSource._coerce_literal("3.14")
360
+ 3.14
361
+ >>> BaseDataSource._coerce_literal("true")
362
+ True
363
+ >>> BaseDataSource._coerce_literal("null")
364
+ None
365
+ """
366
+ t = s.strip()
367
+
368
+ # Handle quoted strings
369
+ if len(t) >= 2 and ((t[0] == t[-1] == "'") or (t[0] == t[-1] == '"')):
370
+ return t[1:-1]
371
+
372
+ # Handle booleans
373
+ if t.lower() == "true":
374
+ return True
375
+ if t.lower() == "false":
376
+ return False
377
+
378
+ # Handle null/none
379
+ if t.lower() in ("null", "none"):
380
+ return None
381
+
382
+ # Try numeric conversion
383
+ try:
384
+ return int(t)
385
+ except Exception:
386
+ pass
387
+
388
+ try:
389
+ return float(t)
390
+ except Exception:
391
+ pass
392
+
393
+ # Default to string
394
+ return t
395
+
396
+ @staticmethod
397
+ def _validate_record(record: Any) -> None:
398
+ """Validate that a record is a dictionary.
399
+
400
+ Args:
401
+ record: Value to validate
402
+
403
+ Raises:
404
+ ValueError: If record is not a dictionary
405
+ """
406
+ if not isinstance(record, dict):
407
+ raise ValueError(f"Record must be a dictionary, got {type(record).__name__}")
408
+
409
+ # ========== HOOK METHODS (Can be overridden by subclasses) ==========
410
+
411
+ def _before_create(self, record: Dict[str, Any]) -> Dict[str, Any]:
412
+ """Hook called before creating a record.
413
+
414
+ Subclasses can override this to perform validation, transformation,
415
+ or side effects before record creation.
416
+
417
+ Args:
418
+ record: Record about to be created
419
+
420
+ Returns:
421
+ Modified record (or original if no changes)
422
+ """
423
+ return record
424
+
425
+ def _after_create(self, record_id: int, record: Dict[str, Any]) -> None:
426
+ """Hook called after creating a record.
427
+
428
+ Subclasses can override this to perform logging, caching updates,
429
+ or other side effects after record creation.
430
+
431
+ Args:
432
+ record_id: ID of the created record
433
+ record: The created record
434
+ """
435
+ pass
436
+
437
+ def _before_update(self, record_id: Any, updates: Dict[str, Any]) -> Dict[str, Any]:
438
+ """Hook called before updating a record.
439
+
440
+ Args:
441
+ record_id: ID of record being updated
442
+ updates: Updates to apply
443
+
444
+ Returns:
445
+ Modified updates (or original if no changes)
446
+ """
447
+ return updates
448
+
449
+ def _after_update(self, record_id: Any, updates: Dict[str, Any], success: bool) -> None:
450
+ """Hook called after updating a record.
451
+
452
+ Args:
453
+ record_id: ID of updated record
454
+ updates: Updates that were applied
455
+ success: Whether the update succeeded
456
+ """
457
+ pass
458
+
459
+ def _before_delete(self, record_id: Any) -> None:
460
+ """Hook called before deleting a record.
461
+
462
+ Args:
463
+ record_id: ID of record about to be deleted
464
+ """
465
+ pass
466
+
467
+ def _after_delete(self, record_id: Any, success: bool) -> None:
468
+ """Hook called after deleting a record.
469
+
470
+ Args:
471
+ record_id: ID of deleted record
472
+ success: Whether the deletion succeeded
473
+ """
474
+ pass