PyBreeze-dev 1.0.17__tar.gz → 1.0.19__tar.gz
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.
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/PKG-INFO +75 -5
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/README.md +73 -3
- pybreeze_dev-1.0.19/pybreeze/extend/language_server/__init__.py +6 -0
- pybreeze_dev-1.0.19/pybreeze/extend/language_server/__main__.py +17 -0
- pybreeze_dev-1.0.19/pybreeze/extend/language_server/launch.py +42 -0
- pybreeze_dev-1.0.19/pybreeze/extend/language_server/server_main.py +59 -0
- pybreeze_dev-1.0.19/pybreeze/extend_multi_language/english_integrations.py +165 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend_multi_language/extend_english.py +76 -49
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend_multi_language/extend_traditional_chinese.py +75 -87
- pybreeze_dev-1.0.19/pybreeze/extend_multi_language/supported_languages.py +88 -0
- pybreeze_dev-1.0.19/pybreeze/extend_multi_language/traditional_chinese_error_text.py +115 -0
- pybreeze_dev-1.0.19/pybreeze/extend_multi_language/traditional_chinese_integrations.py +162 -0
- pybreeze_dev-1.0.19/pybreeze/extend_multi_language/update_language_dict.py +36 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/design/flow_layout.py +101 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/design/panels.py +78 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/design/tokens.py +117 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_editor_widget.py +14 -15
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/editor_main/main_ui.py +52 -1
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_editor_widget.py +12 -7
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/mcp_gui/mcp_client_gui.py +411 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/mcp_gui/mcp_panels.py +290 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/mcp_gui/mcp_profile_dialog.py +176 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/mcp_gui/mcp_server_panel.py +175 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/mcp_gui/mcp_worker.py +41 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/tools/tools_menu.py +271 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/navigation/navigation_dock.py +128 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/navigation/navigation_model.py +151 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/report_gui/report_viewer_gui.py +394 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/thread_keeper.py +30 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/curl_import_gui.py +24 -12
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/har_import_gui.py +27 -10
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/header_analyzer_gui.py +43 -3
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/tools_gui/import_gaps.py +48 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/tools_gui/json_editor_gui.py +398 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/tools_gui/json_tree_panel.py +338 -0
- pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/tools_gui/keyword_reference_gui.py +272 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/response_inspector_gui.py +5 -6
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/curl_import/script_templates.py +1 -33
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/exception/exception_tags.py +39 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/exception/exceptions.py +16 -0
- pybreeze_dev-1.0.19/pybreeze/utils/execution_report/html_report.py +125 -0
- pybreeze_dev-1.0.19/pybreeze/utils/execution_report/junit_xml.py +176 -0
- pybreeze_dev-1.0.19/pybreeze/utils/execution_report/record_reports.py +208 -0
- pybreeze_dev-1.0.19/pybreeze/utils/execution_report/report_files.py +165 -0
- pybreeze_dev-1.0.19/pybreeze/utils/execution_report/report_filter.py +106 -0
- pybreeze_dev-1.0.19/pybreeze/utils/execution_report/report_schema.py +373 -0
- pybreeze_dev-1.0.19/pybreeze/utils/execution_report/safe_xml.py +136 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/har_import/har_codegen.py +7 -36
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/header_tools/header_analyzer.py +32 -22
- pybreeze_dev-1.0.19/pybreeze/utils/header_tools/header_rules.py +179 -0
- pybreeze_dev-1.0.19/pybreeze/utils/header_tools/header_sarif.py +191 -0
- pybreeze_dev-1.0.19/pybreeze/utils/import_targets/builtin_targets.py +69 -0
- pybreeze_dev-1.0.19/pybreeze/utils/import_targets/normalized_request.py +119 -0
- pybreeze_dev-1.0.19/pybreeze/utils/import_targets/target_registry.py +156 -0
- pybreeze_dev-1.0.19/pybreeze/utils/import_targets/webrunner_target.py +79 -0
- pybreeze_dev-1.0.19/pybreeze/utils/json_format/json_document.py +262 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/json_format/json_process.py +6 -6
- pybreeze_dev-1.0.19/pybreeze/utils/json_format/json_tree_edit.py +300 -0
- pybreeze_dev-1.0.19/pybreeze/utils/language_service/action_adapter.py +343 -0
- pybreeze_dev-1.0.19/pybreeze/utils/language_service/framework_profiles.py +55 -0
- pybreeze_dev-1.0.19/pybreeze/utils/language_service/json_scan.py +274 -0
- pybreeze_dev-1.0.19/pybreeze/utils/language_service/keyword_metadata.py +223 -0
- pybreeze_dev-1.0.19/pybreeze/utils/language_service/lsp_server.py +431 -0
- pybreeze_dev-1.0.19/pybreeze/utils/language_service/metadata_probe.py +163 -0
- pybreeze_dev-1.0.19/pybreeze/utils/language_service/service_adapter.py +271 -0
- pybreeze_dev-1.0.19/pybreeze/utils/manager/package_manager/__init__.py +0 -0
- pybreeze_dev-1.0.19/pybreeze/utils/mcp/__init__.py +0 -0
- pybreeze_dev-1.0.19/pybreeze/utils/mcp/mcp_call_log.py +113 -0
- pybreeze_dev-1.0.19/pybreeze/utils/mcp/mcp_client.py +414 -0
- pybreeze_dev-1.0.19/pybreeze/utils/mcp/mcp_profile.py +184 -0
- pybreeze_dev-1.0.19/pybreeze/utils/mcp/mcp_redaction.py +76 -0
- pybreeze_dev-1.0.19/pybreeze/utils/mcp/mcp_transport.py +155 -0
- pybreeze_dev-1.0.19/pybreeze/utils/network/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/network/url_validation.py +1 -1
- pybreeze_dev-1.0.19/pybreeze/utils/query_tools/__init__.py +0 -0
- pybreeze_dev-1.0.19/pybreeze/utils/regex_tools/__init__.py +0 -0
- pybreeze_dev-1.0.19/pybreeze/utils/response_inspector/__init__.py +0 -0
- pybreeze_dev-1.0.19/pybreeze/utils/timestamp_tools/__init__.py +0 -0
- pybreeze_dev-1.0.19/pybreeze/utils/ui_state.py +48 -0
- pybreeze_dev-1.0.19/pybreeze/utils/url_tools/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze_dev.egg-info/PKG-INFO +75 -5
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze_dev.egg-info/SOURCES.txt +59 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze_dev.egg-info/requires.txt +1 -1
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pyproject.toml +2 -2
- pybreeze_dev-1.0.17/pybreeze/extend_multi_language/update_language_dict.py +0 -29
- pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/tools/tools_menu.py +0 -298
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/LICENSE +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/__main__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/mail_thunder_extend/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/mail_thunder_extend/mail_thunder_setting.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/file_runner_process.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/process_executor_utils.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/prthinker/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/prthinker/prthinker_process.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/python_task_process_manager.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/queue_pump.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/run_notice.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/test_pioneer/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/process_executor/test_pioneer/test_pioneer_process_manager.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/prthinker_extend/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend/prthinker_extend/prthinker_setting.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/extend_multi_language/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/busy_cursor.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/closing.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/code_result_logs.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/sftp_session.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_command_widget.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_connect_thread.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_file_viewer_widget.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_host_key_policy.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_key_loader.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_login_widget.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_main_widget.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/url/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/connect_gui/url/ai_code_review_gui.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/diagram_editor → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/design}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/dialog → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/diagram_editor}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_commands.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_items.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_mermaid_parser.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_net_utils.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_property_panel.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_scene.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/diagram_editor/diagram_view.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/editor_main → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/dialog}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/dialog/prthinker_setting_dialog.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/extend_ai_gui → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/editor_main}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/editor_main/file_tree_context_menu.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/editor_main/pybreeze_icon.ico +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/error_text.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/exact_text.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/extend_ai_gui/code_review → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/extend_ai_gui}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/ai_gui_global_variable.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/extend_ai_gui/code_review}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/code_review_thread.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_chain.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_code_review_gui.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/code_smell_detector.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_code_review.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_summary_prompt.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/global_rule.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge_single_review.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/linter.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/step_by_step_analysis.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/total_summary.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_file_io.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/extend_ai_gui/skills → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_explainer.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_review.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_store.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/jupyter_lab_gui → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/extend_ai_gui/skills}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/extend_ai_gui/skills/skills_send_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/fixed_pitch.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/gui_thread_gc.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/jupyter_lab_gui}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/jupyter_lab_gui/jupyter_lab_thread.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/jupyter_lab_gui/jupyter_lab_widget.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/jupyter_lab_gui/lab_page.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/mcp_gui}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu/build_api_testka_menu.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu/build_autocontrol_menu.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu/build_automation_file_menu.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/automation_menu_factory.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu/build_load_density_menu.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu/build_mail_thunder_menu.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu/build_prthinker_menu.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu/build_test_pioneer_menu.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/install_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu/build_webrunner_menu.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/build_menubar.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/install_menu/automation_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu/jupyter_lab_tab.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/install_menu/tools_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/install_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/plugin_menu → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/install_menu/automation_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/install_menu/automation_menu/build_automation_install_menu.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/install_menu/install_utils.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/menu/tools → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/install_menu/tools_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/install_menu/tools_menu/build_tool_install_menu.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/menu_utils.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/show_code_window → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/plugin_menu}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/plugin_menu/build_plugin_menu.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/menu/plugin_menu/build_run_with_menu.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/syntax → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/menu/tools}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/pybreeze_ui/tools_gui → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/navigation}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/plain_text.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/report_gui}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/run_shortcut.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/curl_import → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/show_code_window}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/show_code_window/code_window.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/diff_tools → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/syntax}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/syntax/syntax_extend.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/syntax/syntax_keyword.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/terminal_view.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/exception → pybreeze_dev-1.0.19/pybreeze/pybreeze_ui/tools_gui}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/diff_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/hash_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/http_status_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/json_format_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/jwt_decoder_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/output_actions.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/query_json_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/regex_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/timestamp_gui.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/tool_tabs.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/pybreeze_ui/tools_gui/url_builder_gui.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/file_process → pybreeze_dev-1.0.19/pybreeze/utils}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/app_dirs.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/har_import → pybreeze_dev-1.0.19/pybreeze/utils/curl_import}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/curl_import/curl_parser.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/curl_import/request_body.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/curl_import/request_codegen.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/hash_tools → pybreeze_dev-1.0.19/pybreeze/utils/diff_tools}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/diff_tools/text_diff.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/header_tools → pybreeze_dev-1.0.19/pybreeze/utils/exception}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/exception/error_templates.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/http_reference → pybreeze_dev-1.0.19/pybreeze/utils/execution_report}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/jwt_tools → pybreeze_dev-1.0.19/pybreeze/utils/file_process}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/file_process/get_dir_file_list.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/file_process/read_capped.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/file_process/replace_file.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/logging → pybreeze_dev-1.0.19/pybreeze/utils/har_import}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/har_import/har_parser.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/manager → pybreeze_dev-1.0.19/pybreeze/utils/hash_tools}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/hash_tools/hash_text.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/manager/package_manager → pybreeze_dev-1.0.19/pybreeze/utils/header_tools}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/header_tools/header_merge.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/network → pybreeze_dev-1.0.19/pybreeze/utils/http_reference}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/http_reference/status_codes.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/query_tools → pybreeze_dev-1.0.19/pybreeze/utils/import_targets}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/json_format/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/json_format/view_safe.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/regex_tools → pybreeze_dev-1.0.19/pybreeze/utils/jwt_tools}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/jwt_tools/jwt_decoder.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/response_inspector → pybreeze_dev-1.0.19/pybreeze/utils/language_service}/__init__.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/timestamp_tools → pybreeze_dev-1.0.19/pybreeze/utils/logging}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/logging/logger.py +0 -0
- {pybreeze_dev-1.0.17/pybreeze/utils/url_tools → pybreeze_dev-1.0.19/pybreeze/utils/manager}/__init__.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/manager/package_manager/package_manager_class.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/network/http_client.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/network/public_http.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/query_tools/query_convert.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/regex_tools/regex_tester.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/response_inspector/response_analyzer.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/subprocess_util.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/terminal_style.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/terminal_text.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/timestamp_tools/timestamp_converter.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze/utils/url_tools/url_convert.py +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze_dev.egg-info/dependency_links.txt +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/pybreeze_dev.egg-info/top_level.txt +0 -0
- {pybreeze_dev-1.0.17 → pybreeze_dev-1.0.19}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pybreeze_dev
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.19
|
|
4
4
|
Summary: IDE for multi automation
|
|
5
5
|
Author-email: JE-Chen <jechenmailman@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/Integration-Automation/PyBreeze
|
|
@@ -24,7 +24,7 @@ Requires-Dist: je_web_runner
|
|
|
24
24
|
Requires-Dist: je_load_density
|
|
25
25
|
Requires-Dist: je_api_testka
|
|
26
26
|
Requires-Dist: je-mail-thunder
|
|
27
|
-
Requires-Dist: automation-file
|
|
27
|
+
Requires-Dist: automation-file[all]
|
|
28
28
|
Requires-Dist: PySide6==6.11.2
|
|
29
29
|
Requires-Dist: test_pioneer
|
|
30
30
|
Requires-Dist: paramiko
|
|
@@ -64,6 +64,7 @@ Dynamic: license-file
|
|
|
64
64
|
- [Dependencies](#dependencies)
|
|
65
65
|
- [Testing & CI](#testing--ci)
|
|
66
66
|
- [Target Audience](#target-audience)
|
|
67
|
+
- [Security](#security)
|
|
67
68
|
- [License](#license)
|
|
68
69
|
|
|
69
70
|
---
|
|
@@ -107,6 +108,8 @@ Each module gets the same menu shape: **Run** (single script, batch directory, w
|
|
|
107
108
|
|
|
108
109
|
- **Automation keyword sets** — the `AT_*` / GUI / Web / Load keyword sets are registered for `.json`, and TestPioneer's schema for `.yml` and `.yaml`, on top of JEditor's language support. JEditor does not colour them yet: it highlights those files with its own rules for the suffix, which leave registered keywords out
|
|
109
110
|
- **Code editor** — built on [JEditor](https://github.com/Integration-Automation/JEDITOR): tabs, project tree, format checker, debugger, terminal and a git client pane
|
|
111
|
+
- **Navigation panel** — a dock at the left lists what the menus hold as one tree (Automation, Tools, Settings): type in its box to find a tool or a command by name, then press Enter or double-click to open it. **Dock ▸ Navigation** shows and hides it, and a panel closed on purpose stays closed at the next start
|
|
112
|
+
- **Fits a small screen** — a tool tab never asks for more than 60 font heights of width: a row of buttons too long for the tab wraps onto the next line instead of pushing the window wider than the display
|
|
110
113
|
- **Script execution** — single or batch, each run in a window of its own with a Stop button (Run ▸ Stop All Program stops them all), which asks whether to stop the run when it is closed while the run goes on; action files are passed by path, and a script from the tab in front that is too long for a Windows command line (~32 KB) goes through a temporary file
|
|
111
114
|
- **Report generation** — HTML / JSON / XML after a run, with optional email delivery
|
|
112
115
|
- **Integrated JupyterLab** — launches as a tab, in the same interpreter a run would use, installing JupyterLab there if it is missing, and upgrading it and its server first when either is a release with a known vulnerability (JupyterLab before 4.5.10 or 4.6.0–4.6.1, jupyter_server before 2.20.0); the tab stays on the lab, and a link to anywhere else opens in your browser
|
|
@@ -126,7 +129,7 @@ Paste a `curl` command from your browser's dev tools and pick a target. The pars
|
|
|
126
129
|
|---|---|
|
|
127
130
|
|  |  |
|
|
128
131
|
|
|
129
|
-
Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly),
|
|
132
|
+
Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly), a **LoadDensity** Locust load test, and a **WebRunner** action list that visits the address in a browser. A target that cannot send everything a request holds says so under the output ("Not sent by this target: headers · the body"): a LoadDensity run drives a method and a URL, and a browser visit keeps the URL, the cookies and a time limit. Copy the output, open it straight into an editor tab, or save it with the right extension. One click also hands the parsed URL to the URL parser/builder or the headers to the header analyzer.
|
|
130
133
|
|
|
131
134
|
### HAR Import — a whole session becomes a test suite
|
|
132
135
|
|
|
@@ -148,12 +151,73 @@ The status code is looked up in the HTTP reference, headers are parsed, a JSON b
|
|
|
148
151
|
|
|
149
152
|
Reports names sent more than once, `Set-Cookie` entries missing `Secure` / `HttpOnly` / `SameSite` and those a browser drops outright (a `__Secure-` / `__Host-` name whose rules are broken, `SameSite=None` without `Secure`), wildcard CORS (and the wildcard-plus-credentials combination browsers reject outright), an HSTS `max-age` too short to survive a restart, CSP `unsafe-inline` / `unsafe-eval`, product banners, headers current browsers ignore (`X-XSS-Protection` other than `0`, `Expect-CT`, `Public-Key-Pins`, `P3P`, the old prefixed CSP names), and — for responses — the security headers that are absent, counting a CSP `frame-ancestors` directive as `X-Frame-Options`, as the OWASP HTTP Headers Cheat Sheet does. Headers carrying credentials are reported **by name only**; their values never enter the report.
|
|
150
153
|
|
|
154
|
+
**Export findings as SARIF** saves the analysis as a SARIF 2.1.0 file that GitHub Code Scanning and other security tooling read: each finding with its rule, level, line, what to do about it and a link. The same export runs without the IDE, for CI:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
python -m pybreeze.utils.header_tools.header_sarif response-headers.txt -o headers.sarif
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`-` reads the headers from standard input, leaving out `-o` writes to standard output, and `--fail-on-warning` exits with 1 when a finding is a warning. The report names rules and lines and quotes no header value.
|
|
161
|
+
|
|
151
162
|
### Text Diff
|
|
152
163
|
|
|
153
164
|

|
|
154
165
|
|
|
155
166
|
Compare two payloads — an expected vs. actual API response, say — and get a unified diff, its added and removed lines in the theme's colours, plus a one-line added/removed summary.
|
|
156
167
|
|
|
168
|
+
### Report Viewer
|
|
169
|
+
|
|
170
|
+
**Tools → Report Viewer Tab** opens what a run produced, whatever ran it, into one view.
|
|
171
|
+
|
|
172
|
+
- **Reads** the automation packages' own reports (APITestka, AutoControl, WebRunner, LoadDensity: the `<name>_success.json` / `<name>_failure.json` pair or the `.xml` pair; open either and the other is read with it), **JUnit XML** (pytest's `--junitxml`, and most other runners), and reports exported from PyBreeze. What a file is, is told from what it holds.
|
|
173
|
+
- **Shows** each run as a tree with how every result ended and how long it took; the selected result's details and error, its output, what it left behind, and the package's own record of it, untouched.
|
|
174
|
+
- **Filters** all open runs together: by ending (passed, failed, error, skipped), by time taken, by package, and by text in a name or an error. A line under the tree counts what is shown.
|
|
175
|
+
- **Exports** a run as an execution report (JSON), as **JUnit XML** for a CI service's test summary, or as one self-contained **HTML page** for people, which can be opened here again.
|
|
176
|
+
- The **MCP Client**'s Calls page opens its session here with **Open in Report Viewer**.
|
|
177
|
+
|
|
178
|
+
A report is a file from somewhere: it is read as data (XML that declares a document type is refused), everything in it is shown as text, and the paths it names are listed, not opened.
|
|
179
|
+
|
|
180
|
+
### MCP Client
|
|
181
|
+
|
|
182
|
+
**Tools → MCP Client Tab** connects to [Model Context Protocol](https://modelcontextprotocol.io) servers and shows what each offers: **tools** to call, **resources** to read, **prompts** to fill in.
|
|
183
|
+
|
|
184
|
+
- **Servers** are set up once and kept for you (`~/.pybreeze/mcp_servers.json`, readable by you alone): a name, the command that starts the server (one argument a line, never a shell line), its environment variables, and how long a request may take. The file uses the `mcpServers` layout other clients write, so a list made elsewhere can be dropped in.
|
|
185
|
+
- **A call is asked about first**: the tool, the server and the arguments as they will be sent, with No as the default. Tick *Do not ask again* to trust one tool of one server. What a server says of its own tool ("changes nothing") is shown, not relied on.
|
|
186
|
+
- **A server that comes with a project** (`.mcp.json` in the project folder) is listed, never started by itself: connecting to it shows its command and asks.
|
|
187
|
+
- **Cancel** gives up a call on its way; a server that does not answer within its time limit is given up on; one that goes away is said so, with the last line of its own log. **Connect** again to start over.
|
|
188
|
+
- **Calls** lists the session: when, which tool, how it ended, how long it took. **Export Session...** saves it as an execution report (JSON).
|
|
189
|
+
|
|
190
|
+
Put keys and tokens in the server's environment variables, not in its command: their values are shown as dots, and are taken out of the log, of error messages and of exported sessions wherever they turn up. Servers are started as local programs (the protocol's standard-input-and-output transport).
|
|
191
|
+
|
|
192
|
+
### Keywords for action scripts
|
|
193
|
+
|
|
194
|
+
A WebRunner, AutoControl or LoadDensity script is a JSON list of actions, `["keyword"]` or `["keyword", arguments]`. Open one (`.json`) in the editor and it is completed and checked against the keywords of the framework **as it is installed**:
|
|
195
|
+
|
|
196
|
+
- **Completion** — the framework's keywords where an action's name goes, a keyword's parameters where an argument's name goes.
|
|
197
|
+
- **Diagnostics** — a keyword that version does not have (with the nearest one suggested), a parameter the keyword does not take, a required one left out, a list of values of the wrong length, an action of the wrong shape, and text that is not JSON. In the IDE's language.
|
|
198
|
+
- **Hover** and **go to definition** — a keyword's signature and documentation, and the line of the package that defines it.
|
|
199
|
+
|
|
200
|
+
Nothing about a keyword is kept in PyBreeze. Each framework is asked, in a process of its own, by the interpreter that runs your scripts (the one chosen in the IDE, a `.venv` in the project, else the IDE's own), so upgrading a framework changes what is offered. A framework that is missing or fails to import costs its own keywords and nothing else.
|
|
201
|
+
|
|
202
|
+
**Tools → Automation Keywords Tab** shows the same keywords: each framework's version, what the editor offers for it, every keyword with its parameters and documentation, a filter, and **Copy as Action**. When a framework gives none, it says why.
|
|
203
|
+
|
|
204
|
+
The editor gets all this from a language server, which any editor that speaks the Language Server Protocol can start too:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
python -m pybreeze.extend.language_server [--interpreter /path/to/python] [--language Traditional_Chinese]
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### JSON Editor
|
|
211
|
+
|
|
212
|
+
Edit a JSON file as a **Tree** or as **Text** (**Tools → JSON Editor Tab**). Both are views of one document, so they cannot disagree.
|
|
213
|
+
|
|
214
|
+
- **Tree** — add, delete, move up or down, and rename in place; type over a value, or give it another type (object, array, string, number, boolean, null). A number is kept as it is written: `1.0` stays `1.0`.
|
|
215
|
+
- **Text** — the JSON itself, always there. It is checked as you type and a line under the views says where it stops being JSON; the tree waits until it is JSON again, and nothing typed is thrown away.
|
|
216
|
+
- **Undo / Redo** step through the document whichever view changed it, and a tab with unsaved changes asks before it closes or opens another file.
|
|
217
|
+
- A file is written back the way it was found: its indent (spaces or tabs), on one line if it was, with its final line break. Alignment by hand and blank lines are not kept by an edit in the tree.
|
|
218
|
+
|
|
219
|
+
It is a JSON editor, not a second code editor: a file is opened into it from its **Open...** button.
|
|
220
|
+
|
|
157
221
|
### The everyday utilities
|
|
158
222
|
|
|
159
223
|
Each is a tab or a dock, each has the same copy / open-in-editor / save-to-file row along the bottom.
|
|
@@ -248,7 +312,7 @@ Loaded plugins appear under their own **Plugins** menu with an About entry and o
|
|
|
248
312
|
- **English** (default)
|
|
249
313
|
- **Traditional Chinese** (繁體中文)
|
|
250
314
|
|
|
251
|
-
Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same
|
|
315
|
+
Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same 995 keys, and a test enforces that parity so a new string can never land in one language only. English and Traditional Chinese are the languages PyBreeze maintains. The Language menu also lists JEditor's Japanese (日本語) and Simplified Chinese (简体中文), which PyBreeze passes on without translating: picked, JEditor's own menus change and PyBreeze's strings stay in English. Further languages can be added via translation plugins.
|
|
252
316
|
|
|
253
317
|
---
|
|
254
318
|
|
|
@@ -377,6 +441,8 @@ Once launched:
|
|
|
377
441
|
4. **Generate** an HTML / JSON / XML report
|
|
378
442
|
5. **Send** it by email through the MailThunder integration
|
|
379
443
|
|
|
444
|
+
New here? The [tutorials](https://pybreeze.readthedocs.io/en/latest/Eng/tutorials/index.html) are thirteen short pages, each with an example that runs and what to expect from it: the first launch, a first API, browser, desktop and load run, tests from cURL and HAR, header findings as SARIF in CI, the JSON editor, keywords for action scripts, the MCP client, reports in CI, plugins, and troubleshooting. They test a small site on your own machine, so none of them needs an account.
|
|
445
|
+
|
|
380
446
|
### Log file
|
|
381
447
|
|
|
382
448
|
PyBreeze writes its log to `~/.pybreeze/logs/PyBreeze.log`: UTF-8, appended to by every run, each line carrying the process ID. Only warnings and errors also appear in the editor's Code Result panel. Two environment variables change this:
|
|
@@ -482,7 +548,7 @@ python -m pytest test/test_utils/ -v --tb=short
|
|
|
482
548
|
|
|
483
549
|
- **Unit tests** — `test/test_utils/`, covering the pure-logic layer (curl and HAR parsing, header analysis, SSRF validation, JWT, hashing, timestamps, diffing) plus headless Qt widget tests via `QT_QPA_PLATFORM=offscreen`, with Hypothesis property tests over the parsers. The SSH terminal and the SFTP file tree also log in to an SSH server the tests start on the loopback address, which serves a temporary folder over SFTP
|
|
484
550
|
- **Startup tests** — `test/unit_test/start_automation/` launches the IDE in debug mode and verifies it comes up and exits cleanly
|
|
485
|
-
- **CI** — GitHub Actions on Windows across Python 3.10 – 3.14, on every push and PR plus a nightly run; a push to `dev` that passes also publishes `pybreeze_dev` when the package changed
|
|
551
|
+
- **CI** — GitHub Actions: the whole suite on Windows across Python 3.10 – 3.14, and a short set of platform smoke tests on Linux and macOS, on every push and PR plus a nightly run; a push to `dev` that passes the suite also publishes `pybreeze_dev` when the package changed
|
|
486
552
|
- **Static analysis** — SonarCloud, Codacy and Bandit
|
|
487
553
|
|
|
488
554
|
---
|
|
@@ -496,6 +562,10 @@ python -m pytest test/test_utils/ -v --tb=short
|
|
|
496
562
|
|
|
497
563
|
---
|
|
498
564
|
|
|
565
|
+
## Security
|
|
566
|
+
|
|
567
|
+
Report vulnerabilities privately. The policy, supported versions, and operator notes are in [SECURITY.md](SECURITY.md).
|
|
568
|
+
|
|
499
569
|
## License
|
|
500
570
|
|
|
501
571
|
MIT — see [LICENSE](LICENSE). Copyright (c) 2022 JE-Chen
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
- [Dependencies](#dependencies)
|
|
32
32
|
- [Testing & CI](#testing--ci)
|
|
33
33
|
- [Target Audience](#target-audience)
|
|
34
|
+
- [Security](#security)
|
|
34
35
|
- [License](#license)
|
|
35
36
|
|
|
36
37
|
---
|
|
@@ -74,6 +75,8 @@ Each module gets the same menu shape: **Run** (single script, batch directory, w
|
|
|
74
75
|
|
|
75
76
|
- **Automation keyword sets** — the `AT_*` / GUI / Web / Load keyword sets are registered for `.json`, and TestPioneer's schema for `.yml` and `.yaml`, on top of JEditor's language support. JEditor does not colour them yet: it highlights those files with its own rules for the suffix, which leave registered keywords out
|
|
76
77
|
- **Code editor** — built on [JEditor](https://github.com/Integration-Automation/JEDITOR): tabs, project tree, format checker, debugger, terminal and a git client pane
|
|
78
|
+
- **Navigation panel** — a dock at the left lists what the menus hold as one tree (Automation, Tools, Settings): type in its box to find a tool or a command by name, then press Enter or double-click to open it. **Dock ▸ Navigation** shows and hides it, and a panel closed on purpose stays closed at the next start
|
|
79
|
+
- **Fits a small screen** — a tool tab never asks for more than 60 font heights of width: a row of buttons too long for the tab wraps onto the next line instead of pushing the window wider than the display
|
|
77
80
|
- **Script execution** — single or batch, each run in a window of its own with a Stop button (Run ▸ Stop All Program stops them all), which asks whether to stop the run when it is closed while the run goes on; action files are passed by path, and a script from the tab in front that is too long for a Windows command line (~32 KB) goes through a temporary file
|
|
78
81
|
- **Report generation** — HTML / JSON / XML after a run, with optional email delivery
|
|
79
82
|
- **Integrated JupyterLab** — launches as a tab, in the same interpreter a run would use, installing JupyterLab there if it is missing, and upgrading it and its server first when either is a release with a known vulnerability (JupyterLab before 4.5.10 or 4.6.0–4.6.1, jupyter_server before 2.20.0); the tab stays on the lab, and a link to anywhere else opens in your browser
|
|
@@ -93,7 +96,7 @@ Paste a `curl` command from your browser's dev tools and pick a target. The pars
|
|
|
93
96
|
|---|---|
|
|
94
97
|
|  |  |
|
|
95
98
|
|
|
96
|
-
Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly),
|
|
99
|
+
Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly), a **LoadDensity** Locust load test, and a **WebRunner** action list that visits the address in a browser. A target that cannot send everything a request holds says so under the output ("Not sent by this target: headers · the body"): a LoadDensity run drives a method and a URL, and a browser visit keeps the URL, the cookies and a time limit. Copy the output, open it straight into an editor tab, or save it with the right extension. One click also hands the parsed URL to the URL parser/builder or the headers to the header analyzer.
|
|
97
100
|
|
|
98
101
|
### HAR Import — a whole session becomes a test suite
|
|
99
102
|
|
|
@@ -115,12 +118,73 @@ The status code is looked up in the HTTP reference, headers are parsed, a JSON b
|
|
|
115
118
|
|
|
116
119
|
Reports names sent more than once, `Set-Cookie` entries missing `Secure` / `HttpOnly` / `SameSite` and those a browser drops outright (a `__Secure-` / `__Host-` name whose rules are broken, `SameSite=None` without `Secure`), wildcard CORS (and the wildcard-plus-credentials combination browsers reject outright), an HSTS `max-age` too short to survive a restart, CSP `unsafe-inline` / `unsafe-eval`, product banners, headers current browsers ignore (`X-XSS-Protection` other than `0`, `Expect-CT`, `Public-Key-Pins`, `P3P`, the old prefixed CSP names), and — for responses — the security headers that are absent, counting a CSP `frame-ancestors` directive as `X-Frame-Options`, as the OWASP HTTP Headers Cheat Sheet does. Headers carrying credentials are reported **by name only**; their values never enter the report.
|
|
117
120
|
|
|
121
|
+
**Export findings as SARIF** saves the analysis as a SARIF 2.1.0 file that GitHub Code Scanning and other security tooling read: each finding with its rule, level, line, what to do about it and a link. The same export runs without the IDE, for CI:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
python -m pybreeze.utils.header_tools.header_sarif response-headers.txt -o headers.sarif
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`-` reads the headers from standard input, leaving out `-o` writes to standard output, and `--fail-on-warning` exits with 1 when a finding is a warning. The report names rules and lines and quotes no header value.
|
|
128
|
+
|
|
118
129
|
### Text Diff
|
|
119
130
|
|
|
120
131
|

|
|
121
132
|
|
|
122
133
|
Compare two payloads — an expected vs. actual API response, say — and get a unified diff, its added and removed lines in the theme's colours, plus a one-line added/removed summary.
|
|
123
134
|
|
|
135
|
+
### Report Viewer
|
|
136
|
+
|
|
137
|
+
**Tools → Report Viewer Tab** opens what a run produced, whatever ran it, into one view.
|
|
138
|
+
|
|
139
|
+
- **Reads** the automation packages' own reports (APITestka, AutoControl, WebRunner, LoadDensity: the `<name>_success.json` / `<name>_failure.json` pair or the `.xml` pair; open either and the other is read with it), **JUnit XML** (pytest's `--junitxml`, and most other runners), and reports exported from PyBreeze. What a file is, is told from what it holds.
|
|
140
|
+
- **Shows** each run as a tree with how every result ended and how long it took; the selected result's details and error, its output, what it left behind, and the package's own record of it, untouched.
|
|
141
|
+
- **Filters** all open runs together: by ending (passed, failed, error, skipped), by time taken, by package, and by text in a name or an error. A line under the tree counts what is shown.
|
|
142
|
+
- **Exports** a run as an execution report (JSON), as **JUnit XML** for a CI service's test summary, or as one self-contained **HTML page** for people, which can be opened here again.
|
|
143
|
+
- The **MCP Client**'s Calls page opens its session here with **Open in Report Viewer**.
|
|
144
|
+
|
|
145
|
+
A report is a file from somewhere: it is read as data (XML that declares a document type is refused), everything in it is shown as text, and the paths it names are listed, not opened.
|
|
146
|
+
|
|
147
|
+
### MCP Client
|
|
148
|
+
|
|
149
|
+
**Tools → MCP Client Tab** connects to [Model Context Protocol](https://modelcontextprotocol.io) servers and shows what each offers: **tools** to call, **resources** to read, **prompts** to fill in.
|
|
150
|
+
|
|
151
|
+
- **Servers** are set up once and kept for you (`~/.pybreeze/mcp_servers.json`, readable by you alone): a name, the command that starts the server (one argument a line, never a shell line), its environment variables, and how long a request may take. The file uses the `mcpServers` layout other clients write, so a list made elsewhere can be dropped in.
|
|
152
|
+
- **A call is asked about first**: the tool, the server and the arguments as they will be sent, with No as the default. Tick *Do not ask again* to trust one tool of one server. What a server says of its own tool ("changes nothing") is shown, not relied on.
|
|
153
|
+
- **A server that comes with a project** (`.mcp.json` in the project folder) is listed, never started by itself: connecting to it shows its command and asks.
|
|
154
|
+
- **Cancel** gives up a call on its way; a server that does not answer within its time limit is given up on; one that goes away is said so, with the last line of its own log. **Connect** again to start over.
|
|
155
|
+
- **Calls** lists the session: when, which tool, how it ended, how long it took. **Export Session...** saves it as an execution report (JSON).
|
|
156
|
+
|
|
157
|
+
Put keys and tokens in the server's environment variables, not in its command: their values are shown as dots, and are taken out of the log, of error messages and of exported sessions wherever they turn up. Servers are started as local programs (the protocol's standard-input-and-output transport).
|
|
158
|
+
|
|
159
|
+
### Keywords for action scripts
|
|
160
|
+
|
|
161
|
+
A WebRunner, AutoControl or LoadDensity script is a JSON list of actions, `["keyword"]` or `["keyword", arguments]`. Open one (`.json`) in the editor and it is completed and checked against the keywords of the framework **as it is installed**:
|
|
162
|
+
|
|
163
|
+
- **Completion** — the framework's keywords where an action's name goes, a keyword's parameters where an argument's name goes.
|
|
164
|
+
- **Diagnostics** — a keyword that version does not have (with the nearest one suggested), a parameter the keyword does not take, a required one left out, a list of values of the wrong length, an action of the wrong shape, and text that is not JSON. In the IDE's language.
|
|
165
|
+
- **Hover** and **go to definition** — a keyword's signature and documentation, and the line of the package that defines it.
|
|
166
|
+
|
|
167
|
+
Nothing about a keyword is kept in PyBreeze. Each framework is asked, in a process of its own, by the interpreter that runs your scripts (the one chosen in the IDE, a `.venv` in the project, else the IDE's own), so upgrading a framework changes what is offered. A framework that is missing or fails to import costs its own keywords and nothing else.
|
|
168
|
+
|
|
169
|
+
**Tools → Automation Keywords Tab** shows the same keywords: each framework's version, what the editor offers for it, every keyword with its parameters and documentation, a filter, and **Copy as Action**. When a framework gives none, it says why.
|
|
170
|
+
|
|
171
|
+
The editor gets all this from a language server, which any editor that speaks the Language Server Protocol can start too:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
python -m pybreeze.extend.language_server [--interpreter /path/to/python] [--language Traditional_Chinese]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### JSON Editor
|
|
178
|
+
|
|
179
|
+
Edit a JSON file as a **Tree** or as **Text** (**Tools → JSON Editor Tab**). Both are views of one document, so they cannot disagree.
|
|
180
|
+
|
|
181
|
+
- **Tree** — add, delete, move up or down, and rename in place; type over a value, or give it another type (object, array, string, number, boolean, null). A number is kept as it is written: `1.0` stays `1.0`.
|
|
182
|
+
- **Text** — the JSON itself, always there. It is checked as you type and a line under the views says where it stops being JSON; the tree waits until it is JSON again, and nothing typed is thrown away.
|
|
183
|
+
- **Undo / Redo** step through the document whichever view changed it, and a tab with unsaved changes asks before it closes or opens another file.
|
|
184
|
+
- A file is written back the way it was found: its indent (spaces or tabs), on one line if it was, with its final line break. Alignment by hand and blank lines are not kept by an edit in the tree.
|
|
185
|
+
|
|
186
|
+
It is a JSON editor, not a second code editor: a file is opened into it from its **Open...** button.
|
|
187
|
+
|
|
124
188
|
### The everyday utilities
|
|
125
189
|
|
|
126
190
|
Each is a tab or a dock, each has the same copy / open-in-editor / save-to-file row along the bottom.
|
|
@@ -215,7 +279,7 @@ Loaded plugins appear under their own **Plugins** menu with an About entry and o
|
|
|
215
279
|
- **English** (default)
|
|
216
280
|
- **Traditional Chinese** (繁體中文)
|
|
217
281
|
|
|
218
|
-
Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same
|
|
282
|
+
Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same 995 keys, and a test enforces that parity so a new string can never land in one language only. English and Traditional Chinese are the languages PyBreeze maintains. The Language menu also lists JEditor's Japanese (日本語) and Simplified Chinese (简体中文), which PyBreeze passes on without translating: picked, JEditor's own menus change and PyBreeze's strings stay in English. Further languages can be added via translation plugins.
|
|
219
283
|
|
|
220
284
|
---
|
|
221
285
|
|
|
@@ -344,6 +408,8 @@ Once launched:
|
|
|
344
408
|
4. **Generate** an HTML / JSON / XML report
|
|
345
409
|
5. **Send** it by email through the MailThunder integration
|
|
346
410
|
|
|
411
|
+
New here? The [tutorials](https://pybreeze.readthedocs.io/en/latest/Eng/tutorials/index.html) are thirteen short pages, each with an example that runs and what to expect from it: the first launch, a first API, browser, desktop and load run, tests from cURL and HAR, header findings as SARIF in CI, the JSON editor, keywords for action scripts, the MCP client, reports in CI, plugins, and troubleshooting. They test a small site on your own machine, so none of them needs an account.
|
|
412
|
+
|
|
347
413
|
### Log file
|
|
348
414
|
|
|
349
415
|
PyBreeze writes its log to `~/.pybreeze/logs/PyBreeze.log`: UTF-8, appended to by every run, each line carrying the process ID. Only warnings and errors also appear in the editor's Code Result panel. Two environment variables change this:
|
|
@@ -449,7 +515,7 @@ python -m pytest test/test_utils/ -v --tb=short
|
|
|
449
515
|
|
|
450
516
|
- **Unit tests** — `test/test_utils/`, covering the pure-logic layer (curl and HAR parsing, header analysis, SSRF validation, JWT, hashing, timestamps, diffing) plus headless Qt widget tests via `QT_QPA_PLATFORM=offscreen`, with Hypothesis property tests over the parsers. The SSH terminal and the SFTP file tree also log in to an SSH server the tests start on the loopback address, which serves a temporary folder over SFTP
|
|
451
517
|
- **Startup tests** — `test/unit_test/start_automation/` launches the IDE in debug mode and verifies it comes up and exits cleanly
|
|
452
|
-
- **CI** — GitHub Actions on Windows across Python 3.10 – 3.14, on every push and PR plus a nightly run; a push to `dev` that passes also publishes `pybreeze_dev` when the package changed
|
|
518
|
+
- **CI** — GitHub Actions: the whole suite on Windows across Python 3.10 – 3.14, and a short set of platform smoke tests on Linux and macOS, on every push and PR plus a nightly run; a push to `dev` that passes the suite also publishes `pybreeze_dev` when the package changed
|
|
453
519
|
- **Static analysis** — SonarCloud, Codacy and Bandit
|
|
454
520
|
|
|
455
521
|
---
|
|
@@ -463,6 +529,10 @@ python -m pytest test/test_utils/ -v --tb=short
|
|
|
463
529
|
|
|
464
530
|
---
|
|
465
531
|
|
|
532
|
+
## Security
|
|
533
|
+
|
|
534
|
+
Report vulnerabilities privately. The policy, supported versions, and operator notes are in [SECURITY.md](SECURITY.md).
|
|
535
|
+
|
|
466
536
|
## License
|
|
467
537
|
|
|
468
538
|
MIT — see [LICENSE](LICENSE). Copyright (c) 2022 JE-Chen
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""The action language server as a process the editor starts (``python -m pybreeze.extend.language_server``).
|
|
2
|
+
|
|
3
|
+
The protocol and the answers are in ``pybreeze/utils/language_service/``. Here
|
|
4
|
+
is what makes a process of them: the entry point, the frameworks asked for
|
|
5
|
+
their keywords, and the command JEditor's editors start it with.
|
|
6
|
+
"""
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Start the action language server on this process's standard input and output."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
# The editor starts this file by its path, not with -m: the folder the IDE is
|
|
8
|
+
# in (a project someone opened) is then not on the import path, and a package
|
|
9
|
+
# there called pybreeze is not what gets imported. Started that way the path
|
|
10
|
+
# begins with this folder, and the folder PyBreeze is in takes its place.
|
|
11
|
+
if not __package__:
|
|
12
|
+
sys.path[0] = str(Path(__file__).resolve().parents[3])
|
|
13
|
+
|
|
14
|
+
from pybreeze.extend.language_server.server_main import main # noqa: E402 — the import path is set first
|
|
15
|
+
|
|
16
|
+
if __name__ == "__main__":
|
|
17
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Have JEditor's editors start the action language server for JSON files.
|
|
2
|
+
|
|
3
|
+
JEditor's editor asks a language server about the file it holds, chosen by the
|
|
4
|
+
file's suffix from ``je_editor.utils.lsp.language_servers.DEFAULT_SERVERS``.
|
|
5
|
+
PyBreeze puts its own server there for ``.json``: the automation scripts are
|
|
6
|
+
JSON, and for any other JSON file the server says only whether it is JSON.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from je_editor.utils.lsp.language_servers import DEFAULT_SERVERS
|
|
14
|
+
|
|
15
|
+
# The files the server answers for
|
|
16
|
+
ACTION_SCRIPT_SUFFIX = ".json"
|
|
17
|
+
_ENTRY = Path(__file__).with_name("__main__.py")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def can_serve() -> bool:
|
|
21
|
+
"""Whether there is an interpreter to run the server with: not in a packaged build, where ``sys.executable`` is the app."""
|
|
22
|
+
return not getattr(sys, "frozen", False)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def server_command(interpreter: str | None, language: str) -> list[str]:
|
|
26
|
+
"""The command that starts the server.
|
|
27
|
+
|
|
28
|
+
The entry is named by its path rather than with ``-m``, which would put
|
|
29
|
+
the folder the IDE is in first on the server's import path.
|
|
30
|
+
|
|
31
|
+
:param interpreter: the Python that runs the scripts; the IDE's own when ``None``
|
|
32
|
+
:param language: the IDE's language, by JEditor's name for it
|
|
33
|
+
"""
|
|
34
|
+
command = [sys.executable, str(_ENTRY), "--language", language]
|
|
35
|
+
if interpreter:
|
|
36
|
+
command += ["--interpreter", interpreter]
|
|
37
|
+
return command
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def offer_to_jeditor(interpreter: str | None, language: str) -> None:
|
|
41
|
+
"""Make the action language server the one JEditor's editors start for a JSON file."""
|
|
42
|
+
DEFAULT_SERVERS[ACTION_SCRIPT_SUFFIX] = server_command(interpreter, language)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""The action language server's process: its arguments, the frameworks it asks, the language it answers in."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
from collections.abc import Callable
|
|
7
|
+
from functools import partial
|
|
8
|
+
from importlib import metadata as installed
|
|
9
|
+
|
|
10
|
+
from pybreeze.extend_multi_language.supported_languages import MAINTAINED
|
|
11
|
+
from pybreeze.utils.exception.exceptions import LanguageServiceException
|
|
12
|
+
from pybreeze.utils.language_service.framework_profiles import PROFILES, FrameworkProfile
|
|
13
|
+
from pybreeze.utils.language_service.lsp_server import ActionLanguageServer, serve
|
|
14
|
+
from pybreeze.utils.language_service.metadata_probe import read_metadata
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def words_of(language: str) -> dict[str, str]:
|
|
18
|
+
"""PyBreeze's strings in *language*; in English for a language PyBreeze does not maintain."""
|
|
19
|
+
return next((each.words for each in MAINTAINED if each.key == language), MAINTAINED[0].words)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def server_version() -> str:
|
|
23
|
+
"""The installed PyBreeze's version; empty when it runs from a source tree."""
|
|
24
|
+
try:
|
|
25
|
+
return installed.version("pybreeze")
|
|
26
|
+
except installed.PackageNotFoundError:
|
|
27
|
+
return ""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def ask_framework(
|
|
31
|
+
server: ActionLanguageServer, profile: FrameworkProfile, interpreter: str | None) -> Callable[[], list[dict]]:
|
|
32
|
+
"""Ask *profile*'s framework for its keywords, and return what gives *server* the answer.
|
|
33
|
+
|
|
34
|
+
The asking imports the framework in a process of its own and takes
|
|
35
|
+
seconds: the server runs this on a thread and goes on answering.
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
metadata = read_metadata(profile, interpreter)
|
|
39
|
+
except LanguageServiceException as error:
|
|
40
|
+
return partial(server.decline, profile.framework, str(error))
|
|
41
|
+
return partial(server.offer, metadata)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def main(arguments: list[str]) -> int:
|
|
45
|
+
"""Serve the protocol on standard input and output until the editor says ``exit`` or goes away."""
|
|
46
|
+
parser = argparse.ArgumentParser(
|
|
47
|
+
prog="python -m pybreeze.extend.language_server",
|
|
48
|
+
description="Language server for WebRunner, AutoControl and LoadDensity action scripts (JSON), "
|
|
49
|
+
"speaking the Language Server Protocol on standard input and output.")
|
|
50
|
+
parser.add_argument("--interpreter", default=None,
|
|
51
|
+
help="the Python that runs the scripts, whose installed frameworks are asked for their "
|
|
52
|
+
"keywords (default: the one running this server)")
|
|
53
|
+
parser.add_argument("--language", default=MAINTAINED[0].key,
|
|
54
|
+
help="the language of the diagnostics, as the IDE names it (default: %(default)s)")
|
|
55
|
+
options = parser.parse_args(arguments)
|
|
56
|
+
server = ActionLanguageServer(words_of(options.language), server_version())
|
|
57
|
+
serve(server, sys.stdin.buffer, sys.stdout.buffer,
|
|
58
|
+
[partial(ask_framework, server, profile, options.interpreter) for profile in PROFILES])
|
|
59
|
+
return 0
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""PyBreeze's English strings for the features that reach outside the IDE.
|
|
2
|
+
|
|
3
|
+
The frameworks' keywords and the language service that answers the editor from
|
|
4
|
+
them, and the MCP client. They are merged into ``pybreeze_english_word_dict``
|
|
5
|
+
(``extend_english.py``), which is the dictionary everything reads: this file
|
|
6
|
+
only keeps that one under a thousand lines.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
ENGLISH_INTEGRATION_WORDS: dict[str, str] = {
|
|
11
|
+
# MCP client
|
|
12
|
+
"extend_tools_menu_mcp_client_tab_action": "MCP Client Tab",
|
|
13
|
+
"extend_tools_menu_mcp_client_tab_label": "MCP Client",
|
|
14
|
+
"extend_tools_menu_mcp_client_dock_action": "MCP Client Dock",
|
|
15
|
+
"extend_tools_menu_mcp_client_dock_title": "MCP Client",
|
|
16
|
+
"mcp_servers_label": "Servers",
|
|
17
|
+
"mcp_servers_found_label": "{name} (from this project)",
|
|
18
|
+
"mcp_servers_add_button": "Add...",
|
|
19
|
+
"mcp_servers_edit_button": "Edit...",
|
|
20
|
+
"mcp_servers_remove_button": "Remove",
|
|
21
|
+
"mcp_servers_connect_button": "Connect",
|
|
22
|
+
"mcp_servers_disconnect_button": "Disconnect",
|
|
23
|
+
"mcp_servers_remove_title": "Remove a server",
|
|
24
|
+
"mcp_servers_remove_question": "Remove {name} from your servers?",
|
|
25
|
+
"mcp_page_tools": "Tools",
|
|
26
|
+
"mcp_page_resources": "Resources",
|
|
27
|
+
"mcp_page_prompts": "Prompts",
|
|
28
|
+
"mcp_page_calls": "Calls",
|
|
29
|
+
"mcp_tools_filter_placeholder": "Filter the tools",
|
|
30
|
+
"mcp_tools_arguments_label": "Arguments (a JSON object):",
|
|
31
|
+
"mcp_tools_call_button": "Call",
|
|
32
|
+
"mcp_tools_cancel_button": "Cancel",
|
|
33
|
+
"mcp_tools_hint_read_only": "The server says this tool changes nothing.",
|
|
34
|
+
"mcp_tools_hint_destructive": "The server says this tool may destroy or overwrite something.",
|
|
35
|
+
"mcp_tools_hint_unknown": "The server does not say whether this tool changes anything.",
|
|
36
|
+
"mcp_result_cut": "(cut here: {shown} of {whole} characters are shown)",
|
|
37
|
+
"mcp_resources_read_button": "Read",
|
|
38
|
+
"mcp_prompts_get_button": "Get",
|
|
39
|
+
"mcp_prompts_arguments_label": "Arguments (a JSON object of texts):",
|
|
40
|
+
"mcp_calls_column_when": "When",
|
|
41
|
+
"mcp_calls_column_tool": "Tool",
|
|
42
|
+
"mcp_calls_column_status": "Ended",
|
|
43
|
+
"mcp_calls_column_seconds": "Seconds",
|
|
44
|
+
"mcp_calls_status_passed": "answered",
|
|
45
|
+
"mcp_calls_status_failed": "failed",
|
|
46
|
+
"mcp_calls_status_error": "not answered",
|
|
47
|
+
"mcp_calls_status_skipped": "not called",
|
|
48
|
+
"mcp_calls_export_button": "Export Session...",
|
|
49
|
+
"mcp_calls_export_title": "Export the session",
|
|
50
|
+
"mcp_calls_file_filter": "JSON (*.json)",
|
|
51
|
+
"mcp_client_not_connected": "Not connected. Choose a server and connect.",
|
|
52
|
+
"mcp_client_servers_unreadable": "Your MCP servers could not be read: {reason}",
|
|
53
|
+
"mcp_client_connecting": "Connecting to {name}...",
|
|
54
|
+
"mcp_client_connected": "Connected to {server}: {tools} tools, {resources} resources, {prompts} prompts",
|
|
55
|
+
"mcp_client_disconnected": "Disconnected from {name}",
|
|
56
|
+
"mcp_client_failed_with_log": "{reason}. The server's log ends: {line}",
|
|
57
|
+
"mcp_client_arguments_not_object": "The arguments have to be a JSON object: names and their values, in braces",
|
|
58
|
+
"mcp_client_calling": "Calling {tool}...",
|
|
59
|
+
"mcp_client_called": "{tool} answered in {seconds} s",
|
|
60
|
+
"mcp_client_tool_failed": "{tool} ran and says it failed",
|
|
61
|
+
"mcp_client_declined": "{tool} was not called",
|
|
62
|
+
"mcp_client_fetching": "Getting {name}...",
|
|
63
|
+
"mcp_client_fetched": "Done",
|
|
64
|
+
"mcp_client_exported": "The session was saved to {file}",
|
|
65
|
+
"mcp_confirm_title": "Call an MCP tool",
|
|
66
|
+
"mcp_confirm_question": "Call {tool} on {server}?",
|
|
67
|
+
"mcp_confirm_arguments": "It will be called with:",
|
|
68
|
+
"mcp_confirm_trust": "Do not ask again for {tool} on {server}",
|
|
69
|
+
"mcp_found_title": "Start a server from this project",
|
|
70
|
+
"mcp_found_question":
|
|
71
|
+
"{name} comes from a file in the project folder (.mcp.json), not from your own servers. Starting it runs this command on your machine. Start it?",
|
|
72
|
+
"mcp_profile_dialog_title": "MCP server",
|
|
73
|
+
"mcp_profile_name_label": "Name:",
|
|
74
|
+
"mcp_profile_command_label": "Command:",
|
|
75
|
+
"mcp_profile_command_placeholder": "The program, then one argument on each line",
|
|
76
|
+
"mcp_profile_folder_label": "Start in:",
|
|
77
|
+
"mcp_profile_browse_button": "Browse...",
|
|
78
|
+
"mcp_profile_timeout_label": "Seconds a request may take:",
|
|
79
|
+
"mcp_profile_environment_label": "Environment variables:",
|
|
80
|
+
"mcp_profile_environment_note":
|
|
81
|
+
"Keys and tokens go here, not in the command: the command is shown when the server is started, and these values are not. They are kept in a file only you can read, and left out of the log and of exported sessions.",
|
|
82
|
+
"mcp_profile_variable_name": "Name",
|
|
83
|
+
"mcp_profile_variable_value": "Value",
|
|
84
|
+
"mcp_profile_add_variable_button": "Add Variable",
|
|
85
|
+
"mcp_profile_remove_variable_button": "Remove Variable",
|
|
86
|
+
"mcp_profile_show_values": "Show values",
|
|
87
|
+
"mcp_profile_needs_name": "A server needs a name",
|
|
88
|
+
"mcp_profile_name_taken": "Another server already has that name",
|
|
89
|
+
"mcp_profile_needs_command": "A server needs a command: the program that starts it",
|
|
90
|
+
# Report viewer
|
|
91
|
+
"extend_tools_menu_report_viewer_tab_action": "Report Viewer Tab",
|
|
92
|
+
"extend_tools_menu_report_viewer_tab_label": "Report Viewer",
|
|
93
|
+
"extend_tools_menu_report_viewer_dock_action": "Report Viewer Dock",
|
|
94
|
+
"extend_tools_menu_report_viewer_dock_title": "Report Viewer",
|
|
95
|
+
"report_status_passed": "passed",
|
|
96
|
+
"report_status_failed": "failed",
|
|
97
|
+
"report_status_error": "error",
|
|
98
|
+
"report_status_skipped": "skipped",
|
|
99
|
+
"report_column_name": "Name",
|
|
100
|
+
"report_column_status": "Ended",
|
|
101
|
+
"report_column_seconds": "Seconds",
|
|
102
|
+
"report_html_detail": "What it said",
|
|
103
|
+
"report_html_output": "Output",
|
|
104
|
+
"report_html_seconds": "{seconds} s",
|
|
105
|
+
"report_format_json": "Execution report",
|
|
106
|
+
"report_format_junit": "JUnit XML",
|
|
107
|
+
"report_format_html": "HTML page",
|
|
108
|
+
"report_viewer_open_button": "Open...",
|
|
109
|
+
"report_viewer_export_button": "Export...",
|
|
110
|
+
"report_viewer_close_button": "Close Report",
|
|
111
|
+
"report_viewer_at_least_label": "At least (s):",
|
|
112
|
+
"report_viewer_every_framework": "Every package",
|
|
113
|
+
"report_viewer_filter_placeholder": "Filter by name or error",
|
|
114
|
+
"report_viewer_tab_details": "Details",
|
|
115
|
+
"report_viewer_tab_output": "Output",
|
|
116
|
+
"report_viewer_tab_attachments": "Attachments",
|
|
117
|
+
"report_viewer_tab_raw": "Own record",
|
|
118
|
+
"report_viewer_open_title": "Open reports",
|
|
119
|
+
"report_viewer_open_filter": "Reports (*.json *.xml *.html *.htm);;All Files (*)",
|
|
120
|
+
"report_viewer_export_title": "Export the report",
|
|
121
|
+
"report_viewer_not_read": "{file} was not opened: {reason}",
|
|
122
|
+
"report_viewer_exported": "The report was saved to {file}",
|
|
123
|
+
"report_viewer_nothing_open":
|
|
124
|
+
"No report is open. Open a package's _success or _failure file, JUnit XML, or an exported report.",
|
|
125
|
+
"report_viewer_summary": "{shown} of {every} results shown, from {runs} reports, {seconds} s",
|
|
126
|
+
"mcp_calls_view_button": "Open in Report Viewer",
|
|
127
|
+
# Automation keywords
|
|
128
|
+
"keyword_reference_framework_label": "Framework:",
|
|
129
|
+
"keyword_reference_refresh_button": "Read Again",
|
|
130
|
+
"keyword_reference_search_placeholder": "Filter by name or description",
|
|
131
|
+
"keyword_reference_copy_button": "Copy as Action",
|
|
132
|
+
"keyword_reference_loading": "Reading the keywords of {framework}...",
|
|
133
|
+
"keyword_reference_ready": "{framework}: {count} keywords. In a .json script the editor offers "
|
|
134
|
+
"{capabilities}",
|
|
135
|
+
"keyword_reference_capability_completion": "completion",
|
|
136
|
+
"keyword_reference_capability_diagnostics": "diagnostics",
|
|
137
|
+
"keyword_reference_capability_hover": "hover",
|
|
138
|
+
"keyword_reference_capability_definition": "go to definition",
|
|
139
|
+
"keyword_reference_defined_in": "Defined in {file}, line {line}",
|
|
140
|
+
"keyword_reference_no_interpreter": "No Python interpreter was found to read the keywords with",
|
|
141
|
+
# Language service for action scripts (diagnostics and hover, shown by the editor)
|
|
142
|
+
"language_service_json_syntax": "This is not valid JSON",
|
|
143
|
+
"language_service_unknown_keyword": "{name} is not a keyword of {framework}",
|
|
144
|
+
"language_service_unknown_keyword_suggestion":
|
|
145
|
+
"{name} is not a keyword of {framework}. Did you mean {suggestion}?",
|
|
146
|
+
"language_service_unknown_parameter": "{keyword} has no parameter named {name}",
|
|
147
|
+
"language_service_unknown_parameter_suggestion":
|
|
148
|
+
"{keyword} has no parameter named {name}. Did you mean {suggestion}?",
|
|
149
|
+
"language_service_missing_parameter": "{keyword} needs {names}",
|
|
150
|
+
"language_service_too_many_values":
|
|
151
|
+
"{keyword} takes at most {most} values in a list, and this one gives {count}",
|
|
152
|
+
"language_service_too_few_values":
|
|
153
|
+
"{keyword} needs at least {least} values in a list, and this one gives {count}",
|
|
154
|
+
"language_service_needs_names":
|
|
155
|
+
"{keyword} takes {names} by name only: give an object of named values, not a list",
|
|
156
|
+
"language_service_action_not_list":
|
|
157
|
+
"An action is a list: [\"keyword\"] or [\"keyword\", arguments]",
|
|
158
|
+
"language_service_action_no_keyword": "An action starts with its keyword, in quotes",
|
|
159
|
+
"language_service_action_too_long": "An action holds a keyword and at most one set of arguments",
|
|
160
|
+
"language_service_arguments_shape":
|
|
161
|
+
"Arguments are an object of named values, or a list of values",
|
|
162
|
+
"language_service_actions_not_list": "{key} holds a list of actions",
|
|
163
|
+
"language_service_parameter_required": "required",
|
|
164
|
+
"language_service_parameter_optional": "optional",
|
|
165
|
+
}
|