mammoth-cli 2.2.53__tar.gz → 2.2.54__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.
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/PKG-INFO +2 -2
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/__init__.py +1 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/__main__.py +9 -2
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/app.py +52 -3
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +2 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/auth.py +67 -16
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/client_app.py +34 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/dashboard.py +2 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/project.py +20 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/registry.py +6 -7
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/schema.py +6 -3
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/upgrade.py +1 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/view.py +59 -14
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/view_ops.py +85 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/context/credentials.py +13 -3
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/context/oauth.py +7 -2
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/context/resolver.py +3 -3
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/errors/envelope.py +1 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/confirm.py +7 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/executor.py +1 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/updates.py +37 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/verify.py +2 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/argspec.py +26 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/coerce.py +7 -5
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/command_contract.py +32 -27
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/dispatch.py +13 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/mapping.py +8 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/sdk_service.py +2 -1
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/type_system.py +14 -10
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/pyproject.toml +6 -4
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/view.yaml +8 -8
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/.gitignore +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/LICENSE +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/README.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/calc.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-style.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-template.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/link.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/resolve.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/token.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/database-import.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/activity.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/addon.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/agent.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/ai.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/annotation.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/automation.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/batch.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/billing.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/browse.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/calc.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/capability.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/completion.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/config.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/connector.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/context.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/data_app.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/dataset.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/doctor.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/external_key.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/file.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/folder.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/job.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/link.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/notification.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/parameter.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/report.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/resolve.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/schedule.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/skill.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/snippet.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/support.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/template.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/trash.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/user.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/view_profile.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/webhook.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/workflow.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/commands/workspace.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/context/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/context/endpoint.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/context/profiles.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/contracts/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/contracts/auth.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/embed.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/errors/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/manifest/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/manifest/loader.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/messages/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/output/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/output/envelope.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/output/normalize.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/output/policy.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/output/progress.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/output/render.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/py.typed +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/dataset_health.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/dryrun.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/dryrun_targets.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/embedded.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/input_loader.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/intent_only.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/invocation.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/locked_files.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/new_data.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/options.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/parents.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/runlog.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/session.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/state.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/strict.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/runtime/validate.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/append_blank_columns.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/board_values.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/conditional_format.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/conditions.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/dashboard_filters.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/dashboard_pages.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/dashboard_review.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/data_profile.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/data_quality.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/factory.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/input_fields.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/job_outcome.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/listing.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/local_time.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/openapi_types.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/positionals.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/protocol.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/read_queries.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/sql_check.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/stored_stats.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/testing.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/text_dates.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/view_analysis.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/view_variants.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/services/write_impact.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/skills/__init__.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/skills/installer.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/skills/steering.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/mammoth_cli/testing.py +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/activity.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/addon.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/agent.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/ai.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/annotation.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/auth.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/automation.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/batch.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/billing.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/browse.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/calc.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/capability.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/client-app.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/completion.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/config.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/connector.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/context.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/dashboard.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/data-app.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/dataset.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/doctor.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/external-key.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/file.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/folder.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/job.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/link.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/log.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/notification.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/parameter.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/project.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/report.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/resolve.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/schedule.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/schema.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/skill.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/snippet.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/support.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/template.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/token.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/trash.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/upgrade.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/user.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/version.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/webhook.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/workflow.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/commands/workspace.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/edits-target.source.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/openapi-operations.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/schema-v1.json +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/sdk-catalog.source.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/manifests/sdk-methods.yaml +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/openapi/metadata.json +0 -0
- {mammoth_cli-2.2.53 → mammoth_cli-2.2.54}/spec/openapi/openapi.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mammoth-cli
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.54
|
|
4
4
|
Summary: Command-line interface for the Mammoth Analytics platform
|
|
5
5
|
Project-URL: homepage, https://mammoth.io
|
|
6
6
|
Project-URL: repository, https://github.com/EdgeMetric/mammothsdk
|
|
@@ -17,7 +17,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
17
17
|
Requires-Python: <3.15,>=3.12
|
|
18
18
|
Requires-Dist: jsonschema>=4.20
|
|
19
19
|
Requires-Dist: keyring<26,>=25.7
|
|
20
|
-
Requires-Dist: mammoth-io<0.9,>=0.8.
|
|
20
|
+
Requires-Dist: mammoth-io<0.9,>=0.8.28
|
|
21
21
|
Requires-Dist: platformdirs<5,>=4.10
|
|
22
22
|
Requires-Dist: pydantic<3,>=2.12.5
|
|
23
23
|
Requires-Dist: pyyaml<7,>=6
|
|
@@ -8,10 +8,9 @@ launch symbol that does not change when the application wiring moves.
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
import sys
|
|
11
12
|
from typing import Any
|
|
12
13
|
|
|
13
|
-
from mammoth_cli.app import app
|
|
14
|
-
|
|
15
14
|
|
|
16
15
|
def main() -> Any:
|
|
17
16
|
"""Run the Mammoth CLI application.
|
|
@@ -20,6 +19,14 @@ def main() -> Any:
|
|
|
20
19
|
The value returned by the Typer application, which the runtime uses as
|
|
21
20
|
the process exit code.
|
|
22
21
|
"""
|
|
22
|
+
if sys.argv[1:] == ["--version"]:
|
|
23
|
+
# The answer needs none of the command tree; skip building it.
|
|
24
|
+
from mammoth_cli import __version__
|
|
25
|
+
|
|
26
|
+
sys.stdout.write(f"{__version__}\n")
|
|
27
|
+
return 0
|
|
28
|
+
from mammoth_cli.app import app
|
|
29
|
+
|
|
23
30
|
return app()
|
|
24
31
|
|
|
25
32
|
|
|
@@ -19,6 +19,7 @@ import re
|
|
|
19
19
|
import sys
|
|
20
20
|
from collections.abc import Callable, Sequence
|
|
21
21
|
from dataclasses import replace
|
|
22
|
+
from difflib import get_close_matches
|
|
22
23
|
from functools import cache
|
|
23
24
|
from typing import Annotated, Any
|
|
24
25
|
|
|
@@ -383,9 +384,33 @@ class _EnvelopeGroup(TyperGroup):
|
|
|
383
384
|
def get_command(self, ctx: Any, cmd_name: str) -> Any:
|
|
384
385
|
eager: dict[str, Any] = self.__dict__.setdefault("_eager_commands", {})
|
|
385
386
|
if cmd_name not in eager and cmd_name in _LAZY_GROUP_NAMES:
|
|
387
|
+
if self.__dict__.get("_listing_help"):
|
|
388
|
+
return _group_stub(cmd_name)
|
|
386
389
|
eager[cmd_name] = _load_top_level_group(cmd_name)
|
|
387
390
|
return eager.get(cmd_name)
|
|
388
391
|
|
|
392
|
+
def resolve_command(self, ctx: Any, args: list[str]) -> Any:
|
|
393
|
+
# Typer's override suggests close names from ``self.commands``, which
|
|
394
|
+
# builds every group; the names alone are all a suggestion needs.
|
|
395
|
+
try:
|
|
396
|
+
return self._click_resolve_command(ctx, args)
|
|
397
|
+
except _typer_click_exceptions.UsageError as error:
|
|
398
|
+
if self.suggest_commands and args:
|
|
399
|
+
matches = get_close_matches(args[0], self.list_commands(ctx))
|
|
400
|
+
if matches:
|
|
401
|
+
suggestions = ", ".join(f"{m!r}" for m in matches)
|
|
402
|
+
error.message = f"{error.message.rstrip('.')}. Did you mean {suggestions}?"
|
|
403
|
+
raise
|
|
404
|
+
|
|
405
|
+
def format_help(self, ctx: Any, formatter: Any) -> None:
|
|
406
|
+
# Root ``--help`` only needs each group's name, panel and one-line
|
|
407
|
+
# description; building all ~550 commands to print them cost seconds.
|
|
408
|
+
self.__dict__["_listing_help"] = True
|
|
409
|
+
try:
|
|
410
|
+
super().format_help(ctx, formatter)
|
|
411
|
+
finally:
|
|
412
|
+
self.__dict__["_listing_help"] = False
|
|
413
|
+
|
|
389
414
|
def main(self, *args: Any, **kwargs: Any) -> Any:
|
|
390
415
|
if not kwargs.get("standalone_mode", True):
|
|
391
416
|
return super().main(*args, **kwargs)
|
|
@@ -447,11 +472,16 @@ class _EnvelopeGroup(TyperGroup):
|
|
|
447
472
|
)
|
|
448
473
|
elif isinstance(error, _typer_click_exceptions.NoSuchOption):
|
|
449
474
|
option = getattr(error, "option_name", None) or "unknown"
|
|
475
|
+
close = getattr(error, "possibilities", None) or []
|
|
450
476
|
report = CliError(
|
|
451
477
|
code="unknown_option",
|
|
452
478
|
message=f"Unknown option '{option}'.",
|
|
453
479
|
exit_status=EXIT_USAGE,
|
|
454
|
-
hint=
|
|
480
|
+
hint=(
|
|
481
|
+
f"Did you mean {' or '.join(sorted(close))}?"
|
|
482
|
+
if close
|
|
483
|
+
else "Check the command schema with 'mammoth schema get'."
|
|
484
|
+
),
|
|
455
485
|
details={"option": option},
|
|
456
486
|
)
|
|
457
487
|
elif isinstance(error, _typer_click_exceptions.BadParameter):
|
|
@@ -1032,6 +1062,15 @@ def _command_tree() -> tuple[dict[tuple[str, ...], str], frozenset[tuple[str, ..
|
|
|
1032
1062
|
return path_to_command, frozenset(prefixes & path_to_command.keys())
|
|
1033
1063
|
|
|
1034
1064
|
|
|
1065
|
+
def _leaf_context_settings(command_id: str) -> dict[str, bool]:
|
|
1066
|
+
"""Click settings for one command: a bespoke command declares every option it
|
|
1067
|
+
accepts, so Click itself rejects an unknown one; a generic leaf collects its
|
|
1068
|
+
trailing tokens and validates them in :func:`validate_extra_args`."""
|
|
1069
|
+
if command_id in BESPOKE:
|
|
1070
|
+
return {}
|
|
1071
|
+
return {"allow_extra_args": True, "ignore_unknown_options": True}
|
|
1072
|
+
|
|
1073
|
+
|
|
1035
1074
|
def _group_typer(tokens: tuple[str, ...], command_id: str | None) -> typer.Typer:
|
|
1036
1075
|
if command_id is not None:
|
|
1037
1076
|
# This node is both a group and an invocable command.
|
|
@@ -1088,7 +1127,7 @@ def _populate(base: tuple[str, ...], group: typer.Typer) -> None:
|
|
|
1088
1127
|
name=tokens[-1],
|
|
1089
1128
|
help=_command_help(command_id, record),
|
|
1090
1129
|
rich_help_panel=_ROOT_HELP_PANELS.get(tokens[0]) if len(tokens) == 1 else None,
|
|
1091
|
-
context_settings=
|
|
1130
|
+
context_settings=_leaf_context_settings(command_id),
|
|
1092
1131
|
)(callback)
|
|
1093
1132
|
|
|
1094
1133
|
|
|
@@ -1121,6 +1160,16 @@ def _load_top_level_group(name: str) -> Any:
|
|
|
1121
1160
|
return typer.main.get_group_from_info(info, **_LAZY_SETTINGS)
|
|
1122
1161
|
|
|
1123
1162
|
|
|
1163
|
+
def _group_stub(name: str) -> Any:
|
|
1164
|
+
"""A placeholder group carrying only what the root ``--help`` listing prints."""
|
|
1165
|
+
return TyperGroup(
|
|
1166
|
+
name=name,
|
|
1167
|
+
help=_GROUP_DESCRIPTIONS.get(name, f"Commands for {name}."),
|
|
1168
|
+
rich_help_panel=_ROOT_HELP_PANELS.get(name),
|
|
1169
|
+
rich_markup_mode=_LAZY_SETTINGS["rich_markup_mode"],
|
|
1170
|
+
)
|
|
1171
|
+
|
|
1172
|
+
|
|
1124
1173
|
def build_app() -> typer.Typer:
|
|
1125
1174
|
"""Construct the Typer command tree from the command manifests.
|
|
1126
1175
|
|
|
@@ -1160,7 +1209,7 @@ def build_app() -> typer.Typer:
|
|
|
1160
1209
|
name=name,
|
|
1161
1210
|
help=_command_help(command_id, command_by_id(command_id)),
|
|
1162
1211
|
rich_help_panel=_ROOT_HELP_PANELS.get(name),
|
|
1163
|
-
context_settings=
|
|
1212
|
+
context_settings=_leaf_context_settings(command_id),
|
|
1164
1213
|
)(BESPOKE.get(command_id) or _build_leaf(command_id))
|
|
1165
1214
|
_LAZY_GROUP_NAMES[:] = lazy
|
|
1166
1215
|
_LAZY_SETTINGS.update(
|
|
@@ -312,6 +312,8 @@ Result: `ViewDerivativeCreateResult`; mutation `benign_mutation`, confirmation `
|
|
|
312
312
|
|
|
313
313
|
Status on release: ran once on CLI 2.0.24 — payload probe 2026-09-19: exit 0 on release with CLI 2.0.24. Created derivative id=6 on view 123 (project 52, dataset 104) with the column INTERNAL name as ARGUMENT; metric_status DONE on read-back. The same call with the display name reproduces the HTTP 500…
|
|
314
314
|
|
|
315
|
+
A METRIC shows as an explore-panel card via `display_properties`; the CLI defaults it to the metric card, and the result's `card` says whether one exists.
|
|
316
|
+
|
|
315
317
|
### `view.derivative.data`
|
|
316
318
|
|
|
317
319
|
Run: `mammoth view derivative data`. Exact input fields: `mammoth schema get view.derivative.data`.
|
|
@@ -23,7 +23,7 @@ import typer
|
|
|
23
23
|
from pydantic import ValidationError
|
|
24
24
|
|
|
25
25
|
from mammoth_cli.context import credentials, oauth, profiles, resolver
|
|
26
|
-
from mammoth_cli.context.endpoint import resolve_base_url
|
|
26
|
+
from mammoth_cli.context.endpoint import DEFAULT_SERVER_PREFIX, resolve_base_url
|
|
27
27
|
from mammoth_cli.context.resolver import ResolvedAuth, resolve_auth
|
|
28
28
|
from mammoth_cli.contracts.auth import LoginRequest
|
|
29
29
|
from mammoth_cli.errors.envelope import (
|
|
@@ -143,6 +143,14 @@ def _masked_receipt(value: str) -> str:
|
|
|
143
143
|
return f"{len(value)} characters, ending in …{value[-4:]}"
|
|
144
144
|
|
|
145
145
|
|
|
146
|
+
def _ask(label: str, **options: Any) -> str:
|
|
147
|
+
"""Prompt once; a closed stdin (Ctrl-D, EOF) is a usage error, not a crash."""
|
|
148
|
+
try:
|
|
149
|
+
return str(typer.prompt(label, **options))
|
|
150
|
+
except typer.Abort:
|
|
151
|
+
raise _no_choice(label) from None
|
|
152
|
+
|
|
153
|
+
|
|
146
154
|
def _prompt_secret(label: str) -> str:
|
|
147
155
|
"""Prompt for one secret with hidden input, then confirm what was captured.
|
|
148
156
|
|
|
@@ -152,7 +160,7 @@ def _prompt_secret(label: str) -> str:
|
|
|
152
160
|
entry is rejected here, and a masked receipt (length and last four
|
|
153
161
|
characters, never the value) is printed to stderr as feedback.
|
|
154
162
|
"""
|
|
155
|
-
value =
|
|
163
|
+
value = _ask(label, hide_input=True).strip()
|
|
156
164
|
if not value:
|
|
157
165
|
raise CliError(
|
|
158
166
|
code="login_input_required",
|
|
@@ -298,22 +306,65 @@ def _choose_method(
|
|
|
298
306
|
return method
|
|
299
307
|
if invocation.input_file is not None or blockers:
|
|
300
308
|
return "token"
|
|
301
|
-
|
|
302
|
-
|
|
309
|
+
available = oauth.has_client_id(server_prefix)
|
|
310
|
+
prefix = server_prefix if server_prefix is not None else DEFAULT_SERVER_PREFIX
|
|
311
|
+
browser_note = "recommended" if available else f"(not yet available on {prefix})"
|
|
312
|
+
device_note = "no browser on this machine" if available else browser_note
|
|
303
313
|
typer.echo("How do you want to sign in?", err=True)
|
|
304
|
-
typer.echo(" 1) Browser (OAuth)
|
|
305
|
-
typer.echo(" 2) Device code
|
|
314
|
+
typer.echo(f" 1) Browser (OAuth) {browser_note}", err=True)
|
|
315
|
+
typer.echo(f" 2) Device code {device_note}", err=True)
|
|
306
316
|
typer.echo(" 3) Paste an API token for CI and scripts", err=True)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
+
default = "1" if available else "3"
|
|
318
|
+
if sys.stdin.isatty():
|
|
319
|
+
return _choose_by_keypress(default)
|
|
320
|
+
choice = _ask("Choose", default=default, show_default=False).strip()
|
|
321
|
+
if choice not in _METHOD_KEYS:
|
|
322
|
+
raise _bad_choice(choice)
|
|
323
|
+
return _METHOD_KEYS[choice]
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
_METHOD_KEYS = {"1": "oauth", "2": "device", "3": "token"}
|
|
327
|
+
_METHOD_LABELS = {"1": "Browser (OAuth)", "2": "Device code", "3": "API token"}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _bad_choice(choice: str) -> CliError:
|
|
331
|
+
return CliError(
|
|
332
|
+
code="invalid_login_method",
|
|
333
|
+
message=f"'{choice}' is not one of the choices.",
|
|
334
|
+
exit_status=EXIT_USAGE,
|
|
335
|
+
hint="Enter 1 for the browser, 2 for a device code or 3 to paste an API token.",
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def _choose_by_keypress(default: str) -> str:
|
|
340
|
+
"""Read one key on a terminal: 1, 2 or 3 selects at once, Enter takes ``default``.
|
|
341
|
+
|
|
342
|
+
Any other key asks once more, then errors; Ctrl-C and Ctrl-D are a usage error.
|
|
343
|
+
"""
|
|
344
|
+
key = ""
|
|
345
|
+
for _attempt in range(2):
|
|
346
|
+
typer.echo("Choose: ", nl=False, err=True)
|
|
347
|
+
try:
|
|
348
|
+
key = typer.getchar()
|
|
349
|
+
except (KeyboardInterrupt, EOFError):
|
|
350
|
+
typer.echo("", err=True)
|
|
351
|
+
raise _no_choice() from None
|
|
352
|
+
if key in ("\r", "\n"):
|
|
353
|
+
key = default
|
|
354
|
+
if key in _METHOD_KEYS:
|
|
355
|
+
typer.echo(f"{key} {_METHOD_LABELS[key]}", err=True)
|
|
356
|
+
return _METHOD_KEYS[key]
|
|
357
|
+
typer.echo("", err=True)
|
|
358
|
+
raise _bad_choice(key)
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def _no_choice(label: str = "choice") -> CliError:
|
|
362
|
+
return CliError(
|
|
363
|
+
code="login_input_required",
|
|
364
|
+
message=f"No {label} was entered.",
|
|
365
|
+
exit_status=EXIT_USAGE,
|
|
366
|
+
hint="Pass --method oauth|device|token, or --input FILE for a non-interactive login.",
|
|
367
|
+
)
|
|
317
368
|
|
|
318
369
|
|
|
319
370
|
def _iso(epoch: int) -> str:
|
|
@@ -22,10 +22,13 @@ from typing import Any
|
|
|
22
22
|
|
|
23
23
|
from mammoth.exceptions import MammothModelDriftWarning
|
|
24
24
|
|
|
25
|
+
from mammoth_cli.context import credentials, oauth, profiles
|
|
26
|
+
from mammoth_cli.context.endpoint import resolve_base_url
|
|
25
27
|
from mammoth_cli.errors.envelope import (
|
|
26
28
|
CODE_MISSING_ARGUMENT,
|
|
27
29
|
CODE_MISSING_FIELD,
|
|
28
30
|
CODE_SDK_SYMBOL_UNRESOLVED,
|
|
31
|
+
EXIT_API,
|
|
29
32
|
EXIT_USAGE,
|
|
30
33
|
CliError,
|
|
31
34
|
)
|
|
@@ -254,6 +257,37 @@ def client_app_delete(invocation: Invocation) -> HandlerResult:
|
|
|
254
257
|
enforce_confirmation(
|
|
255
258
|
invocation, policy=POLICY_PROMPT_OR_YES, action=f"delete client app {client_key}"
|
|
256
259
|
)
|
|
260
|
+
own = _own_oauth_session(invocation, client_key)
|
|
261
|
+
if own is not None:
|
|
262
|
+
return _revoke_own_grant(invocation, own)
|
|
257
263
|
with open_service(invocation) as (service, auth):
|
|
258
264
|
data = service.call(_symbol(invocation), client_key=client_key)
|
|
259
265
|
return data, _meta(invocation, auth.workspace_id, resolved_project(invocation))
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _own_oauth_session(invocation: Invocation, client_key: str) -> credentials.OAuthSession | None:
|
|
269
|
+
"""The caller's browser-login session when ``client_key`` is the client it signed in as."""
|
|
270
|
+
credential = credentials.load_credential(invocation.profile or profiles.get_selected())
|
|
271
|
+
session = credential.oauth if credential is not None else None
|
|
272
|
+
return session if session is not None and session.client_id == client_key else None
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _revoke_own_grant(invocation: Invocation, session: credentials.OAuthSession) -> HandlerResult:
|
|
276
|
+
"""Disconnect the caller's own grant: the workspace client-app route does not know it."""
|
|
277
|
+
profile_name = invocation.profile or profiles.get_selected()
|
|
278
|
+
record = profiles.get_profile(profile_name)
|
|
279
|
+
if record is None:
|
|
280
|
+
raise CliError(
|
|
281
|
+
code=CODE_MISSING_ARGUMENT,
|
|
282
|
+
message=f"Profile {profile_name} is not configured.",
|
|
283
|
+
exit_status=EXIT_USAGE,
|
|
284
|
+
)
|
|
285
|
+
base_url = resolve_base_url(record.server_prefix)
|
|
286
|
+
if not oauth.is_fresh(session):
|
|
287
|
+
session = oauth.refresh_session(profile_name, base_url)
|
|
288
|
+
problem = oauth.revoke_grant(base_url, session)
|
|
289
|
+
if problem is not None:
|
|
290
|
+
raise CliError(code="oauth_grant_revoke_failed", message=problem, exit_status=EXIT_API)
|
|
291
|
+
return {"revoked": "own OAuth grant", "grant_id": session.grant_id}, _meta(
|
|
292
|
+
invocation, record.workspace_id, resolved_project(invocation)
|
|
293
|
+
)
|
|
@@ -14,7 +14,6 @@ from collections.abc import Callable
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Any, Literal, cast
|
|
16
16
|
|
|
17
|
-
from mammoth.models.dashboards import AddPagesSpec
|
|
18
17
|
from pydantic import ValidationError
|
|
19
18
|
|
|
20
19
|
from mammoth_cli.commands.view import _FIND_DATASET_SYMBOL, view_profiles
|
|
@@ -733,6 +732,8 @@ def generated_dashboard(invocation: Invocation) -> HandlerResult:
|
|
|
733
732
|
# AddPages has a release-level minItems constraint that must be enforced
|
|
734
733
|
# before confirmation or transport.
|
|
735
734
|
if invocation.command_id == "dashboard.pages.add" and "body" in kwargs:
|
|
735
|
+
from mammoth.models.dashboards import AddPagesSpec
|
|
736
|
+
|
|
736
737
|
try:
|
|
737
738
|
kwargs["body"] = AddPagesSpec.model_validate(kwargs["body"]).model_dump(
|
|
738
739
|
mode="json", exclude_none=True
|
|
@@ -134,11 +134,25 @@ def project_list(invocation: Invocation) -> HandlerResult:
|
|
|
134
134
|
return data, _meta(invocation, auth.workspace_id, resolved_project(invocation))
|
|
135
135
|
|
|
136
136
|
|
|
137
|
+
#: What ``project get`` reads: the project's own record, not what it holds.
|
|
138
|
+
_PROJECT_GET_COVERS = (
|
|
139
|
+
"the project's id and name only; its datasets and views are not counted here "
|
|
140
|
+
"(mammoth dataset list --project {project_id})"
|
|
141
|
+
)
|
|
142
|
+
#: What ``project resource-status`` reads: only work happening right now.
|
|
143
|
+
_RESOURCE_STATUS_COVERS = (
|
|
144
|
+
"resources with a task in flight right now; empty in_flight does not mean the project has "
|
|
145
|
+
"no resources (mammoth dataset list --project {project_id})"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
137
149
|
def project_get(invocation: Invocation) -> HandlerResult:
|
|
138
150
|
"""Get one project by id (positional or active project)."""
|
|
139
151
|
project_id = _project_id(invocation)
|
|
140
152
|
with open_service(invocation) as (service, auth):
|
|
141
153
|
data = service.call(_symbol(invocation), project=project_id)
|
|
154
|
+
if isinstance(data, dict):
|
|
155
|
+
data = {**data, "covers": _PROJECT_GET_COVERS.format(project_id=project_id)}
|
|
142
156
|
return data, _meta(invocation, auth.workspace_id, project_id)
|
|
143
157
|
|
|
144
158
|
|
|
@@ -185,10 +199,15 @@ def project_memory_remove(invocation: Invocation) -> HandlerResult:
|
|
|
185
199
|
|
|
186
200
|
|
|
187
201
|
def project_resource_status(invocation: Invocation) -> HandlerResult:
|
|
188
|
-
"""Report the
|
|
202
|
+
"""Report the project's in-flight resource tasks, named as such."""
|
|
189
203
|
project_id = _project_id(invocation)
|
|
190
204
|
with open_service(invocation) as (service, auth):
|
|
191
205
|
data = service.call(_symbol(invocation), project_id=project_id)
|
|
206
|
+
in_flight = data.get("status") if isinstance(data, dict) else None
|
|
207
|
+
data = {
|
|
208
|
+
"in_flight": in_flight if in_flight is not None else {},
|
|
209
|
+
"covers": _RESOURCE_STATUS_COVERS.format(project_id=project_id),
|
|
210
|
+
}
|
|
192
211
|
return data, _meta(invocation, auth.workspace_id, project_id)
|
|
193
212
|
|
|
194
213
|
|
|
@@ -898,12 +898,11 @@ HANDLERS: dict[str, Handler] = {
|
|
|
898
898
|
}
|
|
899
899
|
|
|
900
900
|
# Dashboard operations generated from the reviewed OpenAPI inventory share one
|
|
901
|
-
# manifest-driven handler. Existing authored handlers remain authoritative
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
}
|
|
901
|
+
# manifest-driven handler. Existing authored handlers remain authoritative, so
|
|
902
|
+
# ``setdefault`` only fills the dashboard commands that have none. Matching on
|
|
903
|
+
# the SDK symbol prefix (rather than importing the generated method list) keeps
|
|
904
|
+
# the generated dashboard models off the startup import path.
|
|
905
|
+
_DASHBOARD_SDK_PREFIX = "mammoth.api.dashboards.DashboardsAPI."
|
|
907
906
|
for _record in load_commands():
|
|
908
|
-
if _record.get("sdk_symbol")
|
|
907
|
+
if str(_record.get("sdk_symbol", "")).startswith(_DASHBOARD_SDK_PREFIX):
|
|
909
908
|
HANDLERS.setdefault(str(_record["command_id"]), dashboard_cmd.generated_dashboard)
|
|
@@ -337,8 +337,8 @@ _COMMAND_DISCOVERY_PURPOSES = {
|
|
|
337
337
|
"window rank row number running total cumulative sum moving average lag lead "
|
|
338
338
|
"previous next row partition"
|
|
339
339
|
),
|
|
340
|
-
#
|
|
341
|
-
# spread, its top values, a count over time.
|
|
340
|
+
# Reads a column's value distribution: what is trending, how a column is
|
|
341
|
+
# spread, its top values, a count over time. It opens no card in the UI.
|
|
342
342
|
"view.data.explore": (
|
|
343
343
|
"explore trend trends trending over time per day week month quarter year by date "
|
|
344
344
|
"distribution spread histogram top most common frequent values breakdown share "
|
|
@@ -572,7 +572,10 @@ _COMMAND_DISCOVERY_PURPOSES = {
|
|
|
572
572
|
"condition checkpoint value changes"
|
|
573
573
|
),
|
|
574
574
|
"view.data-check.create": "data quality check rule validate rows match condition flag",
|
|
575
|
-
"view.derivative.create":
|
|
575
|
+
"view.derivative.create": (
|
|
576
|
+
"metric kpi number single value to check track daily monitor add a metric "
|
|
577
|
+
"sum of column explore panel card metric card"
|
|
578
|
+
),
|
|
576
579
|
"view.draft.auto-run": (
|
|
577
580
|
"stop prevent re-running rerun automatically when source changes auto run enable disable"
|
|
578
581
|
),
|
|
@@ -361,6 +361,7 @@ def perform(invocation: Invocation, *, check: bool, target_version: str | None)
|
|
|
361
361
|
invocation,
|
|
362
362
|
policy=POLICY_PROMPT_OR_YES,
|
|
363
363
|
action=f"upgrade {PACKAGE_NAME} to {action_target} using {manager}",
|
|
364
|
+
default=True,
|
|
364
365
|
)
|
|
365
366
|
result = run_upgrade(command)
|
|
366
367
|
if result.returncode != 0:
|
|
@@ -29,9 +29,6 @@ from datetime import UTC, datetime
|
|
|
29
29
|
from decimal import Decimal, InvalidOperation
|
|
30
30
|
from typing import Any
|
|
31
31
|
|
|
32
|
-
from mammoth.models.exports import ExportStatus
|
|
33
|
-
from mammoth.view import ViewExport
|
|
34
|
-
|
|
35
32
|
from mammoth_cli.context import profiles
|
|
36
33
|
from mammoth_cli.errors.envelope import (
|
|
37
34
|
CODE_INVALID_ARGUMENT,
|
|
@@ -86,6 +83,7 @@ _DATASET_GET_SYMBOL = "mammoth.api.datasets.DatasetsAPI.get"
|
|
|
86
83
|
# data-read commands can take the view id alone and fill the dataset for the
|
|
87
84
|
# caller. See :data:`mammoth_cli.services.positionals.POSITIONAL_OVERRIDES`.
|
|
88
85
|
_FIND_DATASET_SYMBOL = "mammoth.api.pipeline.PipelineAPI.find_dataset_for_dataview"
|
|
86
|
+
_EXPLORE_PANEL_GET_SYMBOL = "mammoth.api.dataviews.DataviewsAPI.explore_panel"
|
|
89
87
|
_WAIT_FOR_PIPELINE_SYMBOL = "mammoth.api.pipeline.PipelineAPI.wait_for_pipeline"
|
|
90
88
|
_DATASET_ID_FIELD = "dataset_id"
|
|
91
89
|
_DRAFT_OPERATIONS = frozenset({"enter", "exit", "submit", "discard"})
|
|
@@ -368,6 +366,9 @@ def _read_meta(
|
|
|
368
366
|
project_id=project_id,
|
|
369
367
|
fields="__min",
|
|
370
368
|
)
|
|
369
|
+
# The read just proved this dataset holds the view; keep the pair so the
|
|
370
|
+
# next command on it (a transform) needs no ``dataset_id`` of its own.
|
|
371
|
+
parents.remember(_profile_name(invocation), workspace_id, {view_id: dataset_id})
|
|
371
372
|
dataset = service.call(
|
|
372
373
|
_DATASET_GET_SYMBOL, dataset_id=dataset_id, project_id=project_id, fields="id,name"
|
|
373
374
|
)
|
|
@@ -1115,6 +1116,15 @@ def view_update(invocation: Invocation) -> HandlerResult:
|
|
|
1115
1116
|
return data, _meta(invocation, auth.workspace_id, project_id)
|
|
1116
1117
|
|
|
1117
1118
|
|
|
1119
|
+
def _read_explore_panel(
|
|
1120
|
+
service: Any, symbol: str, dataset_id: int, dataview_id: int, project_id: int
|
|
1121
|
+
) -> Any:
|
|
1122
|
+
"""The Explore panel the caller saved on a view (``{}`` when none is saved)."""
|
|
1123
|
+
return service.call(
|
|
1124
|
+
symbol, dataset_id=dataset_id, dataview_id=dataview_id, project_id=project_id
|
|
1125
|
+
)
|
|
1126
|
+
|
|
1127
|
+
|
|
1118
1128
|
def view_explore_panel_get(invocation: Invocation) -> HandlerResult:
|
|
1119
1129
|
"""Read the Explore panel the caller saved on a view (empty when none is saved)."""
|
|
1120
1130
|
project_id = require_project(invocation)
|
|
@@ -1122,17 +1132,14 @@ def view_explore_panel_get(invocation: Invocation) -> HandlerResult:
|
|
|
1122
1132
|
document = invocation.load_input() or {}
|
|
1123
1133
|
with open_service(invocation) as (service, auth):
|
|
1124
1134
|
dataset_id = _resolve_dataset_id(service, invocation, dataview_id, document)
|
|
1125
|
-
data =
|
|
1126
|
-
_symbol(invocation),
|
|
1127
|
-
dataset_id=dataset_id,
|
|
1128
|
-
dataview_id=dataview_id,
|
|
1129
|
-
project_id=project_id,
|
|
1135
|
+
data = _read_explore_panel(
|
|
1136
|
+
service, _symbol(invocation), dataset_id, dataview_id, project_id
|
|
1130
1137
|
)
|
|
1131
1138
|
return data, _meta(invocation, auth.workspace_id, project_id)
|
|
1132
1139
|
|
|
1133
1140
|
|
|
1134
1141
|
def view_explore_panel_set(invocation: Invocation) -> HandlerResult:
|
|
1135
|
-
"""Replace the caller's saved Explore panel
|
|
1142
|
+
"""Replace the caller's saved Explore panel; the result carries the panel read back after."""
|
|
1136
1143
|
project_id = require_project(invocation)
|
|
1137
1144
|
dataview_id = _require_int_positional_at(invocation, 0, "view id")
|
|
1138
1145
|
document = invocation.load_input() or {}
|
|
@@ -1146,7 +1153,10 @@ def view_explore_panel_set(invocation: Invocation) -> HandlerResult:
|
|
|
1146
1153
|
panel=panel,
|
|
1147
1154
|
project_id=project_id,
|
|
1148
1155
|
)
|
|
1149
|
-
|
|
1156
|
+
saved = _read_explore_panel(
|
|
1157
|
+
service, _EXPLORE_PANEL_GET_SYMBOL, dataset_id, dataview_id, project_id
|
|
1158
|
+
)
|
|
1159
|
+
return {**data, "panel": saved}, _meta(invocation, auth.workspace_id, project_id)
|
|
1150
1160
|
|
|
1151
1161
|
|
|
1152
1162
|
def _untyped_patch_error(invocation: Invocation) -> CliError:
|
|
@@ -2204,7 +2214,7 @@ def _explore_range(
|
|
|
2204
2214
|
|
|
2205
2215
|
|
|
2206
2216
|
def view_data_explore(invocation: Invocation) -> HandlerResult:
|
|
2207
|
-
"""
|
|
2217
|
+
"""Read one column's value distribution (read-only; opens and changes no card in the UI, that is ``view explore-panel set``): DATE counts per ``level`` bucket (AUTO, SECOND to MILLENNIUM), NUMERIC per power-of-10 ``level``, TEXT top values (``limit`` 20), each with ``count`` and ``percentage``; ``metric`` (a column plus SUM/AVG/MIN/MAX/STDDEV/COUNT/DISTINCT_COUNT) adds a per-bucket value, ``percentage_of`` "metric" shares by it, ``sort`` count_/value_/metric_ + asc/desc, ``condition`` filters first (include, exclude, blanks, range, contains; an exclude drops blank rows the card keeps, so or it with IS_EMPTY; drill down = finer ``level`` + ``condition`` on the bucket), ``limit``/``offset`` page, ``range`` true adds the exact earliest and latest value, ``cumulative`` a running total; ``-o csv`` saves the values; to put it on a dashboard say it in words to 'dashboard chat edit'.
|
|
2208
2218
|
|
|
2209
2219
|
Read-only: computes and returns the result without adding a task to the
|
|
2210
2220
|
view's pipeline or otherwise changing it. Buckets by the column's type --
|
|
@@ -2759,12 +2769,40 @@ def view_data_check_update(invocation: Invocation) -> HandlerResult:
|
|
|
2759
2769
|
# ---------------------------------------------------------------------------
|
|
2760
2770
|
|
|
2761
2771
|
|
|
2772
|
+
_METRIC_CARD_BASE: dict[str, Any] = {
|
|
2773
|
+
"FORMAT_INFO": {"RESULT": {}},
|
|
2774
|
+
"IS_FORMAT_INFO_DIRTY": False,
|
|
2775
|
+
"LOCKED": False,
|
|
2776
|
+
"type": "metric",
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
def _with_metric_card(body: Any) -> Any:
|
|
2781
|
+
"""Default a METRIC derivative's ``display_properties`` to its explore-panel card.
|
|
2782
|
+
|
|
2783
|
+
Without it the API stores ``display_properties: null``, which the explore
|
|
2784
|
+
panel reads as "no card". An explicit value (including ``{}``) is kept.
|
|
2785
|
+
"""
|
|
2786
|
+
param = body.get("param") if isinstance(body, dict) else None
|
|
2787
|
+
metric = param.get("METRIC") if isinstance(param, dict) else None
|
|
2788
|
+
if not isinstance(metric, dict) or body.get("display_properties") is not None:
|
|
2789
|
+
return body
|
|
2790
|
+
return {
|
|
2791
|
+
**body,
|
|
2792
|
+
"display_properties": {**_METRIC_CARD_BASE, "info": {"title": metric.get("AS")}},
|
|
2793
|
+
}
|
|
2794
|
+
|
|
2795
|
+
|
|
2762
2796
|
def view_derivative_create(invocation: Invocation) -> HandlerResult:
|
|
2763
|
-
"""Create a derivative on a dataview. ``body`` is required.
|
|
2797
|
+
"""Create a derivative on a dataview. ``body`` is required.
|
|
2798
|
+
|
|
2799
|
+
A METRIC with no ``display_properties`` gets the metric card config so it
|
|
2800
|
+
shows in the explore panel; the result's ``card`` says whether a card exists.
|
|
2801
|
+
"""
|
|
2764
2802
|
project_id = require_project(invocation)
|
|
2765
2803
|
dataview_id = _require_int_positional_at(invocation, 0, "view id")
|
|
2766
2804
|
document = invocation.load_input()
|
|
2767
|
-
body = _require_field(document, "body")
|
|
2805
|
+
body = _with_metric_card(_require_field(document, "body"))
|
|
2768
2806
|
assert document is not None
|
|
2769
2807
|
with open_service(invocation) as (service, auth):
|
|
2770
2808
|
dataset_id = _resolve_dataset_id(service, invocation, dataview_id, document)
|
|
@@ -2775,7 +2813,8 @@ def view_derivative_create(invocation: Invocation) -> HandlerResult:
|
|
|
2775
2813
|
body=body,
|
|
2776
2814
|
project_id=project_id,
|
|
2777
2815
|
)
|
|
2778
|
-
|
|
2816
|
+
card = bool(body.get("display_properties")) if isinstance(body, dict) else False
|
|
2817
|
+
return {**data, "card": card}, _meta(invocation, auth.workspace_id, project_id)
|
|
2779
2818
|
|
|
2780
2819
|
|
|
2781
2820
|
def view_derivative_data(invocation: Invocation) -> HandlerResult:
|
|
@@ -3275,6 +3314,8 @@ def _end_of_pipeline_exports(
|
|
|
3275
3314
|
dataset_id=dataset_id,
|
|
3276
3315
|
end_of_pipeline=True,
|
|
3277
3316
|
)
|
|
3317
|
+
from mammoth.models.exports import ExportStatus
|
|
3318
|
+
|
|
3278
3319
|
fired: list[dict[str, Any]] = []
|
|
3279
3320
|
source_columns: Any = None
|
|
3280
3321
|
for export in getattr(listing, "exports", None) or []:
|
|
@@ -3920,6 +3961,8 @@ def view_export_specialized(invocation: Invocation) -> HandlerResult:
|
|
|
3920
3961
|
# reviewed trigger controls may flow through its **kwargs extension point;
|
|
3921
3962
|
# using a union of every destination's fields would silently accept, for
|
|
3922
3963
|
# example, email-only fields on a database export.
|
|
3964
|
+
from mammoth.view import ViewExport
|
|
3965
|
+
|
|
3923
3966
|
signature = inspect.signature(getattr(ViewExport, method))
|
|
3924
3967
|
explicit_fields = {
|
|
3925
3968
|
name
|
|
@@ -4135,6 +4178,8 @@ def _existing_internal_dataset_export(
|
|
|
4135
4178
|
and the list endpoint does not filter on status, so a deleted export
|
|
4136
4179
|
would otherwise block every later export into that target forever.
|
|
4137
4180
|
"""
|
|
4181
|
+
from mammoth.models.exports import ExportStatus
|
|
4182
|
+
|
|
4138
4183
|
listing = service.call(
|
|
4139
4184
|
_EXPORTS_LIST_SYMBOL,
|
|
4140
4185
|
dataview_id=dataview_id,
|