datex-studio-cli 0.5.4__tar.gz → 0.5.5__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.
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/PKG-INFO +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/pyproject.toml +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/__init__.py +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/cli.py +92 -2
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/document.py +19 -8
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/odata.py +30 -17
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/release_notes.py +32 -23
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/source.py +147 -237
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/__init__.py +8 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/app_config.py +89 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/flow_generator.py +2 -2
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/flow_shape.py +24 -16
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/validator.py +5 -4
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/errors.py +4 -0
- datex_studio_cli-0.5.5/src/dxs/utils/http_errors.py +109 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/404/index.html +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/404.html +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/design/capture/index.html +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/design/capture/index.txt +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/design/index.html +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/design/index.txt +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/index.html +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/index.txt +1 -1
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/.dockerignore +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/.github/actionlint.yaml +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/.github/workflows/build-image.yml +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/.github/workflows/ci.yml +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/.github/workflows/promote-prod.yml +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/.github/workflows/release.yml +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/.gitignore +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/CONTEXT.md +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/README.md +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/.env.example +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/Dockerfile +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/README.md +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/apply-local-cache.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/collector-config.yaml +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/docker-compose.yml +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/local-test-settings.json +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/otel/remote-settings.json +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/report-creator.skill +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/scripts/analyze_corpus.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/scripts/check_wheel_completeness.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/scripts/datadog_errors.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/scripts/generate_rdlx_schema.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/scripts/wavelength_query.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/__main__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/api.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/auth.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/branch.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/branch_commit_guard.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/cascade.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/config.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/configuration.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/crm.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/crm_delivery.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/crm_time.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/datasource.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/devops.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/endpoint.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/env.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/explore.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/function.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/init.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/marketplace.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/ng/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/ng/_common.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/ng/api.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/ng/create.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/ng/data.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/ng/pack.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/ng/preview.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/organization.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/proxy.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/reference.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/repo.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/add_cmds.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/api.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/batch.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/create.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/data.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/dataset.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/edit.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/folder.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/preview.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/report/schema_cmds.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/reset.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/schema.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/servicepack.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/skills.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/studio.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/telemetry.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/user.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/commands/validation_report.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/context.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/agent_browser.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/client.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/endpoints.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/metadata_models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/reference_graph.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/api/replacements.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/browser_pages.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/datex_tenant.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/decorators.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/msal_client.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/pages/error.html +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/pages/success.html +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/tenants.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/auth/token_cache.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/cache.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/flow_models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/generator.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/parsers.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/resolver.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/datasource/type_def_parser.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/designer/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/designer/flow_models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/designer/models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/designer/parsers.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/devops/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/devops/client.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/devops/helpers.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/devops/models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/dynamics/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/dynamics/client.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/dynamics/html.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/dynamics/metadata_cache.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/dynamics/pagination.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/dynamics/resolvers.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/dynamics/time_entry.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/footprint/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/footprint/client.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/footprint/edmx_parser.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/footprint/metadata.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/function/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/function/generator.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/function/models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/function/validator.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/graph.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/onboarding.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/output/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/output/csv_fmt.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/output/formatter.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/output/json_fmt.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/output/redaction.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/output/yaml_fmt.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/quartermaster/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/quartermaster/client.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/quartermaster/tenants.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/release_notes.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/responses.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/skills/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/skills/frontmatter.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/skills/installer.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/skills/layout.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/skills/lock.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/skills/resolver.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/skills/staleness.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/telemetry/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/telemetry/config.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/telemetry/identity.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/telemetry/recorder.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/telemetry/scrubber.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/core/telemetry/sender.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/models/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/ng/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/ng/folder.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/ng/manifest.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/ng/mocks.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/ng/preview.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/ng/scaffold.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/ng/serve_lock.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/py.typed +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/datasource_binding.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/engine.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/field_parser.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/folder.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/manifest.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/models.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/preview.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/preview_arjs.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/schema.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/svg_renderer.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/templates/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/templates/bill_of_lading.rdlx-json +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/templates/shipping_label.rdlx-json +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/validate_arjs.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/validator.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/report/wrapper.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/click_options.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/clipboard.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/config.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/filtering.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/image.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/paths.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/resolvers.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/responses.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/restricted.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/sorting.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/update_check.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/utils/versioning.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/__init__.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/app.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/design.py +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/proxy_app.py +0 -0
- {datex_studio_cli-0.5.4/src/dxs/web/static/_next/static/CAvN0dC1A3kKCmq1ZHlgY → datex_studio_cli-0.5.5/src/dxs/web/static/_next/static/5wdnX570BhEyVxkNIJZQ9}/_buildManifest.js +0 -0
- {datex_studio_cli-0.5.4/src/dxs/web/static/_next/static/CAvN0dC1A3kKCmq1ZHlgY → datex_studio_cli-0.5.5/src/dxs/web/static/_next/static/5wdnX570BhEyVxkNIJZQ9}/_ssgManifest.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/0b24cca5-c1e1c8810348f107.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/255-102f2e5b2e3dc2ef.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/538-b06224e65f71c9a1.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/697-0e000ab410d9f470.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/871-1acacdb7b4022abf.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/8b8f67fc-6295949a4b5485a4.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/909-c88abba3cf0caec3.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/app/_not-found/page-e3c660196c244183.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/app/design/capture/page-c083dc9f01f32a04.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/app/design/page-689cd5b9e1d9a74e.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/app/layout-cec86f90e385371d.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/app/page-f0380b0f29983264.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/framework-de98b93a850cfc71.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/main-0f18f91200dac003.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/main-app-694cf3568b6c9fa9.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/pages/_app-7d307437aca18ad4.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/chunks/webpack-2b297ada5306c17f.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/_next/static/css/360c657de5e04df8.css +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/render-cli.js +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/report-preview.html +0 -0
- {datex_studio_cli-0.5.4 → datex_studio_cli-0.5.5}/src/dxs/web/static/report-validate.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: datex-studio-cli
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.5
|
|
4
4
|
Summary: CLI for Datex Studio low-code platform, designed for LLM-based AI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/datex/datex-studio-cli
|
|
6
6
|
Project-URL: Documentation, https://github.com/datex/datex-studio-cli
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""Main CLI entry point for Datex Studio CLI."""
|
|
2
2
|
|
|
3
|
+
import errno
|
|
4
|
+
import os
|
|
3
5
|
import sys
|
|
4
6
|
from collections.abc import Callable
|
|
5
|
-
from typing import Any, TypeVar, cast
|
|
7
|
+
from typing import Any, NoReturn, TypeVar, cast
|
|
6
8
|
|
|
7
9
|
import click
|
|
8
10
|
|
|
@@ -136,7 +138,16 @@ class DxsGroup(click.Group):
|
|
|
136
138
|
so ``_resolve_command_path`` reads them back from ``ctx.meta``.
|
|
137
139
|
"""
|
|
138
140
|
ctx.meta[RAW_ARGS_META_KEY] = [*getattr(ctx, "_protected_args", []), *ctx.args]
|
|
139
|
-
|
|
141
|
+
try:
|
|
142
|
+
return super().invoke(ctx)
|
|
143
|
+
except (BrokenPipeError, OSError) as e:
|
|
144
|
+
# Handle a closed stdout here, inside Click's own invoke, rather
|
|
145
|
+
# than around cli(): Click catches EPIPE itself and exits 1, so by
|
|
146
|
+
# the time main() sees anything it is a SystemExit. Raising
|
|
147
|
+
# SystemExit from here passes straight through that handler.
|
|
148
|
+
if not _is_broken_pipe(e):
|
|
149
|
+
raise
|
|
150
|
+
_exit_broken_pipe()
|
|
140
151
|
|
|
141
152
|
def _is_gated(self, cmd_name: str) -> bool:
|
|
142
153
|
"""Whether ``cmd_name`` is Datex-internal and unavailable to this user."""
|
|
@@ -547,6 +558,15 @@ def handle_errors(f: F) -> F:
|
|
|
547
558
|
_record_error_silently(e, dxs_ctx)
|
|
548
559
|
dxs_ctx.output_error(e)
|
|
549
560
|
sys.exit(1)
|
|
561
|
+
except (BrokenPipeError, OSError) as e:
|
|
562
|
+
# A closed stdout is not a command failure: re-raise so main()
|
|
563
|
+
# can silence it. Rendering an error envelope here would both
|
|
564
|
+
# lie to the user and record a bogus command.error.
|
|
565
|
+
if not _is_broken_pipe(e):
|
|
566
|
+
_record_error_silently(e, dxs_ctx)
|
|
567
|
+
dxs_ctx.output_error(e)
|
|
568
|
+
sys.exit(1)
|
|
569
|
+
raise
|
|
550
570
|
except (click.ClickException, click.Abort, click.exceptions.Exit):
|
|
551
571
|
# Let Click handle its own exceptions and control-flow signals
|
|
552
572
|
# (Abort from confirm(abort=True), Exit from ctx.exit) — these are
|
|
@@ -560,6 +580,67 @@ def handle_errors(f: F) -> F:
|
|
|
560
580
|
return cast(F, wrapper)
|
|
561
581
|
|
|
562
582
|
|
|
583
|
+
#: 128 + SIGPIPE, the conventional shell status for "died because the pipe closed".
|
|
584
|
+
BROKEN_PIPE_EXIT_CODE = 141
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def _is_broken_pipe(exc: BaseException) -> bool:
|
|
588
|
+
"""True when ``exc`` is stdout's consumer going away rather than a failure.
|
|
589
|
+
|
|
590
|
+
POSIX raises ``BrokenPipeError`` (EPIPE). Windows has no SIGPIPE and instead
|
|
591
|
+
fails the underlying ``flush()`` with ``OSError [Errno 22] Invalid argument``
|
|
592
|
+
— so EINVAL counts only there, since on POSIX it means a hundred other
|
|
593
|
+
things and must not be mistaken for a closed pipe.
|
|
594
|
+
"""
|
|
595
|
+
if isinstance(exc, BrokenPipeError):
|
|
596
|
+
return True
|
|
597
|
+
if not isinstance(exc, OSError):
|
|
598
|
+
return False
|
|
599
|
+
if exc.errno == errno.EPIPE:
|
|
600
|
+
return True
|
|
601
|
+
return exc.errno == errno.EINVAL and sys.platform == "win32"
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
def _silence_stdout() -> None:
|
|
605
|
+
"""Point stdout at devnull so interpreter shutdown cannot re-raise.
|
|
606
|
+
|
|
607
|
+
Python flushes the standard streams on exit; against a closed pipe that
|
|
608
|
+
raises a second time, past any handler we control, and CPython prints
|
|
609
|
+
"Exception ignored in: <_io.TextIOWrapper name='<stdout>'>". Redirecting the
|
|
610
|
+
file descriptor is the documented way to avoid it. Best-effort: under pytest
|
|
611
|
+
or Click's CliRunner stdout is a StringIO with no real fileno.
|
|
612
|
+
"""
|
|
613
|
+
devnull = None
|
|
614
|
+
try:
|
|
615
|
+
devnull = os.open(os.devnull, os.O_WRONLY)
|
|
616
|
+
os.dup2(devnull, sys.stdout.fileno())
|
|
617
|
+
except Exception: # noqa: BLE001 - silencing output must never itself fail
|
|
618
|
+
pass
|
|
619
|
+
finally:
|
|
620
|
+
if devnull is not None:
|
|
621
|
+
try:
|
|
622
|
+
os.close(devnull)
|
|
623
|
+
except OSError:
|
|
624
|
+
pass
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def _exit_broken_pipe() -> NoReturn:
|
|
628
|
+
"""Leave quietly after the consumer of stdout went away."""
|
|
629
|
+
_silence_stdout()
|
|
630
|
+
_record_broken_pipe_silently()
|
|
631
|
+
sys.exit(BROKEN_PIPE_EXIT_CODE)
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
def _record_broken_pipe_silently() -> None:
|
|
635
|
+
"""Record a closed pipe as a completed run, never as command.error."""
|
|
636
|
+
try:
|
|
637
|
+
from dxs.core.telemetry import record_end
|
|
638
|
+
|
|
639
|
+
record_end(exit_code=BROKEN_PIPE_EXIT_CODE)
|
|
640
|
+
except Exception: # noqa: BLE001
|
|
641
|
+
pass
|
|
642
|
+
|
|
643
|
+
|
|
563
644
|
def _record_error_silently(exc: BaseException, dxs_ctx: "DxsContext | None" = None) -> None:
|
|
564
645
|
"""Emit a telemetry error event; never raises.
|
|
565
646
|
|
|
@@ -850,6 +931,15 @@ def main() -> None:
|
|
|
850
931
|
# SystemExit from sys.exit() inside handle_errors — telemetry already
|
|
851
932
|
# recorded an error there; just propagate.
|
|
852
933
|
raise
|
|
934
|
+
except (BrokenPipeError, OSError) as e:
|
|
935
|
+
if not _is_broken_pipe(e):
|
|
936
|
+
_record_error_silently(e)
|
|
937
|
+
raise
|
|
938
|
+
# The consumer stopped reading (`| head`, an agent that moved on).
|
|
939
|
+
# Say nothing, record a completed run, and exit on the SIGPIPE
|
|
940
|
+
# convention so `set -o pipefail` scripts can still tell truncated
|
|
941
|
+
# output from a clean one.
|
|
942
|
+
_exit_broken_pipe()
|
|
853
943
|
except BaseException as e:
|
|
854
944
|
# Anything else escaping cli() shouldn't take telemetry with it.
|
|
855
945
|
_record_error_silently(e)
|
|
@@ -12,7 +12,14 @@ import click
|
|
|
12
12
|
import yaml
|
|
13
13
|
|
|
14
14
|
from dxs.cli import DxsContext, pass_context
|
|
15
|
-
from dxs.core.api import
|
|
15
|
+
from dxs.core.api import (
|
|
16
|
+
ApiClient,
|
|
17
|
+
BranchEndpoints,
|
|
18
|
+
ConfigurationEndpoints,
|
|
19
|
+
fetch_references,
|
|
20
|
+
reference_branch_ids,
|
|
21
|
+
resolve_references,
|
|
22
|
+
)
|
|
16
23
|
from dxs.core.auth import require_auth
|
|
17
24
|
from dxs.core.cache import ConfigIndex, get_cache
|
|
18
25
|
from dxs.core.graph import (
|
|
@@ -265,12 +272,16 @@ def _fetch_library_branches(
|
|
|
265
272
|
|
|
266
273
|
try:
|
|
267
274
|
refs = fetch_references(client, branch_id)
|
|
275
|
+
resolved = resolve_references(client, refs)
|
|
276
|
+
library_map = reference_branch_ids(refs, resolved)
|
|
268
277
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if
|
|
273
|
-
|
|
278
|
+
# A library we cannot place on a branch cannot be downloaded. Say so —
|
|
279
|
+
# silently returning fewer libraries is what made this failure invisible.
|
|
280
|
+
unresolved = sorted(
|
|
281
|
+
name for ref in refs if (name := ref.get("referenceName")) and name not in library_map
|
|
282
|
+
)
|
|
283
|
+
for name in unresolved:
|
|
284
|
+
_progress(f" Warning: could not resolve library '{name}' to a branch")
|
|
274
285
|
|
|
275
286
|
# Fetch branch statuses for all library branches (for caching decisions)
|
|
276
287
|
for lib_branch_id in set(library_map.values()):
|
|
@@ -281,8 +292,8 @@ def _fetch_library_branches(
|
|
|
281
292
|
except Exception:
|
|
282
293
|
branch_statuses[lib_branch_id] = 0 # Not cacheable if unknown
|
|
283
294
|
|
|
284
|
-
except Exception:
|
|
285
|
-
|
|
295
|
+
except Exception as exc:
|
|
296
|
+
_progress(f" Warning: failed to discover libraries: {exc}")
|
|
286
297
|
|
|
287
298
|
return library_map, branch_statuses
|
|
288
299
|
|
|
@@ -16,7 +16,7 @@ from typing import Any
|
|
|
16
16
|
import click
|
|
17
17
|
import httpx
|
|
18
18
|
|
|
19
|
-
from dxs.cli import DxsContext, pass_context
|
|
19
|
+
from dxs.cli import DxsContext, handle_errors, pass_context
|
|
20
20
|
from dxs.core.api import ApiClient
|
|
21
21
|
from dxs.core.api.endpoints import ApiConnectionEndpoints
|
|
22
22
|
from dxs.core.auth import require_auth
|
|
@@ -25,6 +25,7 @@ from dxs.core.footprint.edmx_parser import parse_edmx
|
|
|
25
25
|
from dxs.core.footprint.metadata import MetadataCache
|
|
26
26
|
from dxs.utils.config import get_settings
|
|
27
27
|
from dxs.utils.errors import ApiError, AuthenticationError, ValidationError
|
|
28
|
+
from dxs.utils.http_errors import raise_for_transport_error
|
|
28
29
|
from dxs.utils.resolvers import resolve_connection_option
|
|
29
30
|
from dxs.utils.responses import list_response, single
|
|
30
31
|
|
|
@@ -88,6 +89,7 @@ def odata() -> None:
|
|
|
88
89
|
)
|
|
89
90
|
@pass_context
|
|
90
91
|
@require_auth
|
|
92
|
+
@handle_errors
|
|
91
93
|
def execute(
|
|
92
94
|
ctx: DxsContext,
|
|
93
95
|
connection_id: int | None,
|
|
@@ -151,6 +153,7 @@ def execute(
|
|
|
151
153
|
token=token,
|
|
152
154
|
timeout=settings.api_timeout,
|
|
153
155
|
apply_oso_security=oso_security,
|
|
156
|
+
verify=settings.verify_ssl,
|
|
154
157
|
)
|
|
155
158
|
|
|
156
159
|
ctx.output(
|
|
@@ -372,6 +375,7 @@ def _execute_footprint_odata(
|
|
|
372
375
|
token: str,
|
|
373
376
|
timeout: int = 30,
|
|
374
377
|
apply_oso_security: bool = False,
|
|
378
|
+
verify: bool = True,
|
|
375
379
|
) -> dict[str, Any]:
|
|
376
380
|
"""Execute an OData GET request against the Footprint API."""
|
|
377
381
|
url = f"{connection_string}/{query}"
|
|
@@ -386,11 +390,14 @@ def _execute_footprint_odata(
|
|
|
386
390
|
if _is_daemon_mode():
|
|
387
391
|
headers["x-caller"] = _build_x_caller_header(token, apply_oso_security=apply_oso_security)
|
|
388
392
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
393
|
+
try:
|
|
394
|
+
with httpx.Client(timeout=timeout, verify=verify) as client:
|
|
395
|
+
response = client.get(url, headers=headers)
|
|
396
|
+
_raise_for_footprint_error(response)
|
|
397
|
+
result: dict[str, Any] = response.json()
|
|
398
|
+
return result
|
|
399
|
+
except httpx.TransportError as e:
|
|
400
|
+
raise_for_transport_error(e, url, what="the Footprint API", timeout=timeout)
|
|
394
401
|
|
|
395
402
|
|
|
396
403
|
@odata.group()
|
|
@@ -449,17 +456,20 @@ def _fetch_metadata(
|
|
|
449
456
|
|
|
450
457
|
x_caller = base64.b64encode(json.dumps({}).encode()).decode()
|
|
451
458
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
459
|
+
try:
|
|
460
|
+
with httpx.Client(timeout=settings.api_timeout, verify=settings.verify_ssl) as client:
|
|
461
|
+
response = client.get(
|
|
462
|
+
url,
|
|
463
|
+
headers={
|
|
464
|
+
"Authorization": f"Bearer {token}",
|
|
465
|
+
"x-caller": x_caller,
|
|
466
|
+
"Accept": "application/xml",
|
|
467
|
+
},
|
|
468
|
+
)
|
|
469
|
+
_raise_for_footprint_error(response)
|
|
470
|
+
xml = response.text
|
|
471
|
+
except httpx.TransportError as e:
|
|
472
|
+
raise_for_transport_error(e, url, what="the Footprint API", timeout=settings.api_timeout)
|
|
463
473
|
|
|
464
474
|
cache.put(resolved_id, xml, connection_name=connection_name)
|
|
465
475
|
ctx.log("Metadata cached.")
|
|
@@ -510,6 +520,7 @@ def _add_connection_options(f: Any) -> Any:
|
|
|
510
520
|
@_add_connection_options
|
|
511
521
|
@pass_context
|
|
512
522
|
@require_auth
|
|
523
|
+
@handle_errors
|
|
513
524
|
def fetch(
|
|
514
525
|
ctx: DxsContext,
|
|
515
526
|
connection_id: int | None,
|
|
@@ -544,6 +555,7 @@ def fetch(
|
|
|
544
555
|
@_add_connection_options
|
|
545
556
|
@pass_context
|
|
546
557
|
@require_auth
|
|
558
|
+
@handle_errors
|
|
547
559
|
def entities(
|
|
548
560
|
ctx: DxsContext,
|
|
549
561
|
connection_id: int | None,
|
|
@@ -587,6 +599,7 @@ def entities(
|
|
|
587
599
|
@_add_connection_options
|
|
588
600
|
@pass_context
|
|
589
601
|
@require_auth
|
|
602
|
+
@handle_errors
|
|
590
603
|
def describe(
|
|
591
604
|
ctx: DxsContext,
|
|
592
605
|
entity_name: str,
|
|
@@ -11,7 +11,10 @@ from dxs.core.api import (
|
|
|
11
11
|
ApiClient,
|
|
12
12
|
BranchEndpoints,
|
|
13
13
|
SourceControlEndpoints,
|
|
14
|
+
diff_references,
|
|
14
15
|
fetch_references,
|
|
16
|
+
reference_branch_id,
|
|
17
|
+
resolve_references,
|
|
15
18
|
)
|
|
16
19
|
from dxs.core.auth import require_auth
|
|
17
20
|
from dxs.core.release_notes import (
|
|
@@ -205,28 +208,26 @@ def release_notes(
|
|
|
205
208
|
from_deps = fetch_references(client, from_branch, direct_only=True)
|
|
206
209
|
to_deps = fetch_references(client, to_branch, direct_only=True)
|
|
207
210
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if ref not in to_by_ref:
|
|
229
|
-
dep_changes["removed"].append(from_by_ref[ref])
|
|
211
|
+
# Diff on the resolved `version`, keyed by uniqueIdentifier — the same
|
|
212
|
+
# helper `source compare` uses, so the two commands agree. The legacy
|
|
213
|
+
# marketPlaceApplicationVersionId comparison read None on both sides and
|
|
214
|
+
# so never reported a bump.
|
|
215
|
+
diff = diff_references(from_deps, to_deps)
|
|
216
|
+
dep_changes["added"] = diff["added"]
|
|
217
|
+
dep_changes["removed"] = diff["removed"]
|
|
218
|
+
|
|
219
|
+
# Classifying an update means diffing the two packages' branches, and the
|
|
220
|
+
# reference rows no longer carry applicationId — resolve it for both sides.
|
|
221
|
+
resolved = resolve_references(client, from_deps + to_deps)
|
|
222
|
+
for entry in diff["updated"]:
|
|
223
|
+
uid = entry.get("unique_identifier")
|
|
224
|
+
entry["from_branch_id"] = reference_branch_id(
|
|
225
|
+
resolved.get((uid, entry.get("from_version")))
|
|
226
|
+
)
|
|
227
|
+
entry["to_branch_id"] = reference_branch_id(
|
|
228
|
+
resolved.get((uid, entry.get("to_version")))
|
|
229
|
+
)
|
|
230
|
+
dep_changes["updated"] = diff["updated"]
|
|
230
231
|
except Exception:
|
|
231
232
|
logger.debug("Failed to fetch dependencies", exc_info=True)
|
|
232
233
|
|
|
@@ -235,7 +236,15 @@ def release_notes(
|
|
|
235
236
|
sync_only_deps: list[dict[str, Any]] = []
|
|
236
237
|
if dep_changes["updated"]:
|
|
237
238
|
ctx.log(f"Classifying {len(dep_changes['updated'])} dependency updates...")
|
|
238
|
-
|
|
239
|
+
# Classification compares the two branches; an update whose branches did not
|
|
240
|
+
# resolve cannot be inspected. Report it as meaningful rather than dropping
|
|
241
|
+
# it — an unexamined bump is not evidence of a sync-only one.
|
|
242
|
+
classifiable = [
|
|
243
|
+
d for d in dep_changes["updated"] if d.get("from_branch_id") and d.get("to_branch_id")
|
|
244
|
+
]
|
|
245
|
+
unclassifiable = [d for d in dep_changes["updated"] if d not in classifiable]
|
|
246
|
+
meaningful_deps, sync_only_deps = classify_dependencies(client, classifiable)
|
|
247
|
+
meaningful_deps.extend(unclassifiable)
|
|
239
248
|
|
|
240
249
|
if include_sync:
|
|
241
250
|
# Move sync-only deps into meaningful list
|