python-hwpx-automation 6.2.1__tar.gz → 6.4.2__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.
- {python_hwpx_automation-6.2.1/src/python_hwpx_automation.egg-info → python_hwpx_automation-6.4.2}/PKG-INFO +7 -6
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/README.md +5 -4
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/pyproject.toml +2 -2
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/content.py +67 -10
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/content_edit.py +65 -8
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/hwpx_ops.py +29 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/identity.json +9 -9
- python_hwpx_automation-6.4.2/src/hwpx_automation/office/charting/__init__.py +162 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/content_layout.py +77 -2
- python_hwpx_automation-6.4.2/src/hwpx_automation/public-modules.json +207 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/server.py +1 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/tool_bindings.py +1 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/tool_contract.py +11 -11
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2/src/python_hwpx_automation.egg-info}/PKG-INFO +7 -6
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/python_hwpx_automation.egg-info/SOURCES.txt +1 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/python_hwpx_automation.egg-info/requires.txt +1 -1
- python_hwpx_automation-6.2.1/src/hwpx_automation/public-modules.json +0 -206
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/LICENSE +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/MANIFEST.in +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/NOTICE +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/setup.cfg +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/__init__.pyi +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/__main__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/agent_document.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/api.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/blind_eval.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/capabilities.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/compat.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/configuration.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/context.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/diff.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/document.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/formatting.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/handles.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/locations.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/locator.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/plan.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/resources.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/search.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/transactions.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/txn.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/document_state.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/errors.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/execution_lock.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/fastmcp_adapter.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/form_fill.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/form_output_models.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/_shared.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/agent_document.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/authoring.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/form_fill.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/layout_style.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/quality_render.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/read_export.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/specialized.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/tracked_changes.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/handlers/workflow.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/hwp_converter.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/hwp_support.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/identity.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ingest_adapters.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/markdown_plan.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/mcp_cli.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/metadata/tools_meta.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/mixed_form.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/mutation_models.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/network_policy.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/_batch_verification.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/bundle.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/catalog.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/dump.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/mapping.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/model.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/native.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/blueprint/replay.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/catalog.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/cli.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/commands.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/document.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/form_plan.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/model.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/path.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/query.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/agent/story.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/advanced_generators.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/builder/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/builder/core.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/builder/report.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/_support.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/composer.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/harvest.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/plan.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profile.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/body.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/heading.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/info_table.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/title.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/profile.json +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/template.hwpx +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/body.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/heading.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/title.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/profile.json +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/template.hwpx +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/body.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/heading.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/info_table.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/title.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/profile.json +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/template.hwpx +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/body.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/heading.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/info_table.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/title.xml +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/report/profile.json +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/profiles/report/template.hwpx +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/design/validator.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/presets/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/presets/proposal.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/report_parser.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/style_profile.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/authoring/template_analyzer.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/compliance/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/compliance/official_lint.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/compliance/pii.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/document_ops/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/document_ops/comparison.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/document_ops/mail_merge.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/document_ops/redline.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/evalplan/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/evalplan/runtime.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/exam/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/exam/compose.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/exam/ir.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/exam/measure.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/exam/parser.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/exam/profile.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/classification.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fill_residue.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/apply.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/engine.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/measure.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/policy.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/report.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/seal.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/fit/wordbox.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/guidance.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/quality.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/split_run.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/form_fill/template_formfit.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/house_style/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/house_style/composition.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/house_style/data/bank.json +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/house_style/data/genres.json +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/quality/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/quality/page_guard.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/_hancom_open_rate.ps1 +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/_refresh_hwpx_mac.applescript +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/_render_hwpx.ps1 +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/_render_hwpx_mac.applescript +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/block_splits.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/detectors.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/diff.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/fixture_corpus.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/oracle.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/page_qa.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/qa_contracts.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/qa_metrics.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/rendering/worker.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/utilities/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/office/utilities/table_compute.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/_border_fill.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/composition.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/context.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/form_fields.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/media.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/memo_style.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/package_validation.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/planning.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/preview_export.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/read_query.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/save_policy.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/tables.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/ops_services/transactions.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/preview_output_models.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/py.typed +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/quality.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/quality_generation.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/runtime.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/runtime_services.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/storage.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/upstream.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/utils/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/utils/helpers.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/visual_qa.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/__init__.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/adapters.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/dispatcher.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/models.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/policy.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/render_contracts.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/render_metrics.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/render_queue.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/render_security.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/render_transport.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/rendering.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/service.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/state_machine.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workflow/store.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/workspace.py +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/python_hwpx_automation.egg-info/dependency_links.txt +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/python_hwpx_automation.egg-info/entry_points.txt +0 -0
- {python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/python_hwpx_automation.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-hwpx-automation
|
|
3
|
-
Version: 6.2
|
|
3
|
+
Version: 6.4.2
|
|
4
4
|
Summary: Task-oriented HWPX document automation for Python, with an optional MCP adapter.
|
|
5
5
|
Author: Kohkyuhyun
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -20,7 +20,7 @@ Requires-Python: >=3.10
|
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
License-File: NOTICE
|
|
23
|
-
Requires-Dist: python-hwpx<6,>=5.
|
|
23
|
+
Requires-Dist: python-hwpx<6,>=5.4.0
|
|
24
24
|
Requires-Dist: pydantic<3,>=2.11
|
|
25
25
|
Requires-Dist: cryptography>=42.0
|
|
26
26
|
Requires-Dist: anyio>=4.0
|
|
@@ -74,10 +74,11 @@ Dynamic: license-file
|
|
|
74
74
|
|
|
75
75
|
<!-- release-state: release-approved -->
|
|
76
76
|
> [!NOTE]
|
|
77
|
-
> 이 저장소의 main은 아직 공개되지 않은 6.2
|
|
78
|
-
>
|
|
79
|
-
>
|
|
80
|
-
>
|
|
77
|
+
> 이 저장소의 main은 아직 공개되지 않은 6.4.2 후보 — release-approved 상태(표 테두리·음영
|
|
78
|
+
> `format_table` 확장, 수리된 core 5.4.0 기본값, 계약 `dbdbdfaac26148b7`,
|
|
79
|
+
> 130 도구)입니다. 현재 공개 트레인은
|
|
80
|
+
> `python-hwpx 5.3.0 → python-hwpx-automation 6.3.1 → hwpx-plugin 1.3.0`
|
|
81
|
+
> (계약 `236f8ea855c875fe`, 2026-07-31 released)입니다. 공개 트레인은
|
|
81
82
|
> core·automation PyPI와 plugin GitHub
|
|
82
83
|
> Release·marketplace·실제 marketplace 설치까지 확인한 뒤 승격했으며, 기존
|
|
83
84
|
> 5.x 설치는 별도 발행된 `hwpx-mcp-server 5.1.1`이 보호합니다. 절차와 상태
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
<!-- release-state: release-approved -->
|
|
16
16
|
> [!NOTE]
|
|
17
|
-
> 이 저장소의 main은 아직 공개되지 않은 6.2
|
|
18
|
-
>
|
|
19
|
-
>
|
|
20
|
-
>
|
|
17
|
+
> 이 저장소의 main은 아직 공개되지 않은 6.4.2 후보 — release-approved 상태(표 테두리·음영
|
|
18
|
+
> `format_table` 확장, 수리된 core 5.4.0 기본값, 계약 `dbdbdfaac26148b7`,
|
|
19
|
+
> 130 도구)입니다. 현재 공개 트레인은
|
|
20
|
+
> `python-hwpx 5.3.0 → python-hwpx-automation 6.3.1 → hwpx-plugin 1.3.0`
|
|
21
|
+
> (계약 `236f8ea855c875fe`, 2026-07-31 released)입니다. 공개 트레인은
|
|
21
22
|
> core·automation PyPI와 plugin GitHub
|
|
22
23
|
> Release·marketplace·실제 marketplace 설치까지 확인한 뒤 승격했으며, 기존
|
|
23
24
|
> 5.x 설치는 별도 발행된 `hwpx-mcp-server 5.1.1`이 보호합니다. 절차와 상태
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-hwpx-automation"
|
|
7
|
-
version = "6.2
|
|
7
|
+
version = "6.4.2"
|
|
8
8
|
description = "Task-oriented HWPX document automation for Python, with an optional MCP adapter."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Kohkyuhyun" }]
|
|
@@ -29,7 +29,7 @@ dependencies = [
|
|
|
29
29
|
# the bounded major here is what makes "no valid install has two declarers"
|
|
30
30
|
# true rather than hopeful, and prevents the next core major from silently
|
|
31
31
|
# breaking an already-published automation line.
|
|
32
|
-
"python-hwpx>=5.
|
|
32
|
+
"python-hwpx>=5.4.0,<6", # HWPX object model, OXML/OPC, format-native primitives
|
|
33
33
|
|
|
34
34
|
"pydantic>=2.11,<3",
|
|
35
35
|
"cryptography>=42.0",
|
{python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/core/content.py
RENAMED
|
@@ -418,20 +418,77 @@ def split_cell_in_table(doc: HwpxDocument, table_index: int, row: int, col: int)
|
|
|
418
418
|
return original
|
|
419
419
|
|
|
420
420
|
|
|
421
|
-
def
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
421
|
+
def _apply_table_border_fill(
|
|
422
|
+
doc: HwpxDocument,
|
|
423
|
+
table,
|
|
424
|
+
border_type: str = None,
|
|
425
|
+
border_color: str = None,
|
|
426
|
+
border_width: str = None,
|
|
427
|
+
fill_color: str = None,
|
|
428
|
+
row: int = None,
|
|
429
|
+
col: int = None,
|
|
430
|
+
) -> str:
|
|
431
|
+
"""테두리/음영 borderFill을 만들어 표 전체 또는 한 셀에 적용한다."""
|
|
432
|
+
border_fill_id = doc.ensure_border_fill(
|
|
433
|
+
border_type=border_type or "SOLID",
|
|
434
|
+
border_color=border_color or "#000000",
|
|
435
|
+
border_width=border_width or "0.12 mm",
|
|
436
|
+
fill_color=fill_color,
|
|
437
|
+
)
|
|
438
|
+
if row is not None:
|
|
439
|
+
table.set_cell_border_fill(row, col, border_fill_id)
|
|
440
|
+
return border_fill_id
|
|
441
|
+
table.element.set("borderFillIDRef", str(border_fill_id))
|
|
442
|
+
for table_row in table.rows:
|
|
443
|
+
for cell in table_row.cells:
|
|
444
|
+
cell.element.set("borderFillIDRef", str(border_fill_id))
|
|
445
|
+
table.mark_dirty()
|
|
446
|
+
return border_fill_id
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def format_table_in_doc(
|
|
450
|
+
doc: HwpxDocument,
|
|
451
|
+
table_index: int,
|
|
452
|
+
has_header_row: bool = None,
|
|
453
|
+
border_type: str = None,
|
|
454
|
+
border_color: str = None,
|
|
455
|
+
border_width: str = None,
|
|
456
|
+
fill_color: str = None,
|
|
457
|
+
row: int = None,
|
|
458
|
+
col: int = None,
|
|
459
|
+
) -> dict:
|
|
460
|
+
"""표 서식을 변경한다. 헤더 행 강조·테두리(선 종류/색/굵기)·셀 음영."""
|
|
461
|
+
if (row is None) != (col is None):
|
|
462
|
+
raise ValueError("row와 col은 함께 지정해야 합니다 (셀 단위 테두리 적용)")
|
|
463
|
+
wants_border = any(
|
|
464
|
+
value is not None for value in (border_type, border_color, border_width, fill_color)
|
|
465
|
+
)
|
|
466
|
+
if row is not None and not wants_border:
|
|
467
|
+
raise ValueError("row/col 지정은 테두리·음영 파라미터와 함께 사용합니다")
|
|
468
|
+
if has_header_row is None and not wants_border:
|
|
469
|
+
return {}
|
|
425
470
|
tables = list(_iter_tables(doc))
|
|
426
471
|
if table_index < 0 or table_index >= len(tables):
|
|
427
472
|
raise ValueError(f"유효하지 않은 table_index: {table_index}")
|
|
428
473
|
table = tables[table_index]
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
474
|
+
applied: dict = {}
|
|
475
|
+
if wants_border:
|
|
476
|
+
applied["border_fill_id"] = _apply_table_border_fill(
|
|
477
|
+
doc,
|
|
478
|
+
table,
|
|
479
|
+
border_type=border_type,
|
|
480
|
+
border_color=border_color,
|
|
481
|
+
border_width=border_width,
|
|
482
|
+
fill_color=fill_color,
|
|
483
|
+
row=row,
|
|
484
|
+
col=col,
|
|
485
|
+
)
|
|
486
|
+
if has_header_row is not None and table.rows:
|
|
487
|
+
for cell in table.rows[0].cells:
|
|
488
|
+
for paragraph in getattr(cell, "paragraphs", []):
|
|
489
|
+
for run in paragraph.runs:
|
|
490
|
+
run.bold = bool(has_header_row)
|
|
491
|
+
return applied
|
|
435
492
|
|
|
436
493
|
|
|
437
494
|
def copy_document_file(source: str, destination: str = None) -> str:
|
|
@@ -680,6 +680,46 @@ def add_page_break(
|
|
|
680
680
|
return _with_save_verification({"success": True}, verification)
|
|
681
681
|
|
|
682
682
|
|
|
683
|
+
def add_chart(
|
|
684
|
+
filename: str,
|
|
685
|
+
chart_type: str,
|
|
686
|
+
categories: list,
|
|
687
|
+
series: list,
|
|
688
|
+
title: str = None,
|
|
689
|
+
paragraph_index: int = None,
|
|
690
|
+
table_index: int = None,
|
|
691
|
+
row: int = None,
|
|
692
|
+
col: int = None,
|
|
693
|
+
treat_as_char: bool = False,
|
|
694
|
+
dry_run: bool = False,
|
|
695
|
+
expected_revision: str = None,
|
|
696
|
+
) -> dict:
|
|
697
|
+
"""네이티브 차트(<hp:chart>+ECMA-376 chartML part)를 삽입합니다. 렌더 검증된
|
|
698
|
+
MVP 3종(bar·line·pie)만 지원 — 밖이면 CHART_UNSUPPORTED로 typed 거부(무음
|
|
699
|
+
근사 없음). series=[{"name": str, "values": [number,...]}], values 길이는
|
|
700
|
+
categories와 일치해야 합니다. 실한컴은 chartML만으로 차트를 그립니다(OLE
|
|
701
|
+
폴백·사전렌더 이미지 불요). 배치: 기본=문서 끝 새 문단(float),
|
|
702
|
+
paragraph_index=기존 문단, tableIndex+row+col=표 셀, treat_as_char=인라인."""
|
|
703
|
+
path = resolve_path(filename)
|
|
704
|
+
guard = _revision_guard(path, expected_revision)
|
|
705
|
+
if guard is not None:
|
|
706
|
+
return guard
|
|
707
|
+
result = RUNTIME_SERVICES.ops.add_chart(
|
|
708
|
+
path,
|
|
709
|
+
chart_type=chart_type,
|
|
710
|
+
categories=categories,
|
|
711
|
+
series=series,
|
|
712
|
+
title=title,
|
|
713
|
+
paragraph_index=paragraph_index,
|
|
714
|
+
table_index=table_index,
|
|
715
|
+
row=row,
|
|
716
|
+
col=col,
|
|
717
|
+
treat_as_char=treat_as_char,
|
|
718
|
+
dry_run=dry_run,
|
|
719
|
+
)
|
|
720
|
+
return _with_document_state(result, path)
|
|
721
|
+
|
|
722
|
+
|
|
683
723
|
def add_equation(
|
|
684
724
|
filename: str,
|
|
685
725
|
latex: str = None,
|
|
@@ -1070,24 +1110,40 @@ def format_table(
|
|
|
1070
1110
|
filename: str,
|
|
1071
1111
|
table_index: int,
|
|
1072
1112
|
has_header_row: bool = None,
|
|
1113
|
+
border_type: str = None,
|
|
1114
|
+
border_color: str = None,
|
|
1115
|
+
border_width: str = None,
|
|
1116
|
+
fill_color: str = None,
|
|
1117
|
+
row: int = None,
|
|
1118
|
+
col: int = None,
|
|
1073
1119
|
dry_run: bool = False,
|
|
1074
1120
|
expected_revision: str = None,
|
|
1075
1121
|
) -> dict:
|
|
1076
|
-
"""표 서식을 적용합니다.
|
|
1122
|
+
"""표 서식을 적용합니다. 헤더 행 강조 외에 테두리 선 종류(OWPML 어휘:
|
|
1123
|
+
SOLID/DASH/DOT/DOUBLE_SLIM/WAVE 등)·색·굵기와 셀 음영(fill_color)을
|
|
1124
|
+
표 전체 또는 (row, col) 한 셀에 적용합니다. dry_run=True이면 원본을
|
|
1125
|
+
저장하지 않습니다."""
|
|
1077
1126
|
path = resolve_path(filename)
|
|
1078
1127
|
guard = _revision_guard(path, expected_revision)
|
|
1079
1128
|
if guard is not None:
|
|
1080
1129
|
return guard
|
|
1081
1130
|
doc = open_doc(path)
|
|
1082
|
-
format_table_in_doc(
|
|
1131
|
+
applied = format_table_in_doc(
|
|
1132
|
+
doc,
|
|
1133
|
+
table_index,
|
|
1134
|
+
has_header_row=has_header_row,
|
|
1135
|
+
border_type=border_type,
|
|
1136
|
+
border_color=border_color,
|
|
1137
|
+
border_width=border_width,
|
|
1138
|
+
fill_color=fill_color,
|
|
1139
|
+
row=row,
|
|
1140
|
+
col=col,
|
|
1141
|
+
)
|
|
1142
|
+
result = {"formatted": True, "table_index": table_index, **applied}
|
|
1083
1143
|
if dry_run:
|
|
1084
|
-
return _with_dry_run_verification(
|
|
1085
|
-
{"formatted": True, "table_index": table_index}, doc, path
|
|
1086
|
-
)
|
|
1144
|
+
return _with_dry_run_verification(result, doc, path)
|
|
1087
1145
|
verification = _save_doc_verification(doc, path)
|
|
1088
|
-
return _with_save_verification(
|
|
1089
|
-
{"formatted": True, "table_index": table_index}, verification
|
|
1090
|
-
)
|
|
1146
|
+
return _with_save_verification(result, verification)
|
|
1091
1147
|
|
|
1092
1148
|
|
|
1093
1149
|
__all__ = [
|
|
@@ -1097,6 +1153,7 @@ __all__ = [
|
|
|
1097
1153
|
"delete_paragraph",
|
|
1098
1154
|
"add_page_break",
|
|
1099
1155
|
"add_equation",
|
|
1156
|
+
"add_chart",
|
|
1100
1157
|
"apply_edits",
|
|
1101
1158
|
"undo_last_edit",
|
|
1102
1159
|
"replace_by_anchor",
|
{python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/hwpx_ops.py
RENAMED
|
@@ -517,6 +517,35 @@ class HwpxOps:
|
|
|
517
517
|
path, text, section_index=section_index, run_style=run_style
|
|
518
518
|
)
|
|
519
519
|
|
|
520
|
+
def add_chart(
|
|
521
|
+
self,
|
|
522
|
+
path: str,
|
|
523
|
+
*,
|
|
524
|
+
chart_type: str,
|
|
525
|
+
categories: list[str],
|
|
526
|
+
series: list[dict],
|
|
527
|
+
title: Optional[str] = None,
|
|
528
|
+
paragraph_index: Optional[int] = None,
|
|
529
|
+
table_index: Optional[int] = None,
|
|
530
|
+
row: Optional[int] = None,
|
|
531
|
+
col: Optional[int] = None,
|
|
532
|
+
treat_as_char: bool = False,
|
|
533
|
+
dry_run: bool = False,
|
|
534
|
+
) -> Dict[str, Any]:
|
|
535
|
+
return self._services.content_layout.add_chart(
|
|
536
|
+
path,
|
|
537
|
+
chart_type=chart_type,
|
|
538
|
+
categories=categories,
|
|
539
|
+
series=series,
|
|
540
|
+
title=title,
|
|
541
|
+
paragraph_index=paragraph_index,
|
|
542
|
+
table_index=table_index,
|
|
543
|
+
row=row,
|
|
544
|
+
col=col,
|
|
545
|
+
treat_as_char=treat_as_char,
|
|
546
|
+
dry_run=dry_run,
|
|
547
|
+
)
|
|
548
|
+
|
|
520
549
|
def add_equation(
|
|
521
550
|
self,
|
|
522
551
|
path: str,
|
{python_hwpx_automation-6.2.1 → python_hwpx_automation-6.4.2}/src/hwpx_automation/identity.json
RENAMED
|
@@ -5,20 +5,20 @@
|
|
|
5
5
|
"releaseState": {
|
|
6
6
|
"status": "release-approved",
|
|
7
7
|
"candidate": {
|
|
8
|
-
"pythonHwpx": "5.
|
|
8
|
+
"pythonHwpx": "5.4.0",
|
|
9
9
|
"canonicalDistribution": "python-hwpx-automation",
|
|
10
|
-
"canonicalAutomation": "6.2
|
|
10
|
+
"canonicalAutomation": "6.4.2",
|
|
11
11
|
"compatibilityDistribution": "hwpx-mcp-server",
|
|
12
|
-
"compatibility": "6.2
|
|
13
|
-
"plugin": "1.
|
|
14
|
-
"contractHash": "
|
|
12
|
+
"compatibility": "6.4.2",
|
|
13
|
+
"plugin": "1.4.0",
|
|
14
|
+
"contractHash": "dbdbdfaac26148b7"
|
|
15
15
|
},
|
|
16
16
|
"currentPublic": {
|
|
17
|
-
"pythonHwpx": "5.
|
|
17
|
+
"pythonHwpx": "5.3.0",
|
|
18
18
|
"primaryDistribution": "python-hwpx-automation",
|
|
19
|
-
"primaryApplication": "6.1
|
|
20
|
-
"plugin": "1.
|
|
21
|
-
"contractHash": "
|
|
19
|
+
"primaryApplication": "6.3.1",
|
|
20
|
+
"plugin": "1.3.0",
|
|
21
|
+
"contractHash": "236f8ea855c875fe"
|
|
22
22
|
},
|
|
23
23
|
"promotionGate": "Three states are mandatory: unreleased-candidate while auditing; release-approved only after separate owner approval and while currentPublic still names the previously observed coherent stack; released only in a follow-up commit after remote truth is observed for core, canonical automation, the compatibility distribution, the plugin GitHub release, the marketplace entry, and a real marketplace install. The automation tag workflow publishes only release-approved, leaves currentPublic unchanged, and hands an attached receipt to plugin publication."
|
|
24
24
|
},
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Deterministic data → ECMA-376 chartML generator (MVP: bar, line, pie).
|
|
3
|
+
|
|
4
|
+
The grammar mirrors the render-verified probes in
|
|
5
|
+
specs/055-chart-authoring/evidence/p0 (workspace): a ``c:chartSpace``
|
|
6
|
+
skeleton, per-series ``c:ser`` with string/number caches, and the
|
|
7
|
+
type-specific plot element (``c:barChart`` / ``c:lineChart`` + axis pair /
|
|
8
|
+
``c:pieChart``). Anything outside the verified set is refused with a typed
|
|
9
|
+
error — no silent approximation. Real Hancom draws the output from the
|
|
10
|
+
chartML alone (no OLE fallback, no pre-rendered image).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from typing import Sequence
|
|
17
|
+
from xml.sax.saxutils import escape
|
|
18
|
+
|
|
19
|
+
CHART_TYPES = ("bar", "line", "pie")
|
|
20
|
+
|
|
21
|
+
_CAT_AX_ID = "111111111"
|
|
22
|
+
_VAL_AX_ID = "222222222"
|
|
23
|
+
|
|
24
|
+
_HEAD = (
|
|
25
|
+
'<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'
|
|
26
|
+
'<c:chartSpace xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"'
|
|
27
|
+
' xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"'
|
|
28
|
+
' xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart">'
|
|
29
|
+
'<c:date1904 val="0"/><c:roundedCorners val="0"/><c:chart>'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class UnsupportedChartError(ValueError):
|
|
34
|
+
"""Raised for chart types or shapes outside the render-verified MVP set."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class ChartSeries:
|
|
39
|
+
"""One data series: a display name and one value per category."""
|
|
40
|
+
|
|
41
|
+
name: str
|
|
42
|
+
values: tuple[float, ...]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _series(index: int, name: str, categories: Sequence[str],
|
|
46
|
+
values: Sequence[float], extra: str = "") -> str:
|
|
47
|
+
cats = "".join(
|
|
48
|
+
f'<c:pt idx="{i}"><c:v>{escape(str(c))}</c:v></c:pt>'
|
|
49
|
+
for i, c in enumerate(categories)
|
|
50
|
+
)
|
|
51
|
+
vals = "".join(
|
|
52
|
+
f'<c:pt idx="{i}"><c:v>{v:g}</c:v></c:pt>' for i, v in enumerate(values)
|
|
53
|
+
)
|
|
54
|
+
column = chr(ord("B") + index)
|
|
55
|
+
return (
|
|
56
|
+
f'<c:ser><c:idx val="{index}"/><c:order val="{index}"/>'
|
|
57
|
+
f"<c:tx><c:strRef><c:f>Sheet1!${column}$1</c:f>"
|
|
58
|
+
f'<c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>{escape(name)}</c:v></c:pt>'
|
|
59
|
+
f"</c:strCache></c:strRef></c:tx>{extra}"
|
|
60
|
+
f"<c:cat><c:strRef><c:f>Sheet1!$A$2:$A${len(categories) + 1}</c:f>"
|
|
61
|
+
f'<c:strCache><c:ptCount val="{len(categories)}"/>{cats}</c:strCache></c:strRef></c:cat>'
|
|
62
|
+
f"<c:val><c:numRef><c:f>Sheet1!${column}$2:${column}${len(values) + 1}</c:f>"
|
|
63
|
+
f"<c:numCache><c:formatCode>General</c:formatCode>"
|
|
64
|
+
f'<c:ptCount val="{len(values)}"/>{vals}</c:numCache></c:numRef></c:val></c:ser>'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _axes() -> str:
|
|
69
|
+
return (
|
|
70
|
+
f'<c:catAx><c:axId val="{_CAT_AX_ID}"/>'
|
|
71
|
+
'<c:scaling><c:orientation val="minMax"/></c:scaling><c:delete val="0"/>'
|
|
72
|
+
f'<c:axPos val="b"/><c:crossAx val="{_VAL_AX_ID}"/></c:catAx>'
|
|
73
|
+
f'<c:valAx><c:axId val="{_VAL_AX_ID}"/>'
|
|
74
|
+
'<c:scaling><c:orientation val="minMax"/></c:scaling><c:delete val="0"/>'
|
|
75
|
+
f'<c:axPos val="l"/><c:crossAx val="{_CAT_AX_ID}"/></c:valAx>'
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def build_chart_ml(
|
|
80
|
+
chart_type: str,
|
|
81
|
+
categories: Sequence[str],
|
|
82
|
+
series: Sequence[ChartSeries],
|
|
83
|
+
*,
|
|
84
|
+
title: str | None = None,
|
|
85
|
+
) -> str:
|
|
86
|
+
"""Build chartML for one of the render-verified MVP chart types.
|
|
87
|
+
|
|
88
|
+
Raises:
|
|
89
|
+
UnsupportedChartError: unknown chart type, empty/mismatched data, or
|
|
90
|
+
a shape outside the verified set (e.g. multi-series pie).
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
if chart_type not in CHART_TYPES:
|
|
94
|
+
raise UnsupportedChartError(
|
|
95
|
+
f"unsupported chart type {chart_type!r}; render-verified types: "
|
|
96
|
+
+ ", ".join(CHART_TYPES)
|
|
97
|
+
)
|
|
98
|
+
if not categories:
|
|
99
|
+
raise UnsupportedChartError("categories must be non-empty")
|
|
100
|
+
if not series:
|
|
101
|
+
raise UnsupportedChartError("series must be non-empty")
|
|
102
|
+
if chart_type == "pie" and len(series) != 1:
|
|
103
|
+
raise UnsupportedChartError("a pie chart takes exactly one series")
|
|
104
|
+
if len(series) > 25:
|
|
105
|
+
raise UnsupportedChartError("at most 25 series are supported")
|
|
106
|
+
for item in series:
|
|
107
|
+
if not item.name.strip():
|
|
108
|
+
raise UnsupportedChartError("every series needs a non-empty name")
|
|
109
|
+
if len(item.values) != len(categories):
|
|
110
|
+
raise UnsupportedChartError(
|
|
111
|
+
f"series {item.name!r} has {len(item.values)} values for "
|
|
112
|
+
f"{len(categories)} categories"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
parts: list[str] = [_HEAD]
|
|
116
|
+
if title is not None and title.strip():
|
|
117
|
+
parts.append(
|
|
118
|
+
"<c:title><c:tx><c:rich><a:bodyPr/><a:p><a:r><a:t>"
|
|
119
|
+
+ escape(title)
|
|
120
|
+
+ "</a:t></a:r></a:p></c:rich></c:tx><c:overlay val=\"0\"/></c:title>"
|
|
121
|
+
'<c:autoTitleDeleted val="0"/>'
|
|
122
|
+
)
|
|
123
|
+
parts.append("<c:plotArea><c:layout/>")
|
|
124
|
+
|
|
125
|
+
if chart_type == "bar":
|
|
126
|
+
parts.append('<c:barChart><c:barDir val="col"/><c:grouping val="clustered"/><c:varyColors val="0"/>')
|
|
127
|
+
for index, item in enumerate(series):
|
|
128
|
+
parts.append(_series(index, item.name, categories, item.values))
|
|
129
|
+
parts.append(
|
|
130
|
+
f'<c:axId val="{_CAT_AX_ID}"/><c:axId val="{_VAL_AX_ID}"/></c:barChart>'
|
|
131
|
+
)
|
|
132
|
+
parts.append(_axes())
|
|
133
|
+
elif chart_type == "line":
|
|
134
|
+
parts.append('<c:lineChart><c:grouping val="standard"/><c:varyColors val="0"/>')
|
|
135
|
+
for index, item in enumerate(series):
|
|
136
|
+
parts.append(
|
|
137
|
+
_series(
|
|
138
|
+
index, item.name, categories, item.values,
|
|
139
|
+
'<c:marker><c:symbol val="circle"/><c:size val="5"/></c:marker>',
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
parts.append(
|
|
143
|
+
'<c:marker val="1"/>'
|
|
144
|
+
f'<c:axId val="{_CAT_AX_ID}"/><c:axId val="{_VAL_AX_ID}"/></c:lineChart>'
|
|
145
|
+
)
|
|
146
|
+
parts.append(_axes())
|
|
147
|
+
else: # pie
|
|
148
|
+
parts.append('<c:pieChart><c:varyColors val="1"/>')
|
|
149
|
+
parts.append(_series(0, series[0].name, categories, series[0].values))
|
|
150
|
+
parts.append('<c:firstSliceAng val="0"/></c:pieChart>')
|
|
151
|
+
|
|
152
|
+
parts.append("</c:plotArea>")
|
|
153
|
+
parts.append('<c:plotVisOnly val="1"/></c:chart></c:chartSpace>')
|
|
154
|
+
return "".join(parts)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
__all__ = [
|
|
158
|
+
"CHART_TYPES",
|
|
159
|
+
"ChartSeries",
|
|
160
|
+
"UnsupportedChartError",
|
|
161
|
+
"build_chart_ml",
|
|
162
|
+
]
|
|
@@ -127,17 +127,18 @@ class ContentLayoutService:
|
|
|
127
127
|
table_index: Optional[int],
|
|
128
128
|
row: Optional[int],
|
|
129
129
|
col: Optional[int],
|
|
130
|
+
target_error_code: str = "EQUATION_TARGET_INVALID",
|
|
130
131
|
) -> Any:
|
|
131
132
|
cell_parts = (table_index, row, col)
|
|
132
133
|
use_cell = any(part is not None for part in cell_parts)
|
|
133
134
|
if use_cell and not all(part is not None for part in cell_parts):
|
|
134
135
|
raise self._context._new_error(
|
|
135
|
-
|
|
136
|
+
target_error_code,
|
|
136
137
|
"provide tableIndex, row, and col together for a cell target",
|
|
137
138
|
)
|
|
138
139
|
if use_cell and paragraph_index is not None:
|
|
139
140
|
raise self._context._new_error(
|
|
140
|
-
|
|
141
|
+
target_error_code,
|
|
141
142
|
"paragraphIndex cannot be combined with a cell target",
|
|
142
143
|
)
|
|
143
144
|
if use_cell:
|
|
@@ -169,6 +170,80 @@ class ContentLayoutService:
|
|
|
169
170
|
) from exc
|
|
170
171
|
return None
|
|
171
172
|
|
|
173
|
+
def add_chart(
|
|
174
|
+
self,
|
|
175
|
+
path: str,
|
|
176
|
+
*,
|
|
177
|
+
chart_type: str,
|
|
178
|
+
categories: list[str],
|
|
179
|
+
series: list[dict],
|
|
180
|
+
title: Optional[str] = None,
|
|
181
|
+
paragraph_index: Optional[int] = None,
|
|
182
|
+
table_index: Optional[int] = None,
|
|
183
|
+
row: Optional[int] = None,
|
|
184
|
+
col: Optional[int] = None,
|
|
185
|
+
treat_as_char: bool = False,
|
|
186
|
+
dry_run: bool = False,
|
|
187
|
+
) -> Dict[str, Any]:
|
|
188
|
+
from ..office.charting import (
|
|
189
|
+
ChartSeries,
|
|
190
|
+
UnsupportedChartError,
|
|
191
|
+
build_chart_ml,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
parsed_series = [
|
|
196
|
+
ChartSeries(
|
|
197
|
+
name=str(item.get("name", "")),
|
|
198
|
+
values=tuple(float(v) for v in item.get("values", ())),
|
|
199
|
+
)
|
|
200
|
+
for item in series
|
|
201
|
+
]
|
|
202
|
+
except (TypeError, ValueError) as exc:
|
|
203
|
+
raise self._context._new_error(
|
|
204
|
+
"CHART_INPUT_INVALID",
|
|
205
|
+
f"series values must be numbers: {exc}",
|
|
206
|
+
) from exc
|
|
207
|
+
try:
|
|
208
|
+
chart_ml = build_chart_ml(
|
|
209
|
+
chart_type, categories, parsed_series, title=title
|
|
210
|
+
)
|
|
211
|
+
except UnsupportedChartError as exc:
|
|
212
|
+
raise self._context._new_error(
|
|
213
|
+
"CHART_UNSUPPORTED", str(exc)
|
|
214
|
+
) from exc
|
|
215
|
+
|
|
216
|
+
document, resolved = self._context._open_document(path)
|
|
217
|
+
paragraph = self._resolve_equation_target(
|
|
218
|
+
document,
|
|
219
|
+
paragraph_index=paragraph_index,
|
|
220
|
+
table_index=table_index,
|
|
221
|
+
row=row,
|
|
222
|
+
col=col,
|
|
223
|
+
target_error_code="CHART_TARGET_INVALID",
|
|
224
|
+
)
|
|
225
|
+
try:
|
|
226
|
+
inline_object = document.add_chart(
|
|
227
|
+
chart_ml, paragraph=paragraph, treat_as_char=treat_as_char
|
|
228
|
+
)
|
|
229
|
+
except ValueError as exc:
|
|
230
|
+
raise self._context._new_error(
|
|
231
|
+
"CHART_INPUT_INVALID", str(exc)
|
|
232
|
+
) from exc
|
|
233
|
+
result = {
|
|
234
|
+
"ok": True,
|
|
235
|
+
"filename": path,
|
|
236
|
+
"chart": {
|
|
237
|
+
"chartType": chart_type,
|
|
238
|
+
"chartIDRef": inline_object.element.get("chartIDRef"),
|
|
239
|
+
"seriesCount": len(parsed_series),
|
|
240
|
+
"categoryCount": len(categories),
|
|
241
|
+
},
|
|
242
|
+
}
|
|
243
|
+
return self._transactions._with_transaction_verification(
|
|
244
|
+
result, document, resolved, dry_run=dry_run
|
|
245
|
+
)
|
|
246
|
+
|
|
172
247
|
def add_equation(
|
|
173
248
|
self,
|
|
174
249
|
path: str,
|