hap-cli 0.8.30__tar.gz → 0.8.31__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.
- {hap_cli-0.8.30 → hap_cli-0.8.31}/PKG-INFO +2 -1
- {hap_cli-0.8.30/hap_cli → hap_cli-0.8.31}/README.md +1 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31/hap_cli}/README.md +1 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/README_CN.md +1 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/__init__.py +1 -1
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/calendar_cmd.py +36 -1
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/calendar_mod.py +65 -1
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/global_meta.py +15 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/record.py +8 -3
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/locale/messages.json +17 -1
- hap_cli-0.8.31/hap_cli/tests/test_calendar_discussion_cli.py +89 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_core.py +75 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli.egg-info/PKG-INFO +2 -1
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli.egg-info/SOURCES.txt +1 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/MANIFEST.in +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/app_live_tests/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/app_live_tests/__main__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/app_live_tests/config.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/app_live_tests/harness.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/app_live_tests/smoke.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/app_live_tests/state.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/__main__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/app_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/app_creator_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/app_editor_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/attachment_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/auth_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/chart_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/chat_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/chatbot_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/config_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/contact_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/department_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/group_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/guide_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/icon_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/instance_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/node_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/optionset_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/page_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/post_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/record_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/region_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/role_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/update_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/upload_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/v3_registry.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/workflow_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/commands/worksheet_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/context.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/action_spec_adapter.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/_hapmeta/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/_hapmeta/control_type_codes.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/_hapmeta/worksheet_templates.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/charts.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/cleanup.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/compiler.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/config.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/design/design.schema.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/errors.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/examples/minimal.design.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/executor.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/fields.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/hap.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/merge.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/recording/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/recording/console.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/recording/jsonl.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/recording/mirror.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/recording/report.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/schema.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/INSTRUCTIONS.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/executor.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/resources/attachments.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/resources/sample.docx +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/resources/sample.pdf +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/resources/sample_images.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/seed/template.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/selftest.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/smoke.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/steps.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/store.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/validate.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/app_creator/workflow_dsl.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/attachment.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/auth.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/chart.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/chat.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/chatbot.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/cli_access.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/contact.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/control_type_codes.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/department.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/apply.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/componentlower.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/editspec/component.schema.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/editspec/custom-action.schema.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/editspec/envelope.schema.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/editspec/field.schema.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/editspec.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/errors.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/fieldlower.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/jsonschema_mini.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/models.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/ops.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/planner.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/editor/reader.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/field_normalizer.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/field_spec_adapter.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/filter_translator.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/flow_node.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/group.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/guide.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/icon_index.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/instance.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/logger.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/optionset.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/page.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/post.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/response_crypto.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/role.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/role_perm_builder.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/session.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/token_crypto.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/update.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/upload.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/v3/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/v3/dispatcher.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/v3/render.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/v3/schema.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/view_spec_adapter.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/workflow.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/workflow_node_dsl.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/worksheet.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/core/worksheet_templates.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/approval.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/chart.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/messages.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/overview.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/post.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/record.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/setup.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/en/skills.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/index.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/approval.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/chart.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/messages.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/overview.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/post.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/record.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/setup.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/guide/zh-Hans/skills.md +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/hap_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/i18n.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/locale/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/locale/messages.schema.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/conftest.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_app_creator.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_app_editor.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_app_export_usage.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_approval_submit_fill_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_attachment_share.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_auth_prerelease.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_bug_036430.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_bug_036750.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_chart.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_chat_attachment_send.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_chat_recall_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_cli_access.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_config_cmd.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_content_language.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_control_lookup_guard.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_destructive_confirm_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_full_e2e.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_global_meta.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_guide.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_i18n.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_instance_history_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_approval.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_approval_actions.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_calendar.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_destructive.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_misc.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_post.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_social.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_v3.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_workflow.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_member_relation_array_wrap.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_multi_profile.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_no_workflow_unsupported.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_org_approval_v3_semantic_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_org_id_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_org_id_docs.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_parameter_conventions.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_post_scope_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_record_batch_v3_semantic_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_record_field_alias.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_record_v3_semantic_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_record_write_fixes.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_select_add_option.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_select_rejects_relation_value.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_semantic_types_registry.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_update.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_update_mode.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_upload_allow_down.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_upload_host_resolution.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_v3_dispatcher.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_v3_session.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_workflow_envelope_errors.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_workflow_list_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_workflow_read_write_keys.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_workflow_v3_semantic_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_worksheet_create_section.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_worksheet_crud_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_worksheet_switch.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/tests/test_worksheet_v3_semantic_cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/utils/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/utils/formatting.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/utils/options.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli/utils/parameter_mapping.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli.egg-info/dependency_links.txt +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli.egg-info/entry_points.txt +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli.egg-info/requires.txt +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/hap_cli.egg-info/top_level.txt +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/__main__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/_wftest.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/charts.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/cleanup.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/compiler.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/config.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/errors.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/executor.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/fields.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/hap.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/recording/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/recording/console.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/recording/jsonl.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/recording/mirror.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/recording/report.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/schema.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/seed/__init__.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/seed/cli.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/seed/executor.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/seed/template.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/selftest.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/smoke.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/step.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/steps.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/store.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/live_tests/workflow_dsl.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/setup.cfg +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/setup.py +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/INDEX.json +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/create_optionset.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/create_role.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/delete_optionset.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/delete_record.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/delete_role.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_app_info.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_record_details.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_record_list.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_record_logs.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_record_relations.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_regions.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_role_details.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/get_role_list.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/knowledge_search.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
- {hap_cli-0.8.30 → hap_cli-0.8.31}/sources/v3-api-schema/update_optionset.yaml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hap-cli
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.31
|
|
4
4
|
Summary: CLI harness for Mingdao HAP - Enterprise no-code platform
|
|
5
5
|
Author: hap-cli
|
|
6
6
|
License: Apache-2.0
|
|
@@ -264,6 +264,7 @@ discover every subcommand.
|
|
|
264
264
|
| `calendar list / get / create / update / delete` | Event lifecycle |
|
|
265
265
|
| `calendar categories` | Built-in categories |
|
|
266
266
|
| `calendar add-member / remove-member` | Membership |
|
|
267
|
+
| `calendar add-discussion` | Comment on an event (attachments supported) |
|
|
267
268
|
|
|
268
269
|
### chat — chat & messaging
|
|
269
270
|
|
|
@@ -235,6 +235,7 @@ discover every subcommand.
|
|
|
235
235
|
| `calendar list / get / create / update / delete` | Event lifecycle |
|
|
236
236
|
| `calendar categories` | Built-in categories |
|
|
237
237
|
| `calendar add-member / remove-member` | Membership |
|
|
238
|
+
| `calendar add-discussion` | Comment on an event (attachments supported) |
|
|
238
239
|
|
|
239
240
|
### chat — chat & messaging
|
|
240
241
|
|
|
@@ -235,6 +235,7 @@ discover every subcommand.
|
|
|
235
235
|
| `calendar list / get / create / update / delete` | Event lifecycle |
|
|
236
236
|
| `calendar categories` | Built-in categories |
|
|
237
237
|
| `calendar add-member / remove-member` | Membership |
|
|
238
|
+
| `calendar add-discussion` | Comment on an event (attachments supported) |
|
|
238
239
|
|
|
239
240
|
### chat — chat & messaging
|
|
240
241
|
|
|
@@ -218,6 +218,7 @@ hap --json worksheet record list WORKSHEET_ID
|
|
|
218
218
|
| `calendar list / get / create / update / delete` | 日程生命周期 |
|
|
219
219
|
| `calendar categories` | 内置分类 |
|
|
220
220
|
| `calendar add-member / remove-member` | 成员管理 |
|
|
221
|
+
| `calendar add-discussion` | 在日程下发表评论(可带附件) |
|
|
221
222
|
|
|
222
223
|
### chat — 聊天与消息
|
|
223
224
|
|
|
@@ -543,4 +543,39 @@ def calendar_categories(ctx):
|
|
|
543
543
|
summary = _simplify_categories_result(raw)
|
|
544
544
|
ctx.output(summary, _render_categories)
|
|
545
545
|
except Exception as e:
|
|
546
|
-
ctx.handle_error(e)
|
|
546
|
+
ctx.handle_error(e)
|
|
547
|
+
|
|
548
|
+
@calendar.command("add-discussion")
|
|
549
|
+
@click.argument("calendar_id")
|
|
550
|
+
@click.option("--message", "-m", required=True, help="Comment text")
|
|
551
|
+
@click.option("--reply-id", default="", help="ID of the comment being replied to")
|
|
552
|
+
@click.option("--file", "-f", "files", multiple=True,
|
|
553
|
+
help="Attach a file to the comment (repeatable). Accepts a local "
|
|
554
|
+
"path or an http(s) URL.")
|
|
555
|
+
@pass_context
|
|
556
|
+
def calendar_add_discussion(ctx, calendar_id, message, reply_id, files):
|
|
557
|
+
"""Post a comment on a calendar event.
|
|
558
|
+
|
|
559
|
+
Everyone invited to the event can see the comment. Attached files are
|
|
560
|
+
downloadable by every participant.
|
|
561
|
+
"""
|
|
562
|
+
try:
|
|
563
|
+
session = ctx.get_session()
|
|
564
|
+
attachments = None
|
|
565
|
+
if files:
|
|
566
|
+
from hap_cli.core import upload as up_mod
|
|
567
|
+
attachments = up_mod.upload_files(
|
|
568
|
+
session, up_mod.source_descriptors(list(files)))
|
|
569
|
+
raw = cal_mod.add_discussion(
|
|
570
|
+
session, calendar_id, message,
|
|
571
|
+
reply_id=reply_id, attachments=attachments,
|
|
572
|
+
)
|
|
573
|
+
data = raw.get("data") if isinstance(raw, dict) else None
|
|
574
|
+
summary = {
|
|
575
|
+
"success": True,
|
|
576
|
+
"discussion_id": (data or {}).get("discussionId", ""),
|
|
577
|
+
"calendar_id": calendar_id,
|
|
578
|
+
}
|
|
579
|
+
ctx.output(summary, lambda d: click.echo("Comment posted."))
|
|
580
|
+
except Exception as e:
|
|
581
|
+
ctx.handle_error(e)
|
|
@@ -13,9 +13,12 @@ Enum re-exports (`FREQUENCY_*`, `REMIND_TYPE_*`) mirror
|
|
|
13
13
|
`src/pages/calendar/modules/calendarDetail/constant.js`.
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
+
import json
|
|
16
17
|
from typing import Any, Optional
|
|
17
18
|
|
|
18
|
-
from hap_cli.core
|
|
19
|
+
from hap_cli.core import global_meta as gm
|
|
20
|
+
from hap_cli.core import record as rec_mod
|
|
21
|
+
from hap_cli.core.session import Session, SessionError
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
# ── Enums (pd-openweb constants) ─────────────────────────────────────────
|
|
@@ -327,3 +330,64 @@ def remove_member(
|
|
|
327
330
|
def get_categories(session: Session) -> dict[str, Any]:
|
|
328
331
|
"""Get all calendar categories (`Calendar.GetUserAllCalCategories`)."""
|
|
329
332
|
return session.api_call("Calendar", "GetUserAllCalCategories", {})
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# ── Discussions (comments on an event) ────────────────────────────────────
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def add_discussion(
|
|
339
|
+
session: Session,
|
|
340
|
+
calendar_id: str,
|
|
341
|
+
message: str,
|
|
342
|
+
reply_id: str = "",
|
|
343
|
+
attachments: Optional[list[dict[str, Any]]] = None,
|
|
344
|
+
) -> dict[str, Any]:
|
|
345
|
+
"""Post a comment on a calendar event (`Discussion.AddDiscussion`).
|
|
346
|
+
|
|
347
|
+
Traced from `src/pages/calendar/modules/calendarDetail/container/
|
|
348
|
+
CalendarCommenter.jsx`, which configures the shared commenter
|
|
349
|
+
(`src/components/comment/commenter.jsx`) with:
|
|
350
|
+
|
|
351
|
+
- `sourceType` = SOURCE_TYPE.CALENDAR (3, comment/config.js)
|
|
352
|
+
- `sourceId` = the bare calendar id (no composite form, unlike the
|
|
353
|
+
worksheet-row case's ``{worksheetId}|{rowId}``)
|
|
354
|
+
- `appId` = md.global.APPInfo.calendarAppID, and *no*
|
|
355
|
+
`fromAppId` — a calendar event has no owning app
|
|
356
|
+
|
|
357
|
+
Two props of CalendarCommenter deliberately do **not** reach this
|
|
358
|
+
payload. `remark` is only consumed when the comment is additionally
|
|
359
|
+
shared to a post (`postAjax.addPost`), and `AddDiscussionRequest`
|
|
360
|
+
(sources/main_api/schemas/…AddDiscussionRequest.json) has no such
|
|
361
|
+
field. `extendsId` is documented "扩展ID(工作表:appId|viewId)" and the
|
|
362
|
+
calendar commenter never sets it.
|
|
363
|
+
|
|
364
|
+
``attachments`` carries uploaded-file descriptors from
|
|
365
|
+
``hap_cli.core.upload``; the frontend sends them JSON-encoded, and
|
|
366
|
+
each descriptor's ``allowDown`` is what lets anyone but the uploader
|
|
367
|
+
download the file (see upload._download_permission).
|
|
368
|
+
"""
|
|
369
|
+
app_id = gm.calendar_app_id(session.get_global_meta())
|
|
370
|
+
if not app_id:
|
|
371
|
+
# Guessing an app id here would produce a discussion the calendar
|
|
372
|
+
# UI cannot render, which is worse than refusing.
|
|
373
|
+
raise SessionError(
|
|
374
|
+
"This server did not publish the calendar application, so the "
|
|
375
|
+
"comment cannot be posted. Check that you are signed in to the "
|
|
376
|
+
"right server, then try again."
|
|
377
|
+
)
|
|
378
|
+
data: dict[str, Any] = {
|
|
379
|
+
"sourceId": calendar_id,
|
|
380
|
+
"sourceType": rec_mod.DISCUSSION_SOURCE_CALENDAR,
|
|
381
|
+
"message": message,
|
|
382
|
+
"appId": app_id,
|
|
383
|
+
# commenter.jsx: `forReacordDiscussion && entityType === 2 ? 2 : 0`
|
|
384
|
+
# — a calendar comment is always the plain kind.
|
|
385
|
+
"entityType": 0,
|
|
386
|
+
}
|
|
387
|
+
if reply_id:
|
|
388
|
+
data["replyId"] = reply_id
|
|
389
|
+
if attachments:
|
|
390
|
+
data["attachments"] = json.dumps(attachments, ensure_ascii=False)
|
|
391
|
+
result = session.api_call("Discussion", "AddDiscussion", data)
|
|
392
|
+
rec_mod.ensure_discussion_ok(result, "add comment")
|
|
393
|
+
return result
|
|
@@ -156,6 +156,21 @@ def worksheet_row_app_id(meta: Any) -> str:
|
|
|
156
156
|
return str(_app_info(meta).get("worksheetRowAppID") or "")
|
|
157
157
|
|
|
158
158
|
|
|
159
|
+
def calendar_app_id(meta: Any) -> str:
|
|
160
|
+
"""Return ``md.global.APPInfo.calendarAppID``.
|
|
161
|
+
|
|
162
|
+
The internal "application" id HAP uses for **calendar-event**
|
|
163
|
+
discussions (``sourceType`` 3 / ``Commenter.TYPES.CALENDAR`` in
|
|
164
|
+
pd-openweb ``src/components/comment/config.js``). ``AddDiscussion``
|
|
165
|
+
must carry it as ``appId`` — see
|
|
166
|
+
``src/pages/calendar/modules/calendarDetail/container/CalendarCommenter.jsx``.
|
|
167
|
+
Unlike the worksheet-row case there is no separate ``fromAppId``:
|
|
168
|
+
a calendar event has no owning app. Returns empty string when the
|
|
169
|
+
deployment does not expose it.
|
|
170
|
+
"""
|
|
171
|
+
return str(_app_info(meta).get("calendarAppID") or "")
|
|
172
|
+
|
|
173
|
+
|
|
159
174
|
def worksheet_app_id(meta: Any) -> str:
|
|
160
175
|
"""Return ``md.global.APPInfo.worksheetAppID`` (whole-worksheet
|
|
161
176
|
discussions, ``sourceType`` 7). Empty string when absent."""
|
|
@@ -12,10 +12,15 @@ from hap_cli.core import global_meta as gm
|
|
|
12
12
|
logger = logging.getLogger("hap_cli.record")
|
|
13
13
|
|
|
14
14
|
# Discussion source types — pd-openweb src/components/comment/config.js
|
|
15
|
+
# CALENDAR = 3 calendar-event discussion
|
|
15
16
|
# WORKSHEET = 7 whole-worksheet discussion
|
|
16
17
|
# WORKSHEETROW = 8 single record/row discussion
|
|
17
18
|
# Record-scoped discussions (add/get/delete on a row) are always type 8,
|
|
18
19
|
# and their sourceId is "{worksheetId}|{rowId}" — NOT the bare rowId.
|
|
20
|
+
# The whole enum lives here because this module owns the Discussion
|
|
21
|
+
# endpoint primitives; other modules (calendar) import from it rather
|
|
22
|
+
# than redeclaring their own copy.
|
|
23
|
+
DISCUSSION_SOURCE_CALENDAR = 3
|
|
19
24
|
DISCUSSION_SOURCE_WORKSHEET = 7
|
|
20
25
|
DISCUSSION_SOURCE_WORKSHEET_ROW = 8
|
|
21
26
|
|
|
@@ -1050,7 +1055,7 @@ def _discussion_source_id(worksheet_id: str, row_id: str) -> str:
|
|
|
1050
1055
|
return f"{worksheet_id}|{row_id}"
|
|
1051
1056
|
|
|
1052
1057
|
|
|
1053
|
-
def
|
|
1058
|
+
def ensure_discussion_ok(result: Any, action: str) -> None:
|
|
1054
1059
|
"""Raise if the Discussion endpoint reported failure.
|
|
1055
1060
|
|
|
1056
1061
|
Discussion endpoints return ``{code: 1, data: ...}`` on success and a
|
|
@@ -1138,7 +1143,7 @@ def add_discussion(
|
|
|
1138
1143
|
if attachments:
|
|
1139
1144
|
data["attachments"] = json.dumps(attachments, ensure_ascii=False)
|
|
1140
1145
|
result = session.api_call("Discussion", "AddDiscussion", data)
|
|
1141
|
-
|
|
1146
|
+
ensure_discussion_ok(result, "add discussion")
|
|
1142
1147
|
return result
|
|
1143
1148
|
|
|
1144
1149
|
|
|
@@ -1157,7 +1162,7 @@ def remove_discussion(
|
|
|
1157
1162
|
"Discussion", "RemoveDiscussion",
|
|
1158
1163
|
{"discussionId": discussion_id, "sourceType": source_type},
|
|
1159
1164
|
)
|
|
1160
|
-
|
|
1165
|
+
ensure_discussion_ok(result, "delete discussion")
|
|
1161
1166
|
return result
|
|
1162
1167
|
|
|
1163
1168
|
|
|
@@ -2217,6 +2217,22 @@
|
|
|
2217
2217
|
"en": "Calendar and schedule management.",
|
|
2218
2218
|
"zh-Hans": "日程与日历管理"
|
|
2219
2219
|
},
|
|
2220
|
+
"calendar add-discussion": {
|
|
2221
|
+
"en": "Post a comment on a calendar event.\n\nEveryone invited to the event can see the comment. Attached files are\ndownloadable by every participant.",
|
|
2222
|
+
"zh-Hans": "在日程下发表评论。\n\n日程的所有参与者都能看到这条评论;随评论上传的附件,参与者均可下载。"
|
|
2223
|
+
},
|
|
2224
|
+
"calendar add-discussion --file": {
|
|
2225
|
+
"en": "Attach a file to the comment (repeatable). Accepts a local path or an http(s) URL.",
|
|
2226
|
+
"zh-Hans": "为评论添加附件(可重复指定)。可传本地路径或 http(s) 链接。"
|
|
2227
|
+
},
|
|
2228
|
+
"calendar add-discussion --message": {
|
|
2229
|
+
"en": "Comment text",
|
|
2230
|
+
"zh-Hans": "评论内容"
|
|
2231
|
+
},
|
|
2232
|
+
"calendar add-discussion --reply-id": {
|
|
2233
|
+
"en": "ID of the comment being replied to",
|
|
2234
|
+
"zh-Hans": "被回复的评论 ID"
|
|
2235
|
+
},
|
|
2220
2236
|
"calendar add-member": {
|
|
2221
2237
|
"en": "Add members to a calendar event.",
|
|
2222
2238
|
"zh-Hans": "向日程事件添加成员"
|
|
@@ -4890,4 +4906,4 @@
|
|
|
4890
4906
|
"zh-Hans": "应用到现有视图的高层视图 JSON(格式与 'view create --view-spec' 相同)。规格中表达的内容全部更新;其他设置保持不变。字段引用可为名称、别名或 controlId。提供时忽略其他选项"
|
|
4891
4907
|
}
|
|
4892
4908
|
}
|
|
4893
|
-
}
|
|
4909
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""`hap calendar add-discussion` — commenting on a calendar event.
|
|
2
|
+
|
|
3
|
+
Until this command existed, attaching a file to a calendar event's
|
|
4
|
+
comment thread had no CLI path at all: the only `Discussion/AddDiscussion`
|
|
5
|
+
caller in the codebase was the worksheet-record one, pinned to
|
|
6
|
+
`sourceType` 8. Anyone who needed it had to assemble the request by hand
|
|
7
|
+
against the raw session — which is how a calendar comment attachment
|
|
8
|
+
first shipped without its download permission (see
|
|
9
|
+
test_upload_allow_down.py).
|
|
10
|
+
|
|
11
|
+
Payload traced from pd-openweb
|
|
12
|
+
`src/pages/calendar/modules/calendarDetail/container/CalendarCommenter.jsx`
|
|
13
|
+
→ `src/components/comment/commenter.jsx`, cross-checked against
|
|
14
|
+
`sources/main_api/schemas/MD.Web.Ajax.Request.Discussion.AddDiscussionRequest.json`.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from unittest.mock import patch
|
|
18
|
+
|
|
19
|
+
from click.testing import CliRunner
|
|
20
|
+
|
|
21
|
+
from hap_cli.hap_cli import cli
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestAddDiscussionCli:
|
|
25
|
+
|
|
26
|
+
def test_message_reaches_the_core_call(self):
|
|
27
|
+
runner = CliRunner()
|
|
28
|
+
with patch("hap_cli.context.Context.get_session"), \
|
|
29
|
+
patch("hap_cli.core.calendar_mod.add_discussion",
|
|
30
|
+
return_value={"code": 1, "data": {"discussionId": "d1"}}) as m:
|
|
31
|
+
res = runner.invoke(cli, ["calendar", "add-discussion", "cal1",
|
|
32
|
+
"-m", "会前看下资料"])
|
|
33
|
+
assert res.exit_code == 0, res.output
|
|
34
|
+
assert m.call_args[0][1:] == ("cal1", "会前看下资料")
|
|
35
|
+
assert m.call_args[1]["reply_id"] == ""
|
|
36
|
+
assert m.call_args[1]["attachments"] is None
|
|
37
|
+
|
|
38
|
+
def test_reply_id_is_forwarded(self):
|
|
39
|
+
runner = CliRunner()
|
|
40
|
+
with patch("hap_cli.context.Context.get_session"), \
|
|
41
|
+
patch("hap_cli.core.calendar_mod.add_discussion",
|
|
42
|
+
return_value={"code": 1, "data": {}}) as m:
|
|
43
|
+
res = runner.invoke(cli, ["calendar", "add-discussion", "cal1",
|
|
44
|
+
"-m", "收到", "--reply-id", "d0"])
|
|
45
|
+
assert res.exit_code == 0, res.output
|
|
46
|
+
assert m.call_args[1]["reply_id"] == "d0"
|
|
47
|
+
|
|
48
|
+
def test_files_are_uploaded_and_attached(self, tmp_path):
|
|
49
|
+
runner = CliRunner()
|
|
50
|
+
f = tmp_path / "proto.zip"
|
|
51
|
+
f.write_bytes(b"zip")
|
|
52
|
+
descriptor = {"fileID": "o_1", "fileExt": ".zip", "allowDown": True}
|
|
53
|
+
with patch("hap_cli.context.Context.get_session"), \
|
|
54
|
+
patch("hap_cli.core.upload.upload_files",
|
|
55
|
+
return_value=[descriptor]) as up, \
|
|
56
|
+
patch("hap_cli.core.calendar_mod.add_discussion",
|
|
57
|
+
return_value={"code": 1, "data": {}}) as m:
|
|
58
|
+
res = runner.invoke(cli, ["calendar", "add-discussion", "cal1",
|
|
59
|
+
"-m", "原型包", "-f", str(f)])
|
|
60
|
+
assert res.exit_code == 0, res.output
|
|
61
|
+
assert up.call_args[0][1] == [{"path": str(f)}]
|
|
62
|
+
assert m.call_args[1]["attachments"] == [descriptor]
|
|
63
|
+
|
|
64
|
+
def test_an_http_source_is_fetched_rather_than_opened_as_a_path(self):
|
|
65
|
+
runner = CliRunner()
|
|
66
|
+
with patch("hap_cli.context.Context.get_session"), \
|
|
67
|
+
patch("hap_cli.core.upload.upload_files",
|
|
68
|
+
return_value=[{"fileID": "o_2"}]) as up, \
|
|
69
|
+
patch("hap_cli.core.calendar_mod.add_discussion",
|
|
70
|
+
return_value={"code": 1, "data": {}}):
|
|
71
|
+
res = runner.invoke(cli, ["calendar", "add-discussion", "cal1",
|
|
72
|
+
"-m", "链接", "-f",
|
|
73
|
+
"https://example.com/a.pdf"])
|
|
74
|
+
assert res.exit_code == 0, res.output
|
|
75
|
+
assert up.call_args[0][1] == [{"url": "https://example.com/a.pdf"}]
|
|
76
|
+
|
|
77
|
+
def test_message_is_required(self):
|
|
78
|
+
runner = CliRunner()
|
|
79
|
+
with patch("hap_cli.context.Context.get_session"):
|
|
80
|
+
res = runner.invoke(cli, ["calendar", "add-discussion", "cal1"])
|
|
81
|
+
assert res.exit_code != 0
|
|
82
|
+
|
|
83
|
+
def test_help_is_end_user_copy(self):
|
|
84
|
+
runner = CliRunner()
|
|
85
|
+
res = runner.invoke(cli, ["calendar", "add-discussion", "--help"])
|
|
86
|
+
assert res.exit_code == 0
|
|
87
|
+
for leak in ("AddDiscussion", "Discussion/", "sourceType", "pd-openweb",
|
|
88
|
+
"calendarAppID", "commenter", "endpoint"):
|
|
89
|
+
assert leak not in res.output
|
|
@@ -4022,6 +4022,81 @@ class TestCalendar:
|
|
|
4022
4022
|
assert body["isAllCalendar"] is True
|
|
4023
4023
|
|
|
4024
4024
|
|
|
4025
|
+
class TestCalendarDiscussions:
|
|
4026
|
+
"""Comments on a calendar event.
|
|
4027
|
+
|
|
4028
|
+
Traced from pd-openweb
|
|
4029
|
+
`src/pages/calendar/modules/calendarDetail/container/CalendarCommenter.jsx`,
|
|
4030
|
+
which feeds the shared `src/components/comment/commenter.jsx`:
|
|
4031
|
+
`sourceType` = SOURCE_TYPE.CALENDAR (3, config.js) and `appId` =
|
|
4032
|
+
`md.global.APPInfo.calendarAppID`. The commenter's `remark` prop is
|
|
4033
|
+
*not* part of the AddDiscussion payload — it is only used when the
|
|
4034
|
+
comment is additionally shared to a post (`postAjax.addPost`), and
|
|
4035
|
+
`AddDiscussionRequest` has no such field. `extendsId` is documented
|
|
4036
|
+
"扩展ID(工作表:appId|viewId)" and the calendar commenter never sets it.
|
|
4037
|
+
"""
|
|
4038
|
+
|
|
4039
|
+
_META = {"md.global": {"APPInfo": {"calendarAppID": "cal-app-id"}}}
|
|
4040
|
+
|
|
4041
|
+
def _session(self):
|
|
4042
|
+
session = MagicMock()
|
|
4043
|
+
session.get_global_meta.return_value = self._META
|
|
4044
|
+
session.api_call.return_value = {"code": 1, "data": {"discussionId": "d1"}}
|
|
4045
|
+
return session
|
|
4046
|
+
|
|
4047
|
+
def test_payload_shape(self):
|
|
4048
|
+
from hap_cli.core import calendar_mod
|
|
4049
|
+
session = self._session()
|
|
4050
|
+
calendar_mod.add_discussion(session, "cal1", "看下这个附件")
|
|
4051
|
+
controller, action, payload = session.api_call.call_args[0][:3]
|
|
4052
|
+
assert (controller, action) == ("Discussion", "AddDiscussion")
|
|
4053
|
+
assert payload["sourceId"] == "cal1" # the bare calendar id
|
|
4054
|
+
assert payload["sourceType"] == 3 # SOURCE_TYPE.CALENDAR
|
|
4055
|
+
assert payload["appId"] == "cal-app-id" # APPInfo.calendarAppID
|
|
4056
|
+
assert payload["message"] == "看下这个附件"
|
|
4057
|
+
assert payload["entityType"] == 0
|
|
4058
|
+
# Worksheet-only / post-only fields must not leak in.
|
|
4059
|
+
assert "extendsId" not in payload
|
|
4060
|
+
assert "remark" not in payload
|
|
4061
|
+
assert "fromAppId" not in payload
|
|
4062
|
+
|
|
4063
|
+
def test_reply_id_is_sent_only_when_given(self):
|
|
4064
|
+
from hap_cli.core import calendar_mod
|
|
4065
|
+
session = self._session()
|
|
4066
|
+
calendar_mod.add_discussion(session, "cal1", "收到")
|
|
4067
|
+
assert "replyId" not in session.api_call.call_args[0][2]
|
|
4068
|
+
calendar_mod.add_discussion(session, "cal1", "收到", reply_id="d0")
|
|
4069
|
+
assert session.api_call.call_args[0][2]["replyId"] == "d0"
|
|
4070
|
+
|
|
4071
|
+
def test_attachments_are_json_encoded(self):
|
|
4072
|
+
from hap_cli.core import calendar_mod
|
|
4073
|
+
session = self._session()
|
|
4074
|
+
calendar_mod.add_discussion(
|
|
4075
|
+
session, "cal1", "原型包",
|
|
4076
|
+
attachments=[{"fileID": "o_1", "fileExt": ".zip", "allowDown": True}],
|
|
4077
|
+
)
|
|
4078
|
+
payload = session.api_call.call_args[0][2]
|
|
4079
|
+
sent = json.loads(payload["attachments"])
|
|
4080
|
+
assert sent[0]["fileID"] == "o_1"
|
|
4081
|
+
# The download permission must survive the hop — see
|
|
4082
|
+
# test_upload_allow_down.py for why it exists at all.
|
|
4083
|
+
assert sent[0]["allowDown"] is True
|
|
4084
|
+
|
|
4085
|
+
def test_failure_code_raises_instead_of_reporting_success(self):
|
|
4086
|
+
from hap_cli.core import calendar_mod
|
|
4087
|
+
session = self._session()
|
|
4088
|
+
session.api_call.return_value = {"code": 7} # 没有权限操作
|
|
4089
|
+
with pytest.raises(APIError):
|
|
4090
|
+
calendar_mod.add_discussion(session, "cal1", "hi")
|
|
4091
|
+
|
|
4092
|
+
def test_missing_calendar_app_id_is_an_error_not_a_guess(self):
|
|
4093
|
+
from hap_cli.core import calendar_mod
|
|
4094
|
+
session = self._session()
|
|
4095
|
+
session.get_global_meta.return_value = {"md.global": {"APPInfo": {}}}
|
|
4096
|
+
with pytest.raises(SessionError):
|
|
4097
|
+
calendar_mod.add_discussion(session, "cal1", "hi")
|
|
4098
|
+
|
|
4099
|
+
|
|
4025
4100
|
# ── Chat Tests ────────────────────────────────────────────────────────────
|
|
4026
4101
|
|
|
4027
4102
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hap-cli
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.31
|
|
4
4
|
Summary: CLI harness for Mingdao HAP - Enterprise no-code platform
|
|
5
5
|
Author: hap-cli
|
|
6
6
|
License: Apache-2.0
|
|
@@ -264,6 +264,7 @@ discover every subcommand.
|
|
|
264
264
|
| `calendar list / get / create / update / delete` | Event lifecycle |
|
|
265
265
|
| `calendar categories` | Built-in categories |
|
|
266
266
|
| `calendar add-member / remove-member` | Membership |
|
|
267
|
+
| `calendar add-discussion` | Comment on an event (attachments supported) |
|
|
267
268
|
|
|
268
269
|
### chat — chat & messaging
|
|
269
270
|
|
|
@@ -175,6 +175,7 @@ hap_cli/tests/test_attachment_share.py
|
|
|
175
175
|
hap_cli/tests/test_auth_prerelease.py
|
|
176
176
|
hap_cli/tests/test_bug_036430.py
|
|
177
177
|
hap_cli/tests/test_bug_036750.py
|
|
178
|
+
hap_cli/tests/test_calendar_discussion_cli.py
|
|
178
179
|
hap_cli/tests/test_chart.py
|
|
179
180
|
hap_cli/tests/test_chat_attachment_send.py
|
|
180
181
|
hap_cli/tests/test_chat_recall_cli.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|