mammoth-cli 2.0.49__tar.gz → 2.0.51__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.0.49 → mammoth_cli-2.0.51}/PKG-INFO +2 -2
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/__init__.py +1 -1
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +1 -1
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/schema.py +9 -1
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/view.py +114 -10
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/command_contract.py +7 -2
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/data_quality.py +42 -3
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/mapping.py +35 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/positionals.py +35 -1
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/type_system.py +24 -1
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/pyproject.toml +2 -2
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/view.yaml +10 -6
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/.gitignore +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/LICENSE +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/README.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/__main__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/app.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/activity.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/addon.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/agent.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/ai.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/annotation.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/auth.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/automation.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/batch.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/billing.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/browse.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/capability.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/client_app.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/completion.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/config.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/connector.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/context.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/dashboard.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/data_app.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/dataset.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/doctor.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/external_key.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/file.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/folder.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/job.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/notification.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/parameter.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/project.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/registry.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/report.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/schedule.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/skill.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/snippet.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/support.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/template.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/trash.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/upgrade.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/user.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/view_ops.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/webhook.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/workflow.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/commands/workspace.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/context/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/context/credentials.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/context/endpoint.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/context/profiles.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/context/resolver.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/contracts/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/contracts/auth.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/embed.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/errors/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/errors/envelope.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/manifest/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/manifest/loader.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/messages/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/output/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/output/envelope.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/output/normalize.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/output/policy.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/output/progress.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/output/render.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/py.typed +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/confirm.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/dryrun.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/embedded.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/executor.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/input_loader.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/invocation.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/options.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/parents.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/runlog.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/session.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/strict.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/updates.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/runtime/validate.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/argspec.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/coerce.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/conditions.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/dashboard_pages.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/dashboard_review.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/dispatch.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/factory.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/input_fields.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/openapi_types.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/protocol.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/sdk_service.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/services/testing.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/skills/__init__.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/skills/installer.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/skills/steering.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/testing.py +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/activity.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/addon.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/agent.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/ai.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/annotation.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/auth.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/automation.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/batch.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/billing.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/browse.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/capability.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/client-app.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/completion.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/config.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/connector.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/context.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/dashboard.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/data-app.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/dataset.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/doctor.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/external-key.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/file.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/folder.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/job.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/log.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/notification.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/parameter.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/project.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/report.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/schedule.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/schema.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/skill.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/snippet.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/support.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/template.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/trash.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/upgrade.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/user.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/version.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/webhook.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/workflow.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/commands/workspace.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/openapi-operations.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/schema-v1.json +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/sdk-catalog.source.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/manifests/sdk-methods.yaml +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/openapi/metadata.json +0 -0
- {mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/spec/openapi/openapi.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mammoth-cli
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.51
|
|
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.8,>=0.7.
|
|
20
|
+
Requires-Dist: mammoth-io<0.8,>=0.7.23
|
|
21
21
|
Requires-Dist: platformdirs<5,>=4.10
|
|
22
22
|
Requires-Dist: pydantic<3,>=2.13
|
|
23
23
|
Requires-Dist: pyyaml<7,>=6
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mammoth-cli
|
|
3
|
-
version: 2.0.
|
|
3
|
+
version: 2.0.51
|
|
4
4
|
description: "Use Mammoth Analytics from a terminal: install or authenticate the CLI, discover its live command contract, and safely manage projects, data, views, pipelines (join, merge, pivot, filter, clean), dashboards, exports, and handoffs."
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -92,6 +92,13 @@ _COMMAND_DISCOVERY_PURPOSES = {
|
|
|
92
92
|
"view.export.sftp": "sftp secure file transfer server",
|
|
93
93
|
"view.export.sharepoint": "share point sharepoint microsoft",
|
|
94
94
|
"view.export.tableau": "tableau server dashboard",
|
|
95
|
+
# "Run"/"execute"/"apply"/"refresh" the pipeline is ambiguous between
|
|
96
|
+
# re-running its tasks and applying a pending draft; both need to surface.
|
|
97
|
+
"view.pipeline.rerun": (
|
|
98
|
+
"run execute rerun re-run refresh recompute apply pipeline tasks "
|
|
99
|
+
"from a point in the task sequence"
|
|
100
|
+
),
|
|
101
|
+
"view.draft.submit": "apply submit run execute a pending draft changes",
|
|
95
102
|
"webhook.create": "webhook http endpoint api push create",
|
|
96
103
|
"webhook.update": "webhook http endpoint api update",
|
|
97
104
|
"webhook.get": "webhook http endpoint api get",
|
|
@@ -142,7 +149,8 @@ _COMMAND_DISCOVERY_PURPOSES = {
|
|
|
142
149
|
"fill missing null empty blank blanks impute carry forward fill down values"
|
|
143
150
|
),
|
|
144
151
|
"view.transform.filter": (
|
|
145
|
-
"filter rows keep drop exclude remove delete rows where condition subset"
|
|
152
|
+
"filter rows keep drop exclude remove delete rows where condition subset "
|
|
153
|
+
"bind bound binding parameter"
|
|
146
154
|
),
|
|
147
155
|
"view.transform.generate-sql": "generate write sql query from natural language intent question",
|
|
148
156
|
"view.transform.increment-date": "add subtract days months years to a date column shift",
|
|
@@ -286,15 +286,39 @@ def brief_view_record(record: Any) -> Any:
|
|
|
286
286
|
return {key: record[key] for key in BRIEF_VIEW_FIELDS if key in record}
|
|
287
287
|
|
|
288
288
|
|
|
289
|
+
#: dataset.list_all's SDK symbol, reused from the pagination-safe helper item
|
|
290
|
+
#: A's discovery fix relies on (mammoth/api/datasets.py) rather than a
|
|
291
|
+
#: single unpaginated page, so a project with many datasets is not silently
|
|
292
|
+
#: truncated here either.
|
|
293
|
+
_DATASETS_LIST_ALL_SYMBOL = "mammoth.api.datasets.DatasetsAPI.list_all"
|
|
294
|
+
#: Soft floor for the no-DATASET_ID ``view list`` walk: whole per-dataset
|
|
295
|
+
#: pages are pulled and appended until at least this many views have been
|
|
296
|
+
#: collected (or every dataset in the project has been visited), so one call
|
|
297
|
+
#: never silently returns a single dataset's worth from a large project.
|
|
298
|
+
_VIEW_LIST_ALL_DATASETS_MIN_VIEWS = 100
|
|
299
|
+
|
|
300
|
+
|
|
289
301
|
def view_list(invocation: Invocation) -> HandlerResult:
|
|
290
|
-
"""List dataviews for a dataset in the active project.
|
|
302
|
+
"""List dataviews for a dataset, or every dataset in the active project.
|
|
303
|
+
|
|
304
|
+
Omitting DATASET_ID used to fail outright with ``missing_argument`` --
|
|
305
|
+
an agent's very first move is often ``view list`` before it knows any
|
|
306
|
+
dataset id. It now walks every dataset in the active project instead
|
|
307
|
+
(paged; see :data:`_VIEW_LIST_ALL_DATASETS_MIN_VIEWS`), same as passing
|
|
308
|
+
an explicit id still does for a single dataset.
|
|
309
|
+
"""
|
|
291
310
|
project_id = require_project(invocation)
|
|
292
|
-
dataset_id =
|
|
311
|
+
dataset_id = _int_positional_at(invocation, 0, "dataset id")
|
|
293
312
|
document = invocation.load_input() or {}
|
|
294
|
-
|
|
295
|
-
|
|
313
|
+
if dataset_id is None and document.get(_DATASET_ID_FIELD) is not None:
|
|
314
|
+
dataset_id = int(document[_DATASET_ID_FIELD])
|
|
296
315
|
with open_service(invocation) as (service, auth):
|
|
297
|
-
|
|
316
|
+
if dataset_id is None:
|
|
317
|
+
data = _view_list_across_project(service, _symbol(invocation), document, project_id)
|
|
318
|
+
else:
|
|
319
|
+
kwargs: dict[str, Any] = {"dataset_id": dataset_id, "project_id": project_id}
|
|
320
|
+
_forward_optional(document, kwargs, ("limit", "sort"))
|
|
321
|
+
data = service.call(_symbol(invocation), **kwargs)
|
|
298
322
|
parents.remember_records(
|
|
299
323
|
_profile_name(invocation), auth.workspace_id, data, project_id=project_id
|
|
300
324
|
)
|
|
@@ -309,6 +333,45 @@ def view_list(invocation: Invocation) -> HandlerResult:
|
|
|
309
333
|
return data, _meta(invocation, auth.workspace_id, project_id)
|
|
310
334
|
|
|
311
335
|
|
|
336
|
+
def _view_list_across_project(
|
|
337
|
+
service: Any, view_list_symbol: str, document: dict[str, Any], project_id: int
|
|
338
|
+
) -> dict[str, Any]:
|
|
339
|
+
"""Aggregate dataviews from every dataset in the project (paged).
|
|
340
|
+
|
|
341
|
+
Starts at ``dataset_offset`` (default 0) into the project's dataset
|
|
342
|
+
list, pulling whole per-dataset view pages until either every dataset
|
|
343
|
+
has been visited or at least ``_VIEW_LIST_ALL_DATASETS_MIN_VIEWS`` views
|
|
344
|
+
have been collected. ``next_dataset_offset`` names where to resume when
|
|
345
|
+
the project holds more datasets than were visited.
|
|
346
|
+
"""
|
|
347
|
+
dataset_offset = int(document.get("dataset_offset", 0))
|
|
348
|
+
datasets_page = service.call(_DATASETS_LIST_ALL_SYMBOL, project_id=project_id)
|
|
349
|
+
datasets = datasets_page.get("datasets", []) if isinstance(datasets_page, dict) else []
|
|
350
|
+
view_kwargs: dict[str, Any] = {}
|
|
351
|
+
_forward_optional(document, view_kwargs, ("sort",))
|
|
352
|
+
dataviews: list[Any] = []
|
|
353
|
+
visited = dataset_offset
|
|
354
|
+
for index in range(dataset_offset, len(datasets)):
|
|
355
|
+
dataset = datasets[index]
|
|
356
|
+
visited = index + 1
|
|
357
|
+
dataset_id = dataset.get("id") if isinstance(dataset, dict) else None
|
|
358
|
+
if not isinstance(dataset_id, int):
|
|
359
|
+
continue
|
|
360
|
+
page = service.call(
|
|
361
|
+
view_list_symbol, dataset_id=dataset_id, project_id=project_id, **view_kwargs
|
|
362
|
+
)
|
|
363
|
+
for item in page.get("dataviews", []) if isinstance(page, dict) else []:
|
|
364
|
+
if isinstance(item, dict):
|
|
365
|
+
item = {**item, "dataset_id": dataset_id}
|
|
366
|
+
dataviews.append(item)
|
|
367
|
+
if len(dataviews) >= _VIEW_LIST_ALL_DATASETS_MIN_VIEWS:
|
|
368
|
+
break
|
|
369
|
+
result: dict[str, Any] = {"dataviews": dataviews, "datasets_visited": visited - dataset_offset}
|
|
370
|
+
if visited < len(datasets):
|
|
371
|
+
result["next_dataset_offset"] = visited
|
|
372
|
+
return result
|
|
373
|
+
|
|
374
|
+
|
|
312
375
|
def view_bulk_delete(invocation: Invocation) -> HandlerResult:
|
|
313
376
|
"""Permanently delete several dataviews by id. Prompt or ``--yes`` required."""
|
|
314
377
|
project_id = require_project(invocation)
|
|
@@ -778,15 +841,17 @@ def _relabel_and_check(
|
|
|
778
841
|
if mapping is None or types is None:
|
|
779
842
|
mapping, types = _column_profile(service, dataset_id, view_id, project_id)
|
|
780
843
|
data = _relabel_columns(service, dataset_id, view_id, project_id, data, mapping)
|
|
781
|
-
return _with_column_warnings(data, types, view_id)
|
|
844
|
+
return _with_column_warnings(data, types, view_id, dataset_id)
|
|
782
845
|
|
|
783
846
|
|
|
784
|
-
def _with_column_warnings(
|
|
847
|
+
def _with_column_warnings(
|
|
848
|
+
data: Any, types: dict[str, str], view_id: int, dataset_id: int | None = None
|
|
849
|
+
) -> Any:
|
|
785
850
|
"""Add ``column_warnings`` for the rows of a data page (never fatal)."""
|
|
786
851
|
if not isinstance(data, dict) or not isinstance(data.get(_ROWS_KEY), list) or not types:
|
|
787
852
|
return data
|
|
788
853
|
try:
|
|
789
|
-
warnings = column_warnings(data[_ROWS_KEY], types, view_id)
|
|
854
|
+
warnings = column_warnings(data[_ROWS_KEY], types, view_id, dataset_id)
|
|
790
855
|
except Exception: # noqa: BLE001 -- a presentation aid must not fail the read
|
|
791
856
|
return data
|
|
792
857
|
return {**data, "column_warnings": warnings} if warnings else data
|
|
@@ -1635,6 +1700,31 @@ def view_pipeline_edit(invocation: Invocation) -> HandlerResult:
|
|
|
1635
1700
|
return data, _meta(invocation, auth.workspace_id, None)
|
|
1636
1701
|
|
|
1637
1702
|
|
|
1703
|
+
#: OpenAPI ``PipelineInfo`` (the exact ``get_pipeline`` payload) pins
|
|
1704
|
+
#: ``draft_mode`` as a top-level string enum and ``auto_run`` as a top-level
|
|
1705
|
+
#: bool. "dirty" means unsubmitted draft changes are pending; ``auto_run``
|
|
1706
|
+
#: false means new tasks stop short of computing. Both leave a dataview
|
|
1707
|
+
#: looking finished when it is not (WPP/T3 evidence: agents that never ran
|
|
1708
|
+
#: 'view pipeline get' had no way to notice either).
|
|
1709
|
+
_DRAFT_MODE_DIRTY = "dirty"
|
|
1710
|
+
|
|
1711
|
+
|
|
1712
|
+
def _pipeline_action_hint(view_id: int, data: dict[str, Any]) -> str | None:
|
|
1713
|
+
"""Best-effort hint naming the exact command a stale pipeline needs."""
|
|
1714
|
+
if data.get("draft_mode") == _DRAFT_MODE_DIRTY:
|
|
1715
|
+
return (
|
|
1716
|
+
f"This view has an unsubmitted draft with pending changes; run "
|
|
1717
|
+
f"'mammoth view draft submit {view_id}' to apply them."
|
|
1718
|
+
)
|
|
1719
|
+
if data.get("auto_run") is False:
|
|
1720
|
+
return (
|
|
1721
|
+
f"Auto-run is off for this pipeline; new tasks will not compute "
|
|
1722
|
+
f"automatically. Run 'mammoth view pipeline rerun {view_id}' to "
|
|
1723
|
+
f"compute pending tasks now."
|
|
1724
|
+
)
|
|
1725
|
+
return None
|
|
1726
|
+
|
|
1727
|
+
|
|
1638
1728
|
def view_pipeline_get(invocation: Invocation) -> HandlerResult:
|
|
1639
1729
|
"""Get a dataview's full pipeline."""
|
|
1640
1730
|
dataview_id = _require_int_positional_at(invocation, 0, "dataview id")
|
|
@@ -1643,6 +1733,9 @@ def view_pipeline_get(invocation: Invocation) -> HandlerResult:
|
|
|
1643
1733
|
_forward_optional(document, kwargs, ("dataset_id",))
|
|
1644
1734
|
with open_service(invocation) as (service, auth):
|
|
1645
1735
|
data = service.call(_symbol(invocation), **kwargs)
|
|
1736
|
+
hint = _pipeline_action_hint(dataview_id, data) if isinstance(data, dict) else None
|
|
1737
|
+
if hint is not None:
|
|
1738
|
+
data = {**data, "hint": hint}
|
|
1646
1739
|
return data, _meta(invocation, auth.workspace_id, None)
|
|
1647
1740
|
|
|
1648
1741
|
|
|
@@ -2149,7 +2242,18 @@ def view_export_specialized(invocation: Invocation) -> HandlerResult:
|
|
|
2149
2242
|
for name, parameter in signature.parameters.items()
|
|
2150
2243
|
if name != "self" and parameter.kind is not inspect.Parameter.VAR_KEYWORD
|
|
2151
2244
|
}
|
|
2152
|
-
|
|
2245
|
+
# The six common trigger controls only actually reach the SDK call when
|
|
2246
|
+
# the route's method has a **kwargs sink to carry them; ``to_dataset`` has
|
|
2247
|
+
# a closed signature (no **kwargs) and does not accept any of them.
|
|
2248
|
+
# Allowing them anyway let a field like ``end_of_pipeline`` pass this
|
|
2249
|
+
# check and then crash the call itself with an opaque "unexpected keyword
|
|
2250
|
+
# argument" TypeError instead of a clear unknown_input_field.
|
|
2251
|
+
accepts_var_keyword = any(
|
|
2252
|
+
parameter.kind is inspect.Parameter.VAR_KEYWORD
|
|
2253
|
+
for parameter in signature.parameters.values()
|
|
2254
|
+
)
|
|
2255
|
+
common_fields = _SPECIAL_EXPORT_COMMON_FIELDS if accepts_var_keyword else frozenset()
|
|
2256
|
+
allowed = explicit_fields | common_fields | {_DATASET_ID_FIELD}
|
|
2153
2257
|
unknown = sorted(set(document) - allowed)
|
|
2154
2258
|
if unknown:
|
|
2155
2259
|
raise CliError(
|
|
@@ -2290,7 +2394,7 @@ def upload_preview(service: Any, dataset_id: int, project_id: int | None) -> dic
|
|
|
2290
2394
|
"sample_rows": rows[:_UPLOAD_SAMPLE_ROWS],
|
|
2291
2395
|
}
|
|
2292
2396
|
try:
|
|
2293
|
-
warnings = column_warnings(rows, types, view_id) if rows else []
|
|
2397
|
+
warnings = column_warnings(rows, types, view_id, dataset_id) if rows else []
|
|
2294
2398
|
except Exception: # noqa: BLE001
|
|
2295
2399
|
warnings = []
|
|
2296
2400
|
if warnings:
|
|
@@ -592,8 +592,13 @@ _S7_ADDITIONAL_INPUT_FIELDS: dict[str, tuple[FieldSpec, ...]] = {
|
|
|
592
592
|
# The dataview GET takes a server-side projection: "__min", "__standard",
|
|
593
593
|
# "__full" or a comma-separated field list.
|
|
594
594
|
"view.get": (FieldSpec("fields", required=False, annotation=str | None, default=None),),
|
|
595
|
-
# ``view list`` records are trimmed to the brief shape; ``full`` keeps
|
|
596
|
-
|
|
595
|
+
# ``view list`` records are trimmed to the brief shape; ``full`` keeps
|
|
596
|
+
# them. ``dataset_offset`` resumes the no-DATASET_ID, every-dataset-in-
|
|
597
|
+
# the-project walk (item G) at a later dataset index.
|
|
598
|
+
"view.list": (
|
|
599
|
+
FieldSpec("full", required=False, annotation=bool, default=False),
|
|
600
|
+
FieldSpec("dataset_offset", required=False, annotation=int, default=0),
|
|
601
|
+
),
|
|
597
602
|
"activity.list": (
|
|
598
603
|
FieldSpec("project_id", required=False, annotation=int | None, default=None),
|
|
599
604
|
FieldSpec("workspace_id", required=False, annotation=int | None, default=None),
|
|
@@ -61,10 +61,43 @@ def _convert_hint(view_id: int | None, column: str, to: str) -> str:
|
|
|
61
61
|
return f"mammoth view transform convert-type {target} --input '{spec}'"
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
def _duplicate_rows_warning(
|
|
65
|
+
rows: list[Mapping[str, Any]],
|
|
66
|
+
view_id: int | None,
|
|
67
|
+
dataset_id: int | None,
|
|
68
|
+
) -> dict[str, Any] | None:
|
|
69
|
+
"""Return a table-level warning when the page itself holds exact duplicates.
|
|
70
|
+
|
|
71
|
+
Scoped honestly to the rows actually read: an agent must not read this as
|
|
72
|
+
table-wide duplication without separately checking the full table (e.g.
|
|
73
|
+
``view data aggregate`` COUNT vs a distinct count).
|
|
74
|
+
"""
|
|
75
|
+
fingerprints = [json.dumps(row, sort_keys=True, default=str) for row in rows]
|
|
76
|
+
counts: dict[str, int] = {}
|
|
77
|
+
for fingerprint in fingerprints:
|
|
78
|
+
counts[fingerprint] = counts.get(fingerprint, 0) + 1
|
|
79
|
+
duplicate_count = sum(count - 1 for count in counts.values() if count > 1)
|
|
80
|
+
if not duplicate_count:
|
|
81
|
+
return None
|
|
82
|
+
warning: dict[str, Any] = {
|
|
83
|
+
"issue": "duplicate_rows",
|
|
84
|
+
"detail": (
|
|
85
|
+
f"{duplicate_count} of the {len(rows)} rows read are exact duplicates "
|
|
86
|
+
"of another row in this page (not checked table-wide)."
|
|
87
|
+
),
|
|
88
|
+
"rows_checked": len(rows),
|
|
89
|
+
}
|
|
90
|
+
if view_id is not None and dataset_id is not None:
|
|
91
|
+
spec = json.dumps({"dataset_id": dataset_id})
|
|
92
|
+
warning["fix"] = f"mammoth view transform discard-duplicates {view_id} --input '{spec}'"
|
|
93
|
+
return warning
|
|
94
|
+
|
|
95
|
+
|
|
64
96
|
def column_warnings(
|
|
65
97
|
rows: Iterable[Mapping[str, Any]],
|
|
66
98
|
column_types: Mapping[str, str],
|
|
67
99
|
view_id: int | None = None,
|
|
100
|
+
dataset_id: int | None = None,
|
|
68
101
|
) -> list[dict[str, Any]]:
|
|
69
102
|
"""Return warnings for text columns that hold numbers or dates, and for blanks.
|
|
70
103
|
|
|
@@ -72,18 +105,24 @@ def column_warnings(
|
|
|
72
105
|
rows: Row objects keyed by display name (a data page after relabeling).
|
|
73
106
|
column_types: Display name to Mammoth type (``TEXT``, ``NUMERIC``, ...).
|
|
74
107
|
view_id: The view the rows came from, used in the suggested command.
|
|
108
|
+
dataset_id: The view's dataset, used for the duplicate-rows fix
|
|
109
|
+
command (a mutation, so it needs the exact parent, not discovery).
|
|
75
110
|
|
|
76
111
|
Returns:
|
|
77
112
|
One record per finding: ``column``, ``issue``
|
|
78
|
-
(``numbers_stored_as_text``, ``dates_stored_as_text
|
|
79
|
-
``blank_values``
|
|
80
|
-
|
|
113
|
+
(``numbers_stored_as_text``, ``dates_stored_as_text``,
|
|
114
|
+
``blank_values`` or the table-level ``duplicate_rows``), ``detail``
|
|
115
|
+
and, where one command fixes it, ``fix``. Counts are over the rows
|
|
116
|
+
given (``rows_checked`` on each record).
|
|
81
117
|
"""
|
|
82
118
|
materialised = [row for row in rows if isinstance(row, Mapping)]
|
|
83
119
|
if not materialised:
|
|
84
120
|
return []
|
|
85
121
|
checked = len(materialised)
|
|
86
122
|
warnings: list[dict[str, Any]] = []
|
|
123
|
+
duplicate_warning = _duplicate_rows_warning(materialised, view_id, dataset_id)
|
|
124
|
+
if duplicate_warning is not None:
|
|
125
|
+
warnings.append(duplicate_warning)
|
|
87
126
|
for column, col_type in column_types.items():
|
|
88
127
|
values = [row.get(column) for row in materialised if column in row]
|
|
89
128
|
if not values:
|
|
@@ -109,6 +109,38 @@ def _job_recovery(job_id: object, *, profile: str | None = None) -> list[str]:
|
|
|
109
109
|
|
|
110
110
|
_PROJECT_DELETE = re.compile(r"/workspaces/\d+/projects/(\d+)/?$")
|
|
111
111
|
_DASHBOARD_WRITE = re.compile(r"/dashboards/(\d+)(?:/|$)")
|
|
112
|
+
_ENDPOINT_WORKSPACE = re.compile(r"/workspaces/(\d+)")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _workspace_mismatch_error(exc: MammothAuthError, workspace_id: int | None) -> CliError | None:
|
|
116
|
+
"""A 401 whose endpoint targets a workspace other than the profile's own
|
|
117
|
+
is a scoping mistake, not invalid credentials, so it must not tell the
|
|
118
|
+
user to reauthenticate (release evidence T4-L-002 — the in-product agent
|
|
119
|
+
parroted "reauthenticate" to a web user for exactly this case).
|
|
120
|
+
"""
|
|
121
|
+
if workspace_id is None:
|
|
122
|
+
return None
|
|
123
|
+
endpoint = getattr(exc, "endpoint", None)
|
|
124
|
+
if not isinstance(endpoint, str):
|
|
125
|
+
return None
|
|
126
|
+
match = _ENDPOINT_WORKSPACE.search(endpoint)
|
|
127
|
+
if match is None:
|
|
128
|
+
return None
|
|
129
|
+
target_workspace_id = int(match.group(1))
|
|
130
|
+
if target_workspace_id == workspace_id:
|
|
131
|
+
return None
|
|
132
|
+
return CliError(
|
|
133
|
+
code=CODE_AUTHORIZATION_REQUIRED,
|
|
134
|
+
message=(
|
|
135
|
+
f"No access to workspace {target_workspace_id} "
|
|
136
|
+
f"(this sign-in is for workspace {workspace_id})."
|
|
137
|
+
),
|
|
138
|
+
exit_status=EXIT_AUTH,
|
|
139
|
+
hint="Pass --workspace or use a profile signed in for that workspace.",
|
|
140
|
+
details=_metadata(exc),
|
|
141
|
+
request_id=exc.request_id,
|
|
142
|
+
authorization_required=True,
|
|
143
|
+
)
|
|
112
144
|
|
|
113
145
|
|
|
114
146
|
def _resource_recovery(
|
|
@@ -161,6 +193,9 @@ def map_sdk_exception(
|
|
|
161
193
|
)
|
|
162
194
|
|
|
163
195
|
if isinstance(exc, MammothAuthError):
|
|
196
|
+
mismatch = _workspace_mismatch_error(exc, workspace_id)
|
|
197
|
+
if mismatch is not None:
|
|
198
|
+
return mismatch
|
|
164
199
|
return CliError(
|
|
165
200
|
code=CODE_AUTHENTICATION_FAILED,
|
|
166
201
|
message="Mammoth rejected the provided credentials.",
|
|
@@ -168,6 +168,23 @@ POSITIONAL_OVERRIDES: dict[str, tuple[PositionalSpec, ...]] = {
|
|
|
168
168
|
"dashboard.tags.merge": (
|
|
169
169
|
PositionalSpec(name="tag_id", type=int, required=True, help="ID of the source tag."),
|
|
170
170
|
),
|
|
171
|
+
# Item G: an agent's first move is often `view list` before it has any
|
|
172
|
+
# dataset id; omitting it now walks every dataset in the active project
|
|
173
|
+
# (paged) instead of failing with missing_argument.
|
|
174
|
+
"view.list": (
|
|
175
|
+
PositionalSpec(
|
|
176
|
+
name="dataset_id",
|
|
177
|
+
type=int,
|
|
178
|
+
required=False,
|
|
179
|
+
falls_back_to_field="dataset_id",
|
|
180
|
+
help=(
|
|
181
|
+
"ID of the dataset. Omit it to list dataviews across every "
|
|
182
|
+
"dataset in the active project instead (paged; see the "
|
|
183
|
+
"'dataset_offset' input field and the 'next_dataset_offset' "
|
|
184
|
+
"result field)."
|
|
185
|
+
),
|
|
186
|
+
),
|
|
187
|
+
),
|
|
171
188
|
# Explicit parent avoids rich-view discovery for the release-scoped GET.
|
|
172
189
|
"view.get": (
|
|
173
190
|
PositionalSpec(name="view_id", type=int, required=True, help="ID of the view."),
|
|
@@ -913,6 +930,22 @@ EXACT_PARENT_HELP = (
|
|
|
913
930
|
"'dataset_id' input field; only read commands may omit it and discover the parent."
|
|
914
931
|
)
|
|
915
932
|
|
|
933
|
+
# Per-command overrides of ``EXACT_PARENT_HELP`` for a command whose own
|
|
934
|
+
# fields could otherwise be mistaken for this positional. ``view.export.dataset``
|
|
935
|
+
# also takes a ``target_ds_id`` input field naming the destination dataset;
|
|
936
|
+
# an agent that read only the generic text passed a destination id here
|
|
937
|
+
# instead and hit a not-found on the (unrelated) source view's own parent
|
|
938
|
+
# (WPP evidence c38/c39).
|
|
939
|
+
_EXACT_PARENT_HELP_OVERRIDES: dict[str, str] = {
|
|
940
|
+
"view.export.dataset": (
|
|
941
|
+
"Exact parent dataset ID of the SOURCE view being exported -- not the "
|
|
942
|
+
"destination. Required for this command: pass it here or as the "
|
|
943
|
+
"'dataset_id' input field. To write into an existing destination dataset "
|
|
944
|
+
"instead of creating one, use the 'target_ds_id' input field, not this "
|
|
945
|
+
"positional."
|
|
946
|
+
),
|
|
947
|
+
}
|
|
948
|
+
|
|
916
949
|
|
|
917
950
|
def _with_exact_parent_help(
|
|
918
951
|
command_id: str, specs: tuple[PositionalSpec, ...]
|
|
@@ -926,13 +959,14 @@ def _with_exact_parent_help(
|
|
|
926
959
|
record = command_by_id(command_id)
|
|
927
960
|
if record is None or record.get("mutation_class", "read") == "read":
|
|
928
961
|
return specs
|
|
962
|
+
help_text = _EXACT_PARENT_HELP_OVERRIDES.get(command_id, EXACT_PARENT_HELP)
|
|
929
963
|
return tuple(
|
|
930
964
|
(
|
|
931
965
|
PositionalSpec(
|
|
932
966
|
name=spec.name,
|
|
933
967
|
type=spec.type,
|
|
934
968
|
required=spec.required,
|
|
935
|
-
help=
|
|
969
|
+
help=help_text,
|
|
936
970
|
falls_back_to_field=spec.falls_back_to_field,
|
|
937
971
|
fills_sdk_param=spec.fills_sdk_param,
|
|
938
972
|
example_value=spec.example_value,
|
|
@@ -91,13 +91,36 @@ def is_opaque_mapping(annotation: Any) -> bool:
|
|
|
91
91
|
return not args or (len(args) == 2 and args[1] is Any)
|
|
92
92
|
|
|
93
93
|
|
|
94
|
+
#: A leaf condition's ``value`` may be a literal, or a marker that binds it to
|
|
95
|
+
#: a project/workspace parameter's live value instead. The server deep-walks
|
|
96
|
+
#: task params for this exact shape and substitutes the parameter's current
|
|
97
|
+
#: value at execution time (``api/api/parameters/binding_extractor.py`` /
|
|
98
|
+
#: ``consts.py`` in mvc-service); the SDK's ``Condition.value`` already
|
|
99
|
+
#: forwards it untouched, so no SDK change is needed — only this schema was
|
|
100
|
+
#: silent about the shape existing.
|
|
101
|
+
_PARAMETER_BINDING_SCHEMA = {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"description": (
|
|
104
|
+
"Bind to a project/workspace parameter's live value instead of a literal. "
|
|
105
|
+
"Create one first with 'parameter create' if it does not exist yet."
|
|
106
|
+
),
|
|
107
|
+
"properties": {
|
|
108
|
+
"type": {"const": "parameter"},
|
|
109
|
+
"parameter_id": {"type": "integer"},
|
|
110
|
+
},
|
|
111
|
+
"required": ["type", "parameter_id"],
|
|
112
|
+
"additionalProperties": False,
|
|
113
|
+
"example": {"type": "parameter", "parameter_id": 12},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
94
117
|
def _condition_schema() -> dict[str, Any]:
|
|
95
118
|
leaf = {
|
|
96
119
|
"type": "object",
|
|
97
120
|
"properties": {
|
|
98
121
|
"column": {"type": "string", "example": "Status"},
|
|
99
122
|
"operator": {"type": "string", "example": "EQ"},
|
|
100
|
-
"value": {"example": "Active"},
|
|
123
|
+
"value": {"anyOf": [{"example": "Active"}, _PARAMETER_BINDING_SCHEMA]},
|
|
101
124
|
"case_sensitive": {"type": "boolean"},
|
|
102
125
|
"value_is_column": {"type": "boolean"},
|
|
103
126
|
"component": {"type": "string"},
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mammoth-cli"
|
|
3
|
-
version = "2.0.
|
|
3
|
+
version = "2.0.51"
|
|
4
4
|
description = "Command-line interface for the Mammoth Analytics platform"
|
|
5
5
|
authors = [{name = "Mammoth Analytics", email = "support@mammoth.io"}]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
license = "LicenseRef-Proprietary"
|
|
8
8
|
requires-python = ">=3.12,<3.15"
|
|
9
9
|
dependencies = [
|
|
10
|
-
"mammoth-io (>=0.7.
|
|
10
|
+
"mammoth-io (>=0.7.23,<0.8)",
|
|
11
11
|
"typer (>=0.27,<0.28)",
|
|
12
12
|
"rich (>=15,<16)",
|
|
13
13
|
"platformdirs (>=4.10,<5)",
|
|
@@ -1881,8 +1881,10 @@ commands:
|
|
|
1881
1881
|
required: false
|
|
1882
1882
|
metavar: DATASET_ID
|
|
1883
1883
|
falls_back_to_field: dataset_id
|
|
1884
|
-
help: 'Exact parent dataset ID
|
|
1885
|
-
|
|
1884
|
+
help: 'Exact parent dataset ID of the SOURCE view being exported -- not the destination.
|
|
1885
|
+
Required for this command: pass it here or as the ''dataset_id'' input field. To write into
|
|
1886
|
+
an existing destination dataset instead of creating one, use the ''target_ds_id'' input field,
|
|
1887
|
+
not this positional.'
|
|
1886
1888
|
options: []
|
|
1887
1889
|
sdk_symbol: mammoth.view.ViewExport.to_dataset
|
|
1888
1890
|
sdk_conversion: Call mammoth.view.ViewExport.to_dataset with validated request fields.
|
|
@@ -2994,10 +2996,12 @@ commands:
|
|
|
2994
2996
|
positionals:
|
|
2995
2997
|
- name: dataset_id
|
|
2996
2998
|
type: int
|
|
2997
|
-
required:
|
|
2999
|
+
required: false
|
|
2998
3000
|
metavar: DATASET_ID
|
|
2999
|
-
falls_back_to_field:
|
|
3000
|
-
help: ID of the dataset.
|
|
3001
|
+
falls_back_to_field: dataset_id
|
|
3002
|
+
help: 'ID of the dataset. Omit it to list dataviews across every dataset in
|
|
3003
|
+
the active project instead (paged; see the ''dataset_offset'' input field
|
|
3004
|
+
and the ''next_dataset_offset'' result field).'
|
|
3001
3005
|
options: []
|
|
3002
3006
|
sdk_symbol: mammoth.api.dataviews.DataviewsAPI.list
|
|
3003
3007
|
sdk_conversion: Call mammoth.api.dataviews.DataviewsAPI.list with validated request fields.
|
|
@@ -3013,7 +3017,7 @@ commands:
|
|
|
3013
3017
|
contract_fixture: null
|
|
3014
3018
|
required_fixture_guard: null
|
|
3015
3019
|
secret_fields: []
|
|
3016
|
-
human_example: mammoth view list
|
|
3020
|
+
human_example: mammoth view list --help
|
|
3017
3021
|
agent_example: mammoth view list 123
|
|
3018
3022
|
unit_tests:
|
|
3019
3023
|
- UT-VIEW-LIST
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mammoth_cli-2.0.49 → mammoth_cli-2.0.51}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|