bootstack 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.
- bootstack/__init__.py +157 -0
- bootstack/__main__.py +5 -0
- bootstack/_core/__init__.py +21 -0
- bootstack/_core/capabilities/__init__.py +45 -0
- bootstack/_core/capabilities/after.py +103 -0
- bootstack/_core/capabilities/bind.py +192 -0
- bootstack/_core/capabilities/bindtags.py +112 -0
- bootstack/_core/capabilities/busy.py +72 -0
- bootstack/_core/capabilities/clipboard.py +89 -0
- bootstack/_core/capabilities/focus.py +118 -0
- bootstack/_core/capabilities/grab.py +65 -0
- bootstack/_core/capabilities/grid.py +211 -0
- bootstack/_core/capabilities/localization.py +231 -0
- bootstack/_core/capabilities/pack.py +140 -0
- bootstack/_core/capabilities/place.py +113 -0
- bootstack/_core/capabilities/selection.py +136 -0
- bootstack/_core/capabilities/signals.py +244 -0
- bootstack/_core/capabilities/winfo.py +315 -0
- bootstack/_core/colorutils.py +234 -0
- bootstack/_core/exceptions.py +25 -0
- bootstack/_core/images.py +463 -0
- bootstack/_core/mixins/__init__.py +1 -0
- bootstack/_core/mixins/ttk_state.py +35 -0
- bootstack/_core/mixins/widget.py +132 -0
- bootstack/_core/paths.py +49 -0
- bootstack/_core/publisher.py +149 -0
- bootstack/_core/variables.py +62 -0
- bootstack/_runtime/__init__.py +3 -0
- bootstack/_runtime/app.py +930 -0
- bootstack/_runtime/base_window.py +945 -0
- bootstack/_runtime/events.py +399 -0
- bootstack/_runtime/shortcuts.py +496 -0
- bootstack/_runtime/tk_patch.py +43 -0
- bootstack/_runtime/toplevel.py +276 -0
- bootstack/_runtime/utility.py +457 -0
- bootstack/_runtime/visual_focus.py +240 -0
- bootstack/_runtime/window_utilities.py +1123 -0
- bootstack/assets/__init__.py +21 -0
- bootstack/assets/bootstack.ico +0 -0
- bootstack/assets/bootstack.png +0 -0
- bootstack/assets/elements/__init__.py +0 -0
- bootstack/assets/elements/badge-pill.png +0 -0
- bootstack/assets/elements/badge-square.png +0 -0
- bootstack/assets/elements/button-compact.png +0 -0
- bootstack/assets/elements/button-default.png +0 -0
- bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
- bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
- bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
- bootstack/assets/elements/card.png +0 -0
- bootstack/assets/elements/checkbox-checked.png +0 -0
- bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- bootstack/assets/elements/checkbox-unchecked.png +0 -0
- bootstack/assets/elements/field.png +0 -0
- bootstack/assets/elements/input-addon-compact.png +0 -0
- bootstack/assets/elements/input-addon-default.png +0 -0
- bootstack/assets/elements/input-compact.png +0 -0
- bootstack/assets/elements/input-default.png +0 -0
- bootstack/assets/elements/list-item-separated.png +0 -0
- bootstack/assets/elements/list-item.png +0 -0
- bootstack/assets/elements/listrow-compact.png +0 -0
- bootstack/assets/elements/listrow-default.png +0 -0
- bootstack/assets/elements/manifest.toml +361 -0
- bootstack/assets/elements/menu-item.png +0 -0
- bootstack/assets/elements/navitem-compact.png +0 -0
- bootstack/assets/elements/navitem-default.png +0 -0
- bootstack/assets/elements/progressbar-h-compact.png +0 -0
- bootstack/assets/elements/progressbar-h-default.png +0 -0
- bootstack/assets/elements/progressbar-v-compact.png +0 -0
- bootstack/assets/elements/progressbar-v-default.png +0 -0
- bootstack/assets/elements/radiobutton.png +0 -0
- bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- bootstack/assets/elements/scrollbar-vertical.png +0 -0
- bootstack/assets/elements/slider-handle.png +0 -0
- bootstack/assets/elements/slider-track-h.png +0 -0
- bootstack/assets/elements/slider-track-v.png +0 -0
- bootstack/assets/elements/switch-off.png +0 -0
- bootstack/assets/elements/switch-on.png +0 -0
- bootstack/assets/elements/tab-h.png +0 -0
- bootstack/assets/elements/tab-v.png +0 -0
- bootstack/assets/icons/bootstrap.ttf +0 -0
- bootstack/assets/icons/glyphmap.json +2080 -0
- bootstack/assets/icons/icon_metrics.json +12470 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +878 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +878 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +854 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +917 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +845 -0
- bootstack/cli/__init__.py +133 -0
- bootstack/cli/__main__.py +6 -0
- bootstack/cli/add.py +395 -0
- bootstack/cli/appicon.py +285 -0
- bootstack/cli/build.py +115 -0
- bootstack/cli/config.py +313 -0
- bootstack/cli/demo.py +564 -0
- bootstack/cli/dev.py +153 -0
- bootstack/cli/doctor.py +195 -0
- bootstack/cli/icons.py +98 -0
- bootstack/cli/promote.py +120 -0
- bootstack/cli/pyinstaller.py +268 -0
- bootstack/cli/run.py +95 -0
- bootstack/cli/start.py +117 -0
- bootstack/cli/templates/__init__.py +931 -0
- bootstack/clipboard.py +48 -0
- bootstack/constants.py +318 -0
- bootstack/data/README.md +615 -0
- bootstack/data/__init__.py +78 -0
- bootstack/data/_observable.py +276 -0
- bootstack/data/base.py +780 -0
- bootstack/data/file_source.py +367 -0
- bootstack/data/memory_source.py +450 -0
- bootstack/data/query.py +367 -0
- bootstack/data/readers.py +289 -0
- bootstack/data/sqlite_source.py +869 -0
- bootstack/data/types.py +354 -0
- bootstack/data/writers.py +232 -0
- bootstack/dev/__init__.py +36 -0
- bootstack/dev/_capture.py +141 -0
- bootstack/dev/_env.py +43 -0
- bootstack/dev/_registry.py +140 -0
- bootstack/dev/_reloader.py +351 -0
- bootstack/dev/_reset.py +50 -0
- bootstack/dev/_watcher.py +91 -0
- bootstack/dialogs/__init__.py +948 -0
- bootstack/dialogs/_impl/__init__.py +47 -0
- bootstack/dialogs/_impl/colorchooser.py +588 -0
- bootstack/dialogs/_impl/datedialog.py +450 -0
- bootstack/dialogs/_impl/dialog.py +594 -0
- bootstack/dialogs/_impl/filterdialog.py +358 -0
- bootstack/dialogs/_impl/fontdialog.py +364 -0
- bootstack/dialogs/_impl/formdialog.py +564 -0
- bootstack/dialogs/_impl/message.py +486 -0
- bootstack/dialogs/_impl/query.py +570 -0
- bootstack/errors.py +67 -0
- bootstack/events/__init__.py +111 -0
- bootstack/events/_event.py +135 -0
- bootstack/events/_payloads.py +539 -0
- bootstack/events/_subscription.py +38 -0
- bootstack/i18n/README.md +77 -0
- bootstack/i18n/__init__.py +23 -0
- bootstack/i18n/catalog.py +121 -0
- bootstack/i18n/intl_format.py +584 -0
- bootstack/i18n/msgcat.py +425 -0
- bootstack/i18n/specs.py +156 -0
- bootstack/images.py +563 -0
- bootstack/py.typed +1 -0
- bootstack/scheduling/__init__.py +11 -0
- bootstack/scheduling/_schedule.py +218 -0
- bootstack/shortcuts.py +21 -0
- bootstack/signals/README.md +98 -0
- bootstack/signals/__init__.py +10 -0
- bootstack/signals/integration.py +100 -0
- bootstack/signals/signal.py +353 -0
- bootstack/signals/types.py +6 -0
- bootstack/store.py +286 -0
- bootstack/streams/__init__.py +12 -0
- bootstack/streams/_stream.py +321 -0
- bootstack/style/__init__.py +38 -0
- bootstack/style/builders/__init__.py +51 -0
- bootstack/style/builders/badge.py +46 -0
- bootstack/style/builders/button.py +339 -0
- bootstack/style/builders/buttongroup.py +311 -0
- bootstack/style/builders/calendar.py +271 -0
- bootstack/style/builders/checkbutton.py +110 -0
- bootstack/style/builders/combobox.py +113 -0
- bootstack/style/builders/contextmenu.py +268 -0
- bootstack/style/builders/entry.py +82 -0
- bootstack/style/builders/expander.py +148 -0
- bootstack/style/builders/field.py +335 -0
- bootstack/style/builders/frame.py +50 -0
- bootstack/style/builders/label.py +28 -0
- bootstack/style/builders/labelframe.py +34 -0
- bootstack/style/builders/listview.py +369 -0
- bootstack/style/builders/menubar.py +91 -0
- bootstack/style/builders/menubutton.py +359 -0
- bootstack/style/builders/panedwindow.py +25 -0
- bootstack/style/builders/progressbar.py +67 -0
- bootstack/style/builders/radiobutton.py +99 -0
- bootstack/style/builders/scale.py +64 -0
- bootstack/style/builders/scrollbar.py +225 -0
- bootstack/style/builders/separator.py +49 -0
- bootstack/style/builders/sidenav.py +643 -0
- bootstack/style/builders/sizegrip.py +15 -0
- bootstack/style/builders/spinbox.py +119 -0
- bootstack/style/builders/switch.py +70 -0
- bootstack/style/builders/tabitem.py +204 -0
- bootstack/style/builders/togglegroup.py +294 -0
- bootstack/style/builders/toolbutton.py +275 -0
- bootstack/style/builders/tooltip.py +26 -0
- bootstack/style/builders/treeview.py +193 -0
- bootstack/style/builders/utils.py +455 -0
- bootstack/style/builders_tk/__init__.py +16 -0
- bootstack/style/builders_tk/defaults.py +229 -0
- bootstack/style/element.py +173 -0
- bootstack/style/fonts.py +123 -0
- bootstack/style/style.py +609 -0
- bootstack/style/style_builder_base.py +716 -0
- bootstack/style/style_builder_mixed.py +93 -0
- bootstack/style/style_builder_tk.py +109 -0
- bootstack/style/style_builder_ttk.py +353 -0
- bootstack/style/style_resolver.py +447 -0
- bootstack/style/theme.py +245 -0
- bootstack/style/theme_provider.py +471 -0
- bootstack/style/themes/__init__.py +128 -0
- bootstack/style/tk_patch.py +5 -0
- bootstack/style/token_maps.py +41 -0
- bootstack/style/types.py +32 -0
- bootstack/style/typography.py +523 -0
- bootstack/style/utility.py +746 -0
- bootstack/types.py +39 -0
- bootstack/validation/__init__.py +6 -0
- bootstack/validation/types.py +15 -0
- bootstack/validation/validation_result.py +17 -0
- bootstack/validation/validation_rules.py +205 -0
- bootstack/widgets/__init__.py +74 -0
- bootstack/widgets/_core/__init__.py +31 -0
- bootstack/widgets/_core/app_config.py +266 -0
- bootstack/widgets/_core/base.py +461 -0
- bootstack/widgets/_core/container.py +334 -0
- bootstack/widgets/_core/context.py +35 -0
- bootstack/widgets/_core/events.py +130 -0
- bootstack/widgets/_core/field_mixin.py +353 -0
- bootstack/widgets/_core/icon_image_props.py +72 -0
- bootstack/widgets/_core/image_binding.py +93 -0
- bootstack/widgets/_core/navmodel.py +345 -0
- bootstack/widgets/_core/options.py +210 -0
- bootstack/widgets/_core/selection_group.py +130 -0
- bootstack/widgets/_core/window_controls.py +96 -0
- bootstack/widgets/_core/window_menu.py +246 -0
- bootstack/widgets/_impl/__init__.py +1 -0
- bootstack/widgets/_impl/_internal/__init__.py +0 -0
- bootstack/widgets/_impl/_internal/wrapper_base.py +307 -0
- bootstack/widgets/_impl/_parts/__init__.py +11 -0
- bootstack/widgets/_impl/_parts/numberentry_part.py +385 -0
- bootstack/widgets/_impl/_parts/spinnerentry_part.py +434 -0
- bootstack/widgets/_impl/_parts/textentry_part.py +406 -0
- bootstack/widgets/_impl/composites/__init__.py +33 -0
- bootstack/widgets/_impl/composites/_dateutils.py +33 -0
- bootstack/widgets/_impl/composites/_image_fit.py +105 -0
- bootstack/widgets/_impl/composites/accordion.py +381 -0
- bootstack/widgets/_impl/composites/avatar.py +191 -0
- bootstack/widgets/_impl/composites/buttongroup.py +371 -0
- bootstack/widgets/_impl/composites/calendar.py +972 -0
- bootstack/widgets/_impl/composites/carousel.py +567 -0
- bootstack/widgets/_impl/composites/chart.py +882 -0
- bootstack/widgets/_impl/composites/compositeframe.py +298 -0
- bootstack/widgets/_impl/composites/contextmenu.py +1951 -0
- bootstack/widgets/_impl/composites/dateentry.py +404 -0
- bootstack/widgets/_impl/composites/dropdownbutton.py +325 -0
- bootstack/widgets/_impl/composites/expander.py +515 -0
- bootstack/widgets/_impl/composites/field.py +670 -0
- bootstack/widgets/_impl/composites/form.py +1066 -0
- bootstack/widgets/_impl/composites/gallery.py +551 -0
- bootstack/widgets/_impl/composites/list/__init__.py +15 -0
- bootstack/widgets/_impl/composites/list/listitem.py +802 -0
- bootstack/widgets/_impl/composites/list/listview.py +1433 -0
- bootstack/widgets/_impl/composites/menu/__init__.py +18 -0
- bootstack/widgets/_impl/composites/menu/model.py +358 -0
- bootstack/widgets/_impl/composites/menu/render_native.py +134 -0
- bootstack/widgets/_impl/composites/menu/render_themed.py +134 -0
- bootstack/widgets/_impl/composites/meter.py +860 -0
- bootstack/widgets/_impl/composites/numericentry.py +201 -0
- bootstack/widgets/_impl/composites/pagestack.py +395 -0
- bootstack/widgets/_impl/composites/passwordentry.py +142 -0
- bootstack/widgets/_impl/composites/pathentry.py +168 -0
- bootstack/widgets/_impl/composites/picture.py +289 -0
- bootstack/widgets/_impl/composites/radiogroup.py +511 -0
- bootstack/widgets/_impl/composites/scrolledtext.py +375 -0
- bootstack/widgets/_impl/composites/scrolledtext.pyi +186 -0
- bootstack/widgets/_impl/composites/scrollview.py +764 -0
- bootstack/widgets/_impl/composites/selectbox.py +1026 -0
- bootstack/widgets/_impl/composites/shell/__init__.py +40 -0
- bootstack/widgets/_impl/composites/shell/content_host.py +52 -0
- bootstack/widgets/_impl/composites/shell/layout.py +335 -0
- bootstack/widgets/_impl/composites/shell/nav_panel.py +345 -0
- bootstack/widgets/_impl/composites/shell/providers.py +558 -0
- bootstack/widgets/_impl/composites/shell/rail.py +117 -0
- bootstack/widgets/_impl/composites/shell/shell.py +581 -0
- bootstack/widgets/_impl/composites/shell/workspace.py +273 -0
- bootstack/widgets/_impl/composites/sidenav/__init__.py +16 -0
- bootstack/widgets/_impl/composites/sidenav/header.py +81 -0
- bootstack/widgets/_impl/composites/sidenav/separator.py +44 -0
- bootstack/widgets/_impl/composites/slider/__init__.py +7 -0
- bootstack/widgets/_impl/composites/slider/_shared.py +195 -0
- bootstack/widgets/_impl/composites/slider/rangeslider.py +982 -0
- bootstack/widgets/_impl/composites/slider/slider.py +851 -0
- bootstack/widgets/_impl/composites/spinnerentry.py +185 -0
- bootstack/widgets/_impl/composites/tableview/__init__.py +5 -0
- bootstack/widgets/_impl/composites/tableview/tableview.py +3388 -0
- bootstack/widgets/_impl/composites/tableview/types.py +169 -0
- bootstack/widgets/_impl/composites/tabs/__init__.py +23 -0
- bootstack/widgets/_impl/composites/tabs/tabitem.py +389 -0
- bootstack/widgets/_impl/composites/tabs/tabs.py +974 -0
- bootstack/widgets/_impl/composites/tabs/tabview.py +650 -0
- bootstack/widgets/_impl/composites/textarea/__init__.py +26 -0
- bootstack/widgets/_impl/composites/textarea/change.py +46 -0
- bootstack/widgets/_impl/composites/textarea/codeeditor.py +526 -0
- bootstack/widgets/_impl/composites/textarea/core.py +495 -0
- bootstack/widgets/_impl/composites/textarea/decoration.py +42 -0
- bootstack/widgets/_impl/composites/textarea/diff.py +127 -0
- bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +1 -0
- bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +138 -0
- bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +158 -0
- bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +138 -0
- bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +312 -0
- bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
- bootstack/widgets/_impl/composites/textarea/filter.py +171 -0
- bootstack/widgets/_impl/composites/textarea/search_overlay.py +459 -0
- bootstack/widgets/_impl/composites/textarea/sidebar.py +88 -0
- bootstack/widgets/_impl/composites/textarea/style_registry.py +178 -0
- bootstack/widgets/_impl/composites/textarea/textarea.py +606 -0
- bootstack/widgets/_impl/composites/textarea/undo.py +217 -0
- bootstack/widgets/_impl/composites/textentry.py +57 -0
- bootstack/widgets/_impl/composites/timeentry.py +176 -0
- bootstack/widgets/_impl/composites/toast.py +390 -0
- bootstack/widgets/_impl/composites/toast_stack.py +156 -0
- bootstack/widgets/_impl/composites/togglegroup.py +418 -0
- bootstack/widgets/_impl/composites/toolbar.py +608 -0
- bootstack/widgets/_impl/composites/tooltip.py +491 -0
- bootstack/widgets/_impl/composites/tree/__init__.py +7 -0
- bootstack/widgets/_impl/composites/tree/source_binding.py +136 -0
- bootstack/widgets/_impl/composites/tree/treeitem.py +393 -0
- bootstack/widgets/_impl/composites/tree/treenode.py +174 -0
- bootstack/widgets/_impl/composites/tree/treeview.py +841 -0
- bootstack/widgets/_impl/mixins/__init__.py +24 -0
- bootstack/widgets/_impl/mixins/configure_mixin.py +216 -0
- bootstack/widgets/_impl/mixins/entry_mixin.py +134 -0
- bootstack/widgets/_impl/mixins/font_mixin.py +368 -0
- bootstack/widgets/_impl/mixins/icon_mixin.py +61 -0
- bootstack/widgets/_impl/mixins/localization_mixin.py +253 -0
- bootstack/widgets/_impl/mixins/signal_mixin.py +268 -0
- bootstack/widgets/_impl/mixins/validation_mixin.py +226 -0
- bootstack/widgets/_impl/primitives/__init__.py +49 -0
- bootstack/widgets/_impl/primitives/_menubutton.py +107 -0
- bootstack/widgets/_impl/primitives/badge.py +45 -0
- bootstack/widgets/_impl/primitives/button.py +76 -0
- bootstack/widgets/_impl/primitives/card.py +45 -0
- bootstack/widgets/_impl/primitives/checkbutton.py +124 -0
- bootstack/widgets/_impl/primitives/checktoggle.py +62 -0
- bootstack/widgets/_impl/primitives/combobox.py +156 -0
- bootstack/widgets/_impl/primitives/entry.py +87 -0
- bootstack/widgets/_impl/primitives/flexframe.py +448 -0
- bootstack/widgets/_impl/primitives/frame.py +185 -0
- bootstack/widgets/_impl/primitives/gridframe.py +546 -0
- bootstack/widgets/_impl/primitives/label.py +84 -0
- bootstack/widgets/_impl/primitives/labelframe.py +54 -0
- bootstack/widgets/_impl/primitives/optionmenu.py +387 -0
- bootstack/widgets/_impl/primitives/packframe.py +227 -0
- bootstack/widgets/_impl/primitives/panedwindow.py +45 -0
- bootstack/widgets/_impl/primitives/progressbar.py +83 -0
- bootstack/widgets/_impl/primitives/radiobutton.py +115 -0
- bootstack/widgets/_impl/primitives/radiotoggle.py +54 -0
- bootstack/widgets/_impl/primitives/scrollbar.py +42 -0
- bootstack/widgets/_impl/primitives/separator.py +43 -0
- bootstack/widgets/_impl/primitives/sizegrip.py +33 -0
- bootstack/widgets/_impl/primitives/spinbox.py +95 -0
- bootstack/widgets/_impl/primitives/switch.py +44 -0
- bootstack/widgets/_impl/primitives/treeview.py +69 -0
- bootstack/widgets/app.py +371 -0
- bootstack/widgets/appshell.py +1179 -0
- bootstack/widgets/avatar.py +140 -0
- bootstack/widgets/boolean_controls.py +455 -0
- bootstack/widgets/button.py +224 -0
- bootstack/widgets/buttongroup.py +239 -0
- bootstack/widgets/calendar.py +195 -0
- bootstack/widgets/card.py +159 -0
- bootstack/widgets/carousel.py +241 -0
- bootstack/widgets/chart.py +302 -0
- bootstack/widgets/codeeditor.py +675 -0
- bootstack/widgets/contextmenu.py +371 -0
- bootstack/widgets/datatable.py +688 -0
- bootstack/widgets/datefield.py +395 -0
- bootstack/widgets/divider.py +60 -0
- bootstack/widgets/expander.py +579 -0
- bootstack/widgets/form.py +200 -0
- bootstack/widgets/gallery.py +250 -0
- bootstack/widgets/gauge.py +168 -0
- bootstack/widgets/grid.py +121 -0
- bootstack/widgets/groupbox.py +162 -0
- bootstack/widgets/label.py +229 -0
- bootstack/widgets/listview.py +354 -0
- bootstack/widgets/menubutton.py +419 -0
- bootstack/widgets/numberfield.py +431 -0
- bootstack/widgets/pagestack.py +345 -0
- bootstack/widgets/passwordfield.py +383 -0
- bootstack/widgets/pathfield.py +454 -0
- bootstack/widgets/picture.py +251 -0
- bootstack/widgets/progressbar.py +106 -0
- bootstack/widgets/radio_variants.py +271 -0
- bootstack/widgets/radiogroup.py +228 -0
- bootstack/widgets/scrollbar.py +64 -0
- bootstack/widgets/scrollview.py +186 -0
- bootstack/widgets/select.py +302 -0
- bootstack/widgets/selectbutton.py +182 -0
- bootstack/widgets/sidebar_toggle.py +130 -0
- bootstack/widgets/sizegrip.py +42 -0
- bootstack/widgets/slider.py +408 -0
- bootstack/widgets/spinbox.py +147 -0
- bootstack/widgets/spinnerfield.py +413 -0
- bootstack/widgets/splash.py +367 -0
- bootstack/widgets/splitview.py +482 -0
- bootstack/widgets/stacks.py +249 -0
- bootstack/widgets/statusbar.py +189 -0
- bootstack/widgets/tabs.py +425 -0
- bootstack/widgets/textarea.py +459 -0
- bootstack/widgets/textfield.py +410 -0
- bootstack/widgets/theme_toggle.py +92 -0
- bootstack/widgets/timefield.py +340 -0
- bootstack/widgets/toast.py +314 -0
- bootstack/widgets/togglegroup.py +231 -0
- bootstack/widgets/toolbar.py +347 -0
- bootstack/widgets/tooltip.py +94 -0
- bootstack/widgets/tree.py +648 -0
- bootstack/widgets/types.py +305 -0
- bootstack/widgets/window.py +307 -0
- bootstack-0.1.0.dist-info/METADATA +301 -0
- bootstack-0.1.0.dist-info/RECORD +471 -0
- bootstack-0.1.0.dist-info/WHEEL +5 -0
- bootstack-0.1.0.dist-info/entry_points.txt +2 -0
- bootstack-0.1.0.dist-info/licenses/LICENSE +21 -0
- bootstack-0.1.0.dist-info/licenses/NOTICE +10 -0
- bootstack-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""PyInstaller spec file generation for bootstack projects."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from bootstack.cli.config import TtkbConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# PyInstaller spec template that reads from bootstack.toml
|
|
13
|
+
SPEC_TEMPLATE = '''\
|
|
14
|
+
# -*- mode: python ; coding: utf-8 -*-
|
|
15
|
+
"""
|
|
16
|
+
PyInstaller spec file for {app_name}.
|
|
17
|
+
|
|
18
|
+
This file is auto-generated by bootstack CLI.
|
|
19
|
+
Edit bootstack.toml to change build settings, then regenerate with:
|
|
20
|
+
bootstack promote --pyinstaller --force
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
# PyInstaller exec's this spec with SPECPATH (directory of the .spec file)
|
|
27
|
+
# in the namespace. __file__ is not defined inside a spec.
|
|
28
|
+
PROJECT_ROOT = Path(SPECPATH).parent.parent
|
|
29
|
+
CONFIG_PATH = PROJECT_ROOT / "bootstack.toml"
|
|
30
|
+
|
|
31
|
+
# Ensure we can import bootstack CLI tools
|
|
32
|
+
try:
|
|
33
|
+
from bootstack.cli.config import TtkbConfig
|
|
34
|
+
except ImportError:
|
|
35
|
+
sys.path.insert(0, str(PROJECT_ROOT / "src"))
|
|
36
|
+
from bootstack.cli.config import TtkbConfig
|
|
37
|
+
|
|
38
|
+
if not CONFIG_PATH.exists():
|
|
39
|
+
raise FileNotFoundError(f"bootstack.toml not found at {{CONFIG_PATH}}")
|
|
40
|
+
|
|
41
|
+
config = TtkbConfig.load(CONFIG_PATH)
|
|
42
|
+
|
|
43
|
+
# Extract settings
|
|
44
|
+
APP_NAME = config.app.name
|
|
45
|
+
ENTRY_POINT = PROJECT_ROOT / config.app.entry
|
|
46
|
+
WINDOWED = config.build.windowed if config.build else True
|
|
47
|
+
ONEFILE = config.build.onefile if config.build else False
|
|
48
|
+
|
|
49
|
+
# Icon handling — resolve the icon for the platform this build runs on
|
|
50
|
+
# (PyInstaller can't cross-compile, so we only need the host's format).
|
|
51
|
+
_HOST_KEY = {{"win32": "windows", "darwin": "macos", "linux": "linux"}}.get(sys.platform)
|
|
52
|
+
_HOST_EXT = {{"win32": ".ico", "darwin": ".icns"}}.get(sys.platform, ".png")
|
|
53
|
+
|
|
54
|
+
ICON_PATH = None
|
|
55
|
+
_icon_cfg = config.build.icon if config.build else None
|
|
56
|
+
|
|
57
|
+
# A host-specific path (windows/macos/linux) wins over the generic path.
|
|
58
|
+
_icon_path = None
|
|
59
|
+
if _icon_cfg:
|
|
60
|
+
_host_specific = getattr(_icon_cfg, _HOST_KEY, None) if _HOST_KEY else None
|
|
61
|
+
_icon_path = _host_specific or _icon_cfg.path
|
|
62
|
+
|
|
63
|
+
if _icon_path:
|
|
64
|
+
_candidate = PROJECT_ROOT / _icon_path
|
|
65
|
+
if _candidate.exists():
|
|
66
|
+
ICON_PATH = str(_candidate)
|
|
67
|
+
elif _icon_cfg and _icon_cfg.glyph:
|
|
68
|
+
# Render the glyph into the host platform's icon format. No app runs during a
|
|
69
|
+
# build, so colors must be hex — a theme token cannot be resolved.
|
|
70
|
+
if not (_icon_cfg.background.startswith("#") and _icon_cfg.foreground.startswith("#")):
|
|
71
|
+
print(
|
|
72
|
+
"[build.icon] background/foreground must be hex colors (e.g. "
|
|
73
|
+
"'#0d6efd'); theme tokens need a running app. Using the default icon."
|
|
74
|
+
)
|
|
75
|
+
else:
|
|
76
|
+
try:
|
|
77
|
+
from bootstack.images import AppIcon
|
|
78
|
+
out = PROJECT_ROOT / "build" / ("app-icon" + _HOST_EXT)
|
|
79
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
80
|
+
AppIcon(
|
|
81
|
+
_icon_cfg.glyph,
|
|
82
|
+
background=_icon_cfg.background,
|
|
83
|
+
foreground=_icon_cfg.foreground,
|
|
84
|
+
radius=_icon_cfg.radius,
|
|
85
|
+
shape=_icon_cfg.shape,
|
|
86
|
+
).save(str(out))
|
|
87
|
+
ICON_PATH = str(out)
|
|
88
|
+
except Exception as exc:
|
|
89
|
+
print(f"Could not generate app icon from glyph {{_icon_cfg.glyph!r}}: {{exc}}")
|
|
90
|
+
|
|
91
|
+
if ICON_PATH is None:
|
|
92
|
+
# Fall back to the bundled bootstack launch icon. Override with [build.icon].
|
|
93
|
+
try:
|
|
94
|
+
import bootstack
|
|
95
|
+
default_icon = Path(bootstack.__file__).parent / "assets" / "bootstack.ico"
|
|
96
|
+
if default_icon.exists():
|
|
97
|
+
ICON_PATH = str(default_icon)
|
|
98
|
+
except Exception:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# =============================================================================
|
|
103
|
+
# Collect data files
|
|
104
|
+
# =============================================================================
|
|
105
|
+
|
|
106
|
+
from glob import glob
|
|
107
|
+
|
|
108
|
+
datas = []
|
|
109
|
+
|
|
110
|
+
# Always include bootstack.toml
|
|
111
|
+
datas.append((str(CONFIG_PATH), "."))
|
|
112
|
+
|
|
113
|
+
# Include patterns from config
|
|
114
|
+
if config.build and config.build.datas.include:
|
|
115
|
+
for pattern in config.build.datas.include:
|
|
116
|
+
if pattern == "bootstack.toml":
|
|
117
|
+
continue # Already added
|
|
118
|
+
matches = glob(str(PROJECT_ROOT / pattern), recursive=True)
|
|
119
|
+
for match in matches:
|
|
120
|
+
match_path = Path(match)
|
|
121
|
+
if match_path.is_file():
|
|
122
|
+
rel_path = match_path.relative_to(PROJECT_ROOT)
|
|
123
|
+
dest_dir = str(rel_path.parent) if rel_path.parent != Path(".") else "."
|
|
124
|
+
datas.append((str(match_path), dest_dir))
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# =============================================================================
|
|
128
|
+
# Collect package data (themes, fonts, icon glyphmaps, locales, etc.)
|
|
129
|
+
# =============================================================================
|
|
130
|
+
|
|
131
|
+
from PyInstaller.utils.hooks import collect_data_files, copy_metadata
|
|
132
|
+
|
|
133
|
+
for _pkg in ("bootstack",):
|
|
134
|
+
try:
|
|
135
|
+
datas += collect_data_files(_pkg)
|
|
136
|
+
datas += copy_metadata(_pkg)
|
|
137
|
+
except Exception as _e: # pragma: no cover
|
|
138
|
+
print(f"Warning: Could not collect data files from {{_pkg}}: {{_e}}")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# =============================================================================
|
|
142
|
+
# Hidden imports for bootstack
|
|
143
|
+
# =============================================================================
|
|
144
|
+
|
|
145
|
+
hiddenimports = [
|
|
146
|
+
"bootstack",
|
|
147
|
+
"bootstack.style",
|
|
148
|
+
"bootstack.widgets",
|
|
149
|
+
"PIL",
|
|
150
|
+
"PIL._tkinter_finder",
|
|
151
|
+
"babel.numbers",
|
|
152
|
+
"babel.dates",
|
|
153
|
+
"dateutil",
|
|
154
|
+
"dateparser",
|
|
155
|
+
]
|
|
156
|
+
# Extra hidden imports from [build] hidden_imports
|
|
157
|
+
if config.build and config.build.hidden_imports:
|
|
158
|
+
hiddenimports += list(config.build.hidden_imports)
|
|
159
|
+
|
|
160
|
+
# babel.bin is a CLI script package whose __init__.py calls exit(1) when
|
|
161
|
+
# imported without args; PyInstaller's binary-dependency analyzer
|
|
162
|
+
# imports it during package walking and crashes. Excluding it is safe
|
|
163
|
+
# because nothing in a bootstack app uses babel's command-line tools.
|
|
164
|
+
excludes = [
|
|
165
|
+
"babel.bin",
|
|
166
|
+
]
|
|
167
|
+
# Extra excludes from [build] excludes
|
|
168
|
+
if config.build and config.build.excludes:
|
|
169
|
+
excludes += list(config.build.excludes)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
# =============================================================================
|
|
173
|
+
# Analysis
|
|
174
|
+
# =============================================================================
|
|
175
|
+
|
|
176
|
+
a = Analysis(
|
|
177
|
+
[str(ENTRY_POINT)],
|
|
178
|
+
pathex=[str(PROJECT_ROOT / "src")],
|
|
179
|
+
binaries=[],
|
|
180
|
+
datas=datas,
|
|
181
|
+
hiddenimports=hiddenimports,
|
|
182
|
+
hookspath=[],
|
|
183
|
+
hooksconfig={{}},
|
|
184
|
+
runtime_hooks=[],
|
|
185
|
+
excludes=excludes,
|
|
186
|
+
noarchive=False,
|
|
187
|
+
optimize=0,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# =============================================================================
|
|
192
|
+
# Build
|
|
193
|
+
# =============================================================================
|
|
194
|
+
|
|
195
|
+
pyz = PYZ(a.pure)
|
|
196
|
+
|
|
197
|
+
if ONEFILE:
|
|
198
|
+
exe = EXE(
|
|
199
|
+
pyz,
|
|
200
|
+
a.scripts,
|
|
201
|
+
a.binaries,
|
|
202
|
+
a.datas,
|
|
203
|
+
[],
|
|
204
|
+
name=APP_NAME,
|
|
205
|
+
debug=False,
|
|
206
|
+
bootloader_ignore_signals=False,
|
|
207
|
+
strip=False,
|
|
208
|
+
upx=True,
|
|
209
|
+
upx_exclude=[],
|
|
210
|
+
runtime_tmpdir=None,
|
|
211
|
+
console=not WINDOWED,
|
|
212
|
+
disable_windowed_traceback=False,
|
|
213
|
+
argv_emulation=False,
|
|
214
|
+
target_arch=None,
|
|
215
|
+
codesign_identity=None,
|
|
216
|
+
entitlements_file=None,
|
|
217
|
+
icon=ICON_PATH,
|
|
218
|
+
)
|
|
219
|
+
else:
|
|
220
|
+
exe = EXE(
|
|
221
|
+
pyz,
|
|
222
|
+
a.scripts,
|
|
223
|
+
[],
|
|
224
|
+
exclude_binaries=True,
|
|
225
|
+
name=APP_NAME,
|
|
226
|
+
debug=False,
|
|
227
|
+
bootloader_ignore_signals=False,
|
|
228
|
+
strip=False,
|
|
229
|
+
upx=True,
|
|
230
|
+
console=not WINDOWED,
|
|
231
|
+
disable_windowed_traceback=False,
|
|
232
|
+
argv_emulation=False,
|
|
233
|
+
target_arch=None,
|
|
234
|
+
codesign_identity=None,
|
|
235
|
+
entitlements_file=None,
|
|
236
|
+
icon=ICON_PATH,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
coll = COLLECT(
|
|
240
|
+
exe,
|
|
241
|
+
a.binaries,
|
|
242
|
+
a.datas,
|
|
243
|
+
strip=False,
|
|
244
|
+
upx=True,
|
|
245
|
+
upx_exclude=[],
|
|
246
|
+
name=APP_NAME,
|
|
247
|
+
)
|
|
248
|
+
'''
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def generate_spec(
|
|
252
|
+
config: TtkbConfig,
|
|
253
|
+
project_root: Path,
|
|
254
|
+
output_path: Path,
|
|
255
|
+
) -> None:
|
|
256
|
+
"""Generate a PyInstaller spec file.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
config: The project configuration.
|
|
260
|
+
project_root: Root directory of the project.
|
|
261
|
+
output_path: Path to write the spec file.
|
|
262
|
+
"""
|
|
263
|
+
content = SPEC_TEMPLATE.format(
|
|
264
|
+
app_name=config.app.name,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
268
|
+
output_path.write_text(content, encoding="utf-8")
|
bootstack/cli/run.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""bootstack run command - Run a bootstack application."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from bootstack.cli.config import TtkbConfig, find_config
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def add_parser(subparsers: argparse._SubParsersAction) -> None:
|
|
14
|
+
"""Add the 'run' subcommand parser."""
|
|
15
|
+
parser = subparsers.add_parser(
|
|
16
|
+
"run",
|
|
17
|
+
help="Run the bootstack application",
|
|
18
|
+
description="Run the application using the entry point defined in bootstack.toml.",
|
|
19
|
+
)
|
|
20
|
+
parser.add_argument(
|
|
21
|
+
"path",
|
|
22
|
+
nargs="?",
|
|
23
|
+
default=None,
|
|
24
|
+
help="Path to entry point or directory containing bootstack.toml (default: current directory)",
|
|
25
|
+
)
|
|
26
|
+
parser.set_defaults(func=run_run)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def run_run(args: argparse.Namespace) -> None:
|
|
30
|
+
"""Execute the run command."""
|
|
31
|
+
path = args.path
|
|
32
|
+
config = None
|
|
33
|
+
|
|
34
|
+
# Determine what to run
|
|
35
|
+
if path:
|
|
36
|
+
path = Path(path)
|
|
37
|
+
if path.is_file() and path.suffix == ".py":
|
|
38
|
+
# Direct path to a Python file
|
|
39
|
+
entry_point = path
|
|
40
|
+
project_root = path.parent
|
|
41
|
+
elif path.is_dir():
|
|
42
|
+
# Directory - look for bootstack.toml
|
|
43
|
+
config_path = path / "bootstack.toml"
|
|
44
|
+
if not config_path.exists():
|
|
45
|
+
print(f"Error: No bootstack.toml found in '{path}'")
|
|
46
|
+
return
|
|
47
|
+
config = TtkbConfig.load(config_path)
|
|
48
|
+
entry_point = path / config.app.entry
|
|
49
|
+
project_root = path
|
|
50
|
+
else:
|
|
51
|
+
print(f"Error: '{path}' is not a valid file or directory")
|
|
52
|
+
return
|
|
53
|
+
else:
|
|
54
|
+
# No path specified - find bootstack.toml
|
|
55
|
+
config_path = find_config()
|
|
56
|
+
if config_path is None:
|
|
57
|
+
print("Error: No bootstack.toml found in current directory or parents.")
|
|
58
|
+
print("Run 'bootstack start <appname>' to create a new project.")
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
config = TtkbConfig.load(config_path)
|
|
62
|
+
project_root = config_path.parent
|
|
63
|
+
entry_point = project_root / config.app.entry
|
|
64
|
+
|
|
65
|
+
# Verify entry point exists
|
|
66
|
+
if not entry_point.exists():
|
|
67
|
+
print(f"Error: Entry point '{entry_point}' does not exist.")
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
print(f"Running {entry_point.relative_to(project_root)}...")
|
|
71
|
+
print()
|
|
72
|
+
|
|
73
|
+
# Run the application
|
|
74
|
+
# Add project src directory to PYTHONPATH
|
|
75
|
+
import os
|
|
76
|
+
|
|
77
|
+
src_dir = project_root / "src"
|
|
78
|
+
env = dict(os.environ)
|
|
79
|
+
python_path = env.get("PYTHONPATH", "")
|
|
80
|
+
if src_dir.exists():
|
|
81
|
+
if python_path:
|
|
82
|
+
env["PYTHONPATH"] = f"{src_dir}{os.pathsep}{python_path}"
|
|
83
|
+
else:
|
|
84
|
+
env["PYTHONPATH"] = str(src_dir)
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
result = subprocess.run(
|
|
88
|
+
[sys.executable, str(entry_point.resolve())],
|
|
89
|
+
cwd=str(project_root),
|
|
90
|
+
env=env,
|
|
91
|
+
)
|
|
92
|
+
sys.exit(result.returncode)
|
|
93
|
+
except KeyboardInterrupt:
|
|
94
|
+
print("\nInterrupted.")
|
|
95
|
+
sys.exit(1)
|
bootstack/cli/start.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""bootstack start command - Create a new bootstack project."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from bootstack.cli.templates import create_project
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def add_parser(subparsers: argparse._SubParsersAction) -> None:
|
|
12
|
+
"""Add the 'start' subcommand parser."""
|
|
13
|
+
parser = subparsers.add_parser(
|
|
14
|
+
"start",
|
|
15
|
+
help="Create a new bootstack project",
|
|
16
|
+
description="Scaffold a new bootstack application with sensible defaults.",
|
|
17
|
+
)
|
|
18
|
+
parser.add_argument(
|
|
19
|
+
"name",
|
|
20
|
+
help="Application name (e.g., 'MyApp')",
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"--template",
|
|
24
|
+
choices=["basic", "appshell"],
|
|
25
|
+
default="basic",
|
|
26
|
+
help="Project template: 'basic' for single-view app, 'appshell' for sidebar navigation (default: basic)",
|
|
27
|
+
)
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
"--nav",
|
|
30
|
+
choices=["single", "grouped", "master-detail", "workspaces"],
|
|
31
|
+
default="single",
|
|
32
|
+
help="Navigation style for the appshell template (default: single, "
|
|
33
|
+
"ignored for the basic template)",
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"--simple",
|
|
37
|
+
action="store_true",
|
|
38
|
+
help="Create minimal project without assets or build configuration",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"--container",
|
|
42
|
+
choices=["grid", "pack"],
|
|
43
|
+
default="grid",
|
|
44
|
+
help="Default container type for views (default: grid, ignored for appshell template)",
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--theme",
|
|
48
|
+
default="bootstrap-light",
|
|
49
|
+
help="Theme name for the application (default: bootstrap-light)",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--dir",
|
|
53
|
+
type=Path,
|
|
54
|
+
default=None,
|
|
55
|
+
help="Target directory (default: ./<appname>)",
|
|
56
|
+
)
|
|
57
|
+
parser.set_defaults(func=run_start)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def run_start(args: argparse.Namespace) -> None:
|
|
61
|
+
"""Execute the start command."""
|
|
62
|
+
name = args.name
|
|
63
|
+
simple = args.simple
|
|
64
|
+
container = args.container
|
|
65
|
+
theme = args.theme
|
|
66
|
+
template = args.template
|
|
67
|
+
nav = args.nav
|
|
68
|
+
|
|
69
|
+
# Warn if --container is used with appshell (it's ignored)
|
|
70
|
+
if template == "appshell" and container != "grid":
|
|
71
|
+
print("Note: --container is ignored for appshell template.")
|
|
72
|
+
# Warn if --nav is used with the basic template (it's ignored)
|
|
73
|
+
if template == "basic" and nav != "single":
|
|
74
|
+
print("Note: --nav is ignored for the basic template.")
|
|
75
|
+
|
|
76
|
+
# Determine target directory
|
|
77
|
+
if args.dir:
|
|
78
|
+
target_dir = args.dir
|
|
79
|
+
else:
|
|
80
|
+
# Use lowercase name with underscores for directory
|
|
81
|
+
dir_name = name.lower().replace(" ", "_").replace("-", "_")
|
|
82
|
+
target_dir = Path.cwd() / dir_name
|
|
83
|
+
|
|
84
|
+
# Check if directory already exists and has content
|
|
85
|
+
if target_dir.exists() and any(target_dir.iterdir()):
|
|
86
|
+
print(f"Error: Directory '{target_dir}' already exists and is not empty.")
|
|
87
|
+
print("Choose a different name or remove the existing directory.")
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
# Create the project
|
|
91
|
+
print(f"Creating '{template}' project '{name}' in {target_dir}...")
|
|
92
|
+
create_project(
|
|
93
|
+
name=name,
|
|
94
|
+
target_dir=target_dir,
|
|
95
|
+
container=container,
|
|
96
|
+
theme=theme,
|
|
97
|
+
template=template,
|
|
98
|
+
simple=simple,
|
|
99
|
+
nav=nav,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Print success message
|
|
103
|
+
print()
|
|
104
|
+
print(f"Project '{name}' created successfully!")
|
|
105
|
+
print()
|
|
106
|
+
print("Next steps:")
|
|
107
|
+
print(f" cd {target_dir.name}")
|
|
108
|
+
print(" bootstack run")
|
|
109
|
+
print()
|
|
110
|
+
if template == "appshell":
|
|
111
|
+
print("To add a new page:")
|
|
112
|
+
print(" bootstack add page DashboardPage")
|
|
113
|
+
print()
|
|
114
|
+
if not simple:
|
|
115
|
+
print("To build for distribution:")
|
|
116
|
+
print(" bootstack promote --pyinstaller")
|
|
117
|
+
print(" bootstack build")
|