pycforge-sdk 0.6.3__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.
- pycforge_sdk/__init__.py +6 -0
- pycforge_sdk/__main__.py +3 -0
- pycforge_sdk/catalogue.py +287 -0
- pycforge_sdk/cli.py +114 -0
- pycforge_sdk/connection.py +136 -0
- pycforge_sdk/discovery.py +227 -0
- pycforge_sdk/editing.py +84 -0
- pycforge_sdk/engine_launch.py +45 -0
- pycforge_sdk/engine_worker.py +53 -0
- pycforge_sdk/gui/__init__.py +1 -0
- pycforge_sdk/gui/__main__.py +3 -0
- pycforge_sdk/gui/app.py +36 -0
- pycforge_sdk/gui/dialogs.py +310 -0
- pycforge_sdk/gui/editor.py +412 -0
- pycforge_sdk/gui/help/index.html +9 -0
- pycforge_sdk/gui/identity.py +139 -0
- pycforge_sdk/gui/jobs.py +146 -0
- pycforge_sdk/gui/reference.py +39 -0
- pycforge_sdk/gui/resources/sdk-mark.png +0 -0
- pycforge_sdk/gui/scanner.py +134 -0
- pycforge_sdk/gui/startup.py +118 -0
- pycforge_sdk/gui/visual/__init__.py +1 -0
- pycforge_sdk/gui/visual/action_contract.py +550 -0
- pycforge_sdk/gui/visual/icons.py +117 -0
- pycforge_sdk/gui/visual/qt_actions.py +501 -0
- pycforge_sdk/gui/visual/qt_branding.py +47 -0
- pycforge_sdk/gui/visual/qt_dialog_chrome.py +337 -0
- pycforge_sdk/gui/visual/qt_file_icons.py +130 -0
- pycforge_sdk/gui/visual/qt_icons.py +80 -0
- pycforge_sdk/gui/visual/qt_screen_geometry.py +166 -0
- pycforge_sdk/gui/visual/qt_title_controls.py +333 -0
- pycforge_sdk/gui/visual/qt_window_chrome.py +314 -0
- pycforge_sdk/gui/visual/qt_window_resize.py +93 -0
- pycforge_sdk/gui/visual/qt_workspace_widgets.py +448 -0
- pycforge_sdk/gui/visual/resources/icons/128/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/whitespace.png +0 -0
- pycforge_sdk/gui/visual/theme.py +204 -0
- pycforge_sdk/gui/visual/theme_steel_stylesheet.py +901 -0
- pycforge_sdk/gui/visual/theme_stylesheet.py +597 -0
- pycforge_sdk/gui/visual/theme_workspace_stylesheet.py +169 -0
- pycforge_sdk/gui/visual/visual_tokens.py +146 -0
- pycforge_sdk/gui/widgets.py +68 -0
- pycforge_sdk/gui/window.py +559 -0
- pycforge_sdk/native.py +42 -0
- pycforge_sdk/package_metadata.py +21 -0
- pycforge_sdk/process.py +58 -0
- pycforge_sdk/project.py +143 -0
- pycforge_sdk/readiness.py +106 -0
- pycforge_sdk/results.py +45 -0
- pycforge_sdk/service.py +454 -0
- pycforge_sdk/workbench.py +88 -0
- pycforge_sdk-0.6.3.dist-info/METADATA +221 -0
- pycforge_sdk-0.6.3.dist-info/RECORD +559 -0
- pycforge_sdk-0.6.3.dist-info/WHEEL +5 -0
- pycforge_sdk-0.6.3.dist-info/entry_points.txt +5 -0
- pycforge_sdk-0.6.3.dist-info/licenses/LICENSE +674 -0
- pycforge_sdk-0.6.3.dist-info/top_level.txt +1 -0
pycforge_sdk/process.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Bounded explicit subprocess work; no shell and no Qt event loop."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
import os
|
|
5
|
+
import signal
|
|
6
|
+
import subprocess
|
|
7
|
+
import tempfile
|
|
8
|
+
import threading
|
|
9
|
+
import time
|
|
10
|
+
from .results import SDKError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class ProcessResult:
|
|
15
|
+
returncode: int
|
|
16
|
+
stdout: bytes
|
|
17
|
+
stderr: bytes
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def run(argv, *, input_bytes=b"", cwd=None, timeout=30.0, cancel=None, max_output=8*1024*1024):
|
|
21
|
+
"""Run an explicitly requested tool, bounding time and captured output.
|
|
22
|
+
|
|
23
|
+
POSIX work uses a process group so timeout/cancellation also stops child
|
|
24
|
+
processes. This is supervision, not a security sandbox. Windows terminates
|
|
25
|
+
the direct process; native fixture qualification is Linux-only in 0.1.
|
|
26
|
+
"""
|
|
27
|
+
if timeout <= 0 or timeout > 300:
|
|
28
|
+
raise SDKError("SDK_ARGUMENT", "Timeout must be greater than zero and at most 300 seconds.")
|
|
29
|
+
if cancel is not None and cancel.is_set():
|
|
30
|
+
raise SDKError("SDK_CANCELED", "Operation canceled before execution.", status="canceled")
|
|
31
|
+
tick = threading.Event()
|
|
32
|
+
with tempfile.TemporaryFile() as source, tempfile.TemporaryFile() as out, tempfile.TemporaryFile() as err:
|
|
33
|
+
source.write(input_bytes); source.seek(0)
|
|
34
|
+
process = subprocess.Popen([str(a) for a in argv], stdin=source, stdout=out, stderr=err,
|
|
35
|
+
cwd=cwd, start_new_session=(os.name == "posix"))
|
|
36
|
+
deadline = time.monotonic() + timeout
|
|
37
|
+
try:
|
|
38
|
+
while process.poll() is None:
|
|
39
|
+
if cancel is not None and cancel.is_set():
|
|
40
|
+
raise SDKError("SDK_CANCELED", "Operation canceled.", status="canceled")
|
|
41
|
+
if time.monotonic() >= deadline:
|
|
42
|
+
raise SDKError("SDK_TIMEOUT", "Tool execution exceeded its time limit.", status="incomplete")
|
|
43
|
+
if max(os.fstat(out.fileno()).st_size, os.fstat(err.fileno()).st_size) > max_output:
|
|
44
|
+
raise SDKError("SDK_OUTPUT_LIMIT", "Tool output exceeded the configured budget.", status="incomplete")
|
|
45
|
+
tick.wait(0.02)
|
|
46
|
+
out.seek(0); err.seek(0)
|
|
47
|
+
stdout, stderr = out.read(max_output+1), err.read(max_output+1)
|
|
48
|
+
if max(len(stdout), len(stderr)) > max_output:
|
|
49
|
+
raise SDKError("SDK_OUTPUT_LIMIT", "Tool output exceeded the configured budget.", status="incomplete")
|
|
50
|
+
return ProcessResult(process.returncode, stdout, stderr)
|
|
51
|
+
finally:
|
|
52
|
+
if os.name == "posix":
|
|
53
|
+
try: os.killpg(process.pid, signal.SIGKILL)
|
|
54
|
+
except ProcessLookupError: pass
|
|
55
|
+
elif process.poll() is None:
|
|
56
|
+
process.kill()
|
|
57
|
+
process.wait()
|
|
58
|
+
|
pycforge_sdk/project.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""Data-only extension projects and immutable file snapshots."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
import hashlib
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path, PurePosixPath
|
|
8
|
+
import re
|
|
9
|
+
import tempfile
|
|
10
|
+
from .results import SDKError
|
|
11
|
+
|
|
12
|
+
PROJECT_SCHEMA = "pycforge-sdk.project/0.1"
|
|
13
|
+
DOCUMENTED_PROJECT_SCHEMA = "pycforge-sdk.project/0.2"
|
|
14
|
+
REPORT_SCHEMA = "pycforge-sdk.verification/0.2"
|
|
15
|
+
MAX_SOURCE = 256 * 1024
|
|
16
|
+
MAX_PROJECT = 4 * 1024 * 1024
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def canonical(value):
|
|
20
|
+
return (json.dumps(value, sort_keys=True, indent=2, ensure_ascii=True, allow_nan=False) + "\n").encode("utf-8")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def digest(value):
|
|
24
|
+
return hashlib.sha256(value).hexdigest()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def parse(data):
|
|
28
|
+
def unique(items):
|
|
29
|
+
result = {}
|
|
30
|
+
for key, value in items:
|
|
31
|
+
if key in result:
|
|
32
|
+
raise SDKError("SDK_PROJECT", "Duplicate JSON key: " + key)
|
|
33
|
+
result[key] = value
|
|
34
|
+
return result
|
|
35
|
+
try:
|
|
36
|
+
return json.loads(data.decode("utf-8") if isinstance(data, bytes) else data, object_pairs_hook=unique,
|
|
37
|
+
parse_constant=lambda value: (_ for _ in ()).throw(ValueError(value)))
|
|
38
|
+
except (ValueError, UnicodeError, RecursionError) as exc:
|
|
39
|
+
raise SDKError("SDK_PROJECT", "Invalid UTF-8 JSON document.") from exc
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def read(path, limit):
|
|
43
|
+
path = Path(path)
|
|
44
|
+
if path.is_symlink() or not path.is_file():
|
|
45
|
+
raise SDKError("SDK_PROJECT", "Expected a regular non-symlink file: " + str(path))
|
|
46
|
+
with path.open("rb") as stream:
|
|
47
|
+
data = stream.read(limit+1)
|
|
48
|
+
if len(data) > limit:
|
|
49
|
+
raise SDKError("SDK_PROJECT", "File exceeds the size budget: " + str(path))
|
|
50
|
+
return data
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def atomic_write(path, data):
|
|
54
|
+
path = Path(path)
|
|
55
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
56
|
+
if path.is_symlink():
|
|
57
|
+
raise SDKError("SDK_PROJECT", "Refusing a symbolic-link destination.")
|
|
58
|
+
fd, name = tempfile.mkstemp(prefix=".sdk-write-", dir=path.parent)
|
|
59
|
+
try:
|
|
60
|
+
with os.fdopen(fd, "wb") as stream:
|
|
61
|
+
stream.write(data); stream.flush(); os.fsync(stream.fileno())
|
|
62
|
+
os.replace(name, path)
|
|
63
|
+
finally:
|
|
64
|
+
if os.path.exists(name): os.unlink(name)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def require(condition, message):
|
|
68
|
+
if not condition:
|
|
69
|
+
raise SDKError("SDK_PROJECT", message)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True)
|
|
73
|
+
class Project:
|
|
74
|
+
root: Path
|
|
75
|
+
document_bytes: bytes
|
|
76
|
+
sources: tuple[tuple[str, bytes], ...]
|
|
77
|
+
sha256: str
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def document(self):
|
|
81
|
+
return parse(self.document_bytes)
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def report_path(self):
|
|
85
|
+
return self.root / ".pycforge-sdk" / "verification.json"
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def load(cls, root, *, document_bytes=None):
|
|
89
|
+
root = Path(root).absolute()
|
|
90
|
+
require(not root.is_symlink(), "Project root cannot be a symlink.")
|
|
91
|
+
root = root.resolve()
|
|
92
|
+
data = read(root / "project.json", MAX_PROJECT) if document_bytes is None else document_bytes
|
|
93
|
+
document = parse(data)
|
|
94
|
+
require(type(document) is dict, "Project must be an object.")
|
|
95
|
+
schema = document.get("schema")
|
|
96
|
+
require(schema in (PROJECT_SCHEMA, DOCUMENTED_PROJECT_SCHEMA), "Unsupported SDK project schema.")
|
|
97
|
+
fields = {"schema","declaration","metadata","cases"}
|
|
98
|
+
if schema == DOCUMENTED_PROJECT_SCHEMA: fields.add("documentation")
|
|
99
|
+
require(set(document) == fields, "Unknown or missing project fields.")
|
|
100
|
+
metadata = document["metadata"]
|
|
101
|
+
require(type(metadata) is dict and set(metadata) == {"author","created","description","license"}
|
|
102
|
+
and all(type(v) is str and 0 < len(v) <= 4096 for v in metadata.values()), "Invalid author metadata.")
|
|
103
|
+
cases = document["cases"]
|
|
104
|
+
require(type(cases) is list and 1 <= len(cases) <= 64, "Projects require 1..64 explicit test cases.")
|
|
105
|
+
names, sources, total = set(), {}, len(data)
|
|
106
|
+
for case in cases:
|
|
107
|
+
require(type(case) is dict and set(case) == {"name","file","expect"}, "Invalid test case fields.")
|
|
108
|
+
name = case["name"]
|
|
109
|
+
require(type(name) is str and re.fullmatch(r"[a-zA-Z0-9_-]{1,64}", name) and name not in names, "Test names must be unique simple identifiers.")
|
|
110
|
+
names.add(name)
|
|
111
|
+
filename = case["file"]
|
|
112
|
+
require(filename != "project.json", "A fixture cannot overwrite the project document.")
|
|
113
|
+
require(type(filename) is str and len(filename) <= 240 and "\\" not in filename and ":" not in filename, "Invalid source path.")
|
|
114
|
+
parts = PurePosixPath(filename).parts
|
|
115
|
+
require(parts and not PurePosixPath(filename).is_absolute() and all(p not in (".","..", ".pycforge-sdk") for p in parts), "Source path must stay inside the project.")
|
|
116
|
+
candidate = root
|
|
117
|
+
for part in parts:
|
|
118
|
+
candidate = candidate / part
|
|
119
|
+
require(not candidate.is_symlink(), "Source paths cannot contain symlinks.")
|
|
120
|
+
require(candidate.resolve().is_relative_to(root), "Source path escapes the project.")
|
|
121
|
+
if filename not in sources:
|
|
122
|
+
content = read(candidate, MAX_SOURCE)
|
|
123
|
+
try: content.decode("utf-8")
|
|
124
|
+
except UnicodeError as exc: raise SDKError("SDK_PROJECT", "Sources must be UTF-8.") from exc
|
|
125
|
+
sources[filename] = content; total += len(content)
|
|
126
|
+
expected = case["expect"]
|
|
127
|
+
require(type(expected) is dict, "Test expectations must be an object.")
|
|
128
|
+
if expected.get("kind") == "run":
|
|
129
|
+
require(set(expected) == {"kind","stdout","stderr","exit_code"}, "Invalid run expectation.")
|
|
130
|
+
require(all(type(expected[k]) is str and len(expected[k]) <= MAX_SOURCE for k in ("stdout","stderr")), "Expected output must be bounded text.")
|
|
131
|
+
require(type(expected["exit_code"]) is int and 0 <= expected["exit_code"] <= 255, "Expected exit status must be 0..255.")
|
|
132
|
+
elif expected.get("kind") == "reject":
|
|
133
|
+
require(set(expected) == {"kind","code"} and type(expected["code"]) is str and bool(re.fullmatch(r"PYC[0-9]{4}", expected["code"])), "Rejected cases require an explicit engine diagnostic code.")
|
|
134
|
+
else:
|
|
135
|
+
raise SDKError("SDK_PROJECT", "Unsupported case kind; use run or reject.")
|
|
136
|
+
require(total <= MAX_PROJECT, "Project snapshot exceeds the total budget.")
|
|
137
|
+
require(not (root/".pycforge-sdk").is_symlink(), "SDK work folder cannot be a symlink.")
|
|
138
|
+
identity = {"project.json": digest(data), **{name: digest(value) for name,value in sorted(sources.items())}}
|
|
139
|
+
return cls(root, data, tuple(sorted(sources.items())), digest(canonical(identity)))
|
|
140
|
+
|
|
141
|
+
def ensure_current(self):
|
|
142
|
+
if Project.load(self.root).sha256 != self.sha256:
|
|
143
|
+
raise SDKError("SDK_STALE_PROJECT", "Project changed during the operation; inspect and verify the new snapshot.")
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Explainable packaging gate shared by Python, console and desktop clients."""
|
|
2
|
+
from .project import Project, REPORT_SCHEMA, parse, read
|
|
3
|
+
from .results import Outcome, SDKError, SDK_VERSION
|
|
4
|
+
|
|
5
|
+
SCOPE = ("Readiness covers the saved project and its explicit fixtures on the recorded "
|
|
6
|
+
"engine, compiler and host. It is not proof of every input or a signed certificate.")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def evaluate(sdk, directory, *, compiler=None):
|
|
10
|
+
result = {"schema": "pycforge-sdk.readiness/0.1", "state": "unavailable",
|
|
11
|
+
"ready": False, "project_sha256": None, "engine": None,
|
|
12
|
+
"checks": [], "issues": [], "scope": SCOPE, "evidence_sha256": None}
|
|
13
|
+
stage = "project"
|
|
14
|
+
|
|
15
|
+
def passed(identifier, label):
|
|
16
|
+
result["checks"].append({"id": identifier, "label": label, "status": "passed"})
|
|
17
|
+
sdk._notify("check", name=label)
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
sdk._notify("check", name="Read saved project")
|
|
21
|
+
project = Project.load(directory)
|
|
22
|
+
result["project_sha256"] = project.sha256
|
|
23
|
+
passed("project", "Saved project and fixture files")
|
|
24
|
+
stage = "engine"
|
|
25
|
+
sdk._connection.ensure_current()
|
|
26
|
+
result["engine"] = dict(sdk._connection.snapshot.identity)
|
|
27
|
+
passed("engine", "Selected engine is available and current")
|
|
28
|
+
stage = "authoring"
|
|
29
|
+
scan = sdk._scan(project)
|
|
30
|
+
result["scan"] = scan
|
|
31
|
+
passed("declaration", "Declaration and supported contracts")
|
|
32
|
+
if scan["issues"]:
|
|
33
|
+
result.update(state="needs-authoring", issues=scan["issues"])
|
|
34
|
+
result["checks"].append({"id": "documentation", "label": "Help and example links", "status": "incomplete"})
|
|
35
|
+
return Outcome("rejected", {"readiness": result}, tuple(result["issues"]))
|
|
36
|
+
passed("documentation", "Offline Help and example links")
|
|
37
|
+
stage = "fixtures"
|
|
38
|
+
guide = sdk._connection.reference()
|
|
39
|
+
policy = guide.get("verification", {})
|
|
40
|
+
kinds = {c["expect"]["kind"] for c in project.document["cases"]}
|
|
41
|
+
if policy.get("policy") not in ("scalar-fixtures/0.1", "scalar-fixtures/0.2"):
|
|
42
|
+
raise SDKError("SDK_CAPABILITY", "Unsupported engine fixture policy.")
|
|
43
|
+
if not set(policy.get("required_case_kinds", [])) <= kinds:
|
|
44
|
+
raise SDKError("SDK_INCOMPLETE_SUITE", "Include both native run fixtures and expected conversion rejections.")
|
|
45
|
+
passed("fixtures", "Required fixture kinds are present")
|
|
46
|
+
stage = "evidence"
|
|
47
|
+
report, inspection, _ = sdk._validated_evidence(project, selected_compiler=compiler)
|
|
48
|
+
passed("native", "Every explicit native and rejection fixture passed")
|
|
49
|
+
passed("coverage", "Every export and linked Help example is covered")
|
|
50
|
+
passed("freshness", "Project, SDK, engine, compiler and host match evidence")
|
|
51
|
+
stage = "package"
|
|
52
|
+
sdk._package_content(project, report)
|
|
53
|
+
sdk._connection.ensure_current()
|
|
54
|
+
passed("package", "Engine validates package metadata and archive")
|
|
55
|
+
result.update(state="ready-to-package", ready=True,
|
|
56
|
+
evidence_sha256=report["evidence_sha256"], compiler=report["compiler"],
|
|
57
|
+
coverage=report["coverage"], cases=report["cases"])
|
|
58
|
+
return Outcome("succeeded", {"readiness": result})
|
|
59
|
+
except (SDKError, OSError) as exc:
|
|
60
|
+
code = getattr(exc, "code", "SDK_IO")
|
|
61
|
+
canceled = getattr(exc, "status", "") == "canceled"
|
|
62
|
+
missing = code == "SDK_VERIFICATION_REQUIRED"
|
|
63
|
+
state = ("canceled" if canceled else "ready-to-verify" if missing else
|
|
64
|
+
"needs-verification" if stage == "evidence" else
|
|
65
|
+
"needs-authoring" if stage in ("project", "authoring", "fixtures", "package") else "unavailable")
|
|
66
|
+
issue = {"code": code, "message": str(exc), "path": "/metadata" if stage == "package" else "",
|
|
67
|
+
"remedy": "Run Verify fixtures, then scan again." if stage == "evidence" else
|
|
68
|
+
"Connect to a compatible engine." if stage == "engine" else "Correct the project, save and scan again."}
|
|
69
|
+
result.update(state=state, issues=[issue])
|
|
70
|
+
result["checks"].append({"id": stage, "label": str(exc), "status": "not-run" if missing else "incomplete"})
|
|
71
|
+
if stage == "evidence" and not canceled:
|
|
72
|
+
last_attempt(result, project)
|
|
73
|
+
return Outcome("canceled" if canceled else "incomplete" if state in
|
|
74
|
+
("unavailable", "ready-to-verify", "needs-verification") else "rejected",
|
|
75
|
+
{"readiness": result}, tuple(result["issues"]))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def last_attempt(result, project):
|
|
79
|
+
"""Explain a failed attempt for these exact inputs; never promote it."""
|
|
80
|
+
try:
|
|
81
|
+
report = parse(read(project.report_path, 8*1024*1024))
|
|
82
|
+
except (SDKError, OSError):
|
|
83
|
+
return
|
|
84
|
+
if (type(report) is not dict or report.get("schema") != REPORT_SCHEMA
|
|
85
|
+
or report.get("project_sha256") != project.sha256
|
|
86
|
+
or report.get("sdk_version") != SDK_VERSION or report.get("engine") != result["engine"]
|
|
87
|
+
or report.get("status") not in ("failed", "incomplete", "canceled")
|
|
88
|
+
or type(report.get("cases")) is not list):
|
|
89
|
+
return
|
|
90
|
+
result["last_attempt_status"] = report["status"]
|
|
91
|
+
result["cases"] = []
|
|
92
|
+
expected = {case["name"]: (index, case) for index, case in enumerate(project.document["cases"])}
|
|
93
|
+
for case in report["cases"]:
|
|
94
|
+
if type(case) is not dict or type(case.get("name")) is not str: continue
|
|
95
|
+
entry = expected.get(case["name"])
|
|
96
|
+
if entry is None or case.get("file") != entry[1]["file"] or case.get("expected") != entry[1]["expect"]: continue
|
|
97
|
+
result["cases"].append(case)
|
|
98
|
+
if case.get("passed") is not True:
|
|
99
|
+
result["issues"].append({"code": "SDK_FIXTURE_FAILED", "path": f"/cases/{entry[0]}",
|
|
100
|
+
"message": "Fixture '" + case["name"] + "' did not pass: " + str(case.get("reason", "review its diagnostics")),
|
|
101
|
+
"remedy": "Review expected and actual results in Fixture results, then correct the declaration, fixture or expectation and verify again."})
|
|
102
|
+
coverage = report.get("coverage")
|
|
103
|
+
if isinstance(coverage, dict) and coverage.get("missing"):
|
|
104
|
+
result["issues"].append({"code": "SDK_INCOMPLETE_COVERAGE", "path": "/declaration/functions",
|
|
105
|
+
"message": "Exports missing native source-call coverage: " + str(coverage["missing"]),
|
|
106
|
+
"remedy": "Add calls to these operations in passing native fixtures."})
|
pycforge_sdk/results.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Versioned, UI-independent SDK results and errors."""
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from functools import wraps
|
|
4
|
+
|
|
5
|
+
SDK_VERSION = "0.6.3"
|
|
6
|
+
RESULT_SCHEMA = "pycforge-sdk.result/0.1"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SDKError(Exception):
|
|
10
|
+
def __init__(self, code, message, *, status="rejected", details=None):
|
|
11
|
+
super().__init__(message)
|
|
12
|
+
self.code, self.status, self.details = code, status, details or {}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class Outcome:
|
|
17
|
+
status: str
|
|
18
|
+
data: dict = field(default_factory=dict)
|
|
19
|
+
diagnostics: tuple = ()
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def ok(self):
|
|
23
|
+
return self.status == "succeeded"
|
|
24
|
+
|
|
25
|
+
def to_dict(self):
|
|
26
|
+
return {"schema": RESULT_SCHEMA, "sdk_version": SDK_VERSION, "status": self.status,
|
|
27
|
+
"data": self.data, "diagnostics": list(self.diagnostics)}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def operation(function):
|
|
31
|
+
"""Keep failure categories identical for Python, console and GUI."""
|
|
32
|
+
@wraps(function)
|
|
33
|
+
def invoke(*args, **kwargs):
|
|
34
|
+
try:
|
|
35
|
+
result = function(*args, **kwargs)
|
|
36
|
+
return result if isinstance(result, Outcome) else Outcome("succeeded", result)
|
|
37
|
+
except SDKError as exc:
|
|
38
|
+
return Outcome(exc.status, {}, ({"code": exc.code, "message": str(exc), "details": exc.details},))
|
|
39
|
+
except OSError as exc:
|
|
40
|
+
return Outcome("incomplete", {}, ({"code": "SDK_IO", "message": str(exc)},))
|
|
41
|
+
except Exception as exc:
|
|
42
|
+
return Outcome("internal_failure", {}, ({"code": "SDK_INTERNAL", "message": str(exc),
|
|
43
|
+
"details": {"exception_type": type(exc).__name__}},))
|
|
44
|
+
return invoke
|
|
45
|
+
|