pltr-cli 0.13.1__tar.gz → 0.14.0__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.
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/PKG-INFO +1 -1
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/pyproject.toml +1 -1
- pltr_cli-0.14.0/src/pltr/__init__.py +1 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/oauth.py +10 -1
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/token.py +10 -1
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/connectivity.py +121 -3
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/folder.py +25 -4
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/orchestration.py +25 -4
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/project.py +61 -16
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/resource.py +151 -47
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_oauth.py +100 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_token.py +88 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_connectivity.py +155 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_folder.py +39 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_orchestration.py +96 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_project.py +86 -8
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_resource.py +214 -30
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/uv.lock +1 -1
- pltr_cli-0.13.1/src/pltr/__init__.py +0 -1
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/ci.yml +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/claude-code-review.yml +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/claude.yml +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/publish.yml +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/test-publish.yml +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.gitignore +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.pre-commit-config.yaml +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/CHANGELOG.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/CLAUDE.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/LICENSE +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/README.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/RELEASE.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/README.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/SKILL.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/admin-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/aip-agents-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/connectivity-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/dataset-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/filesystem-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/functions-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/language-models-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/mediasets-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/models-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/ontology-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/orchestration-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/quick-start.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/sql-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/streams-commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/workflows/data-analysis.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/workflows/data-pipeline.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/workflows/permission-management.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/README.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/api/wrapper.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/examples/csv-upload.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/examples/gallery.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/features/dataset-transactions.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/migration/v2-pagination.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/pagination.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/aliases.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/authentication.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/claude-skill.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/commands.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/quick-start.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/troubleshooting.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/workflows.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/mypy.ini +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/scripts/release.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/__main__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/base.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/manager.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/storage.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/cli.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/admin.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/aip_agents.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/alias.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/audit.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/completion.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/configure.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/connectivity.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/cp.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/data_health.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/dataset.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/folder.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/functions.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/language_models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/mediasets.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/ontology.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/orchestration.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/project.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/resource.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/resource_role.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/shell.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/space.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/sql.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/streams.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/third_party_applications.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/verify.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/widgets.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/aliases.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/profiles.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/settings.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/admin.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/aip_agents.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/audit.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/base.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/copy.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/data_health.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/dataset.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/functions.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/language_models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/mediasets.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/ontology.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/resource_role.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/space.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/sql.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/streams.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/third_party_applications.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/widgets.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/alias_resolver.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/completion.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/formatting.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/pagination.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/progress.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/conftest.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/README.md +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/conftest.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_auth_flow.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_cli_integration.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_data_workflows.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_data_workflows_simple.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_simple_integration.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_base.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_manager.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_storage.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_admin.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_aip_agents.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_alias.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_audit.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_completion.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_connectivity.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_data_health.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_dataset.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_folder.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_functions.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_language_models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_mediasets.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_ontology.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_orchestration.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_shell.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_sql.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_streams.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_third_party_applications.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_verify_simple.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_widgets.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/test_aliases.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/test_profiles.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/test_settings.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_admin.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_aip_agents.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_base.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_copy.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_data_health.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_dataset.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_dataset_transactions.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_functions.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_language_models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_mediasets.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_models.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_ontology.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_pagination_integration.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_resource_role.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_space.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_sql.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_streams.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_utils/__init__.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_utils/test_alias_resolver.py +0 -0
- {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_utils/test_pagination.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.14.0"
|
|
@@ -54,7 +54,16 @@ class OAuthClientProvider(AuthProvider):
|
|
|
54
54
|
client_secret=self.client_secret, # type: ignore
|
|
55
55
|
scopes=self.scopes,
|
|
56
56
|
)
|
|
57
|
-
|
|
57
|
+
# Newer SDKs may support client-level preview mode while older ones do not.
|
|
58
|
+
# Try the preview-aware constructor first, then fall back for compatibility.
|
|
59
|
+
try:
|
|
60
|
+
return FoundryClient( # type: ignore[call-arg]
|
|
61
|
+
auth=auth, hostname=self.host, preview=True
|
|
62
|
+
)
|
|
63
|
+
except TypeError as e:
|
|
64
|
+
if "preview" not in str(e):
|
|
65
|
+
raise
|
|
66
|
+
return FoundryClient(auth=auth, hostname=self.host)
|
|
58
67
|
|
|
59
68
|
def validate(self) -> bool:
|
|
60
69
|
"""Validate authentication credentials."""
|
|
@@ -32,7 +32,16 @@ class TokenAuthProvider(AuthProvider):
|
|
|
32
32
|
from foundry_sdk import FoundryClient, UserTokenAuth
|
|
33
33
|
|
|
34
34
|
auth = UserTokenAuth(token=self.token) # type: ignore
|
|
35
|
-
|
|
35
|
+
# Newer SDKs may support client-level preview mode while older ones do not.
|
|
36
|
+
# Try the preview-aware constructor first, then fall back for compatibility.
|
|
37
|
+
try:
|
|
38
|
+
return FoundryClient( # type: ignore[call-arg]
|
|
39
|
+
auth=auth, hostname=self.host, preview=True
|
|
40
|
+
)
|
|
41
|
+
except TypeError as e:
|
|
42
|
+
if "preview" not in str(e):
|
|
43
|
+
raise
|
|
44
|
+
return FoundryClient(auth=auth, hostname=self.host)
|
|
36
45
|
|
|
37
46
|
def validate(self) -> bool:
|
|
38
47
|
"""Validate authentication credentials."""
|
|
@@ -2,14 +2,22 @@
|
|
|
2
2
|
Connectivity service wrapper for Foundry SDK.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
from collections import deque
|
|
5
8
|
from typing import Any, Optional, Dict, List
|
|
6
9
|
|
|
7
10
|
from .base import BaseService
|
|
8
11
|
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
9
14
|
|
|
10
15
|
class ConnectivityService(BaseService):
|
|
11
16
|
"""Service wrapper for Foundry connectivity operations."""
|
|
12
17
|
|
|
18
|
+
DEFAULT_FILESYSTEM_FALLBACK_START_FOLDER_RID = "ri.compass.main.folder.0"
|
|
19
|
+
MAX_FALLBACK_FOLDERS = 1000
|
|
20
|
+
|
|
13
21
|
def _get_service(self) -> Any:
|
|
14
22
|
"""Get the Foundry client for connectivity operations."""
|
|
15
23
|
return self.client
|
|
@@ -17,7 +25,15 @@ class ConnectivityService(BaseService):
|
|
|
17
25
|
@property
|
|
18
26
|
def connections_service(self) -> Any:
|
|
19
27
|
"""Get the connections service from the client."""
|
|
20
|
-
|
|
28
|
+
# Prefer legacy namespace first for backward compatibility with older SDKs.
|
|
29
|
+
legacy_connections = getattr(self.client, "connections", None)
|
|
30
|
+
if legacy_connections is not None:
|
|
31
|
+
return legacy_connections
|
|
32
|
+
|
|
33
|
+
connectivity = getattr(self.client, "connectivity", None)
|
|
34
|
+
if connectivity is None:
|
|
35
|
+
raise RuntimeError("Connectivity service is not available on the client")
|
|
36
|
+
return connectivity
|
|
21
37
|
|
|
22
38
|
@property
|
|
23
39
|
def file_imports_service(self) -> Any:
|
|
@@ -37,8 +53,17 @@ class ConnectivityService(BaseService):
|
|
|
37
53
|
List of connection information dictionaries
|
|
38
54
|
"""
|
|
39
55
|
try:
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
connection_client = self.connections_service.Connection
|
|
57
|
+
if hasattr(connection_client, "list"):
|
|
58
|
+
connections = connection_client.list()
|
|
59
|
+
return [self._format_connection_info(conn) for conn in connections]
|
|
60
|
+
|
|
61
|
+
logger.warning(
|
|
62
|
+
"Connection.list() is unavailable; falling back to filesystem scan. "
|
|
63
|
+
"Set PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID to a narrower folder "
|
|
64
|
+
"if this is slow."
|
|
65
|
+
)
|
|
66
|
+
return self._list_connections_from_filesystem()
|
|
42
67
|
except Exception as e:
|
|
43
68
|
raise RuntimeError(f"Failed to list connections: {e}")
|
|
44
69
|
|
|
@@ -384,6 +409,17 @@ class ConnectivityService(BaseService):
|
|
|
384
409
|
Formatted connection dictionary
|
|
385
410
|
"""
|
|
386
411
|
try:
|
|
412
|
+
if isinstance(connection, dict):
|
|
413
|
+
return {
|
|
414
|
+
"rid": connection.get("rid", "N/A"),
|
|
415
|
+
"display_name": connection.get("display_name", "N/A"),
|
|
416
|
+
"description": connection.get("description", ""),
|
|
417
|
+
"connection_type": connection.get("connection_type", "N/A"),
|
|
418
|
+
"status": connection.get("status", "N/A"),
|
|
419
|
+
"created_time": connection.get("created_time", "N/A"),
|
|
420
|
+
"modified_time": connection.get("modified_time", "N/A"),
|
|
421
|
+
}
|
|
422
|
+
|
|
387
423
|
return {
|
|
388
424
|
"rid": getattr(connection, "rid", "N/A"),
|
|
389
425
|
"display_name": getattr(connection, "display_name", "N/A"),
|
|
@@ -396,6 +432,88 @@ class ConnectivityService(BaseService):
|
|
|
396
432
|
except Exception:
|
|
397
433
|
return {"raw": str(connection)}
|
|
398
434
|
|
|
435
|
+
def _list_connections_from_filesystem(self) -> List[Dict[str, Any]]:
|
|
436
|
+
"""
|
|
437
|
+
Discover connection resources from filesystem when SDK list() is unavailable.
|
|
438
|
+
|
|
439
|
+
Notes:
|
|
440
|
+
- Uses Folder.children(preview=True), which requires preview access.
|
|
441
|
+
- Traversal starts from PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID when set,
|
|
442
|
+
otherwise defaults to ri.compass.main.folder.0.
|
|
443
|
+
"""
|
|
444
|
+
filesystem = getattr(self.client, "filesystem", None)
|
|
445
|
+
if filesystem is None or not hasattr(filesystem, "Folder"):
|
|
446
|
+
raise RuntimeError(
|
|
447
|
+
"Connection.list() is unavailable and filesystem fallback is not supported"
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
folder_client = filesystem.Folder
|
|
451
|
+
start_folder_rid = os.environ.get(
|
|
452
|
+
"PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID",
|
|
453
|
+
self.DEFAULT_FILESYSTEM_FALLBACK_START_FOLDER_RID,
|
|
454
|
+
)
|
|
455
|
+
pending_folders = deque([start_folder_rid])
|
|
456
|
+
visited_folders: set[str] = set()
|
|
457
|
+
discovered_connections: List[Dict[str, Any]] = []
|
|
458
|
+
|
|
459
|
+
while pending_folders and len(visited_folders) < self.MAX_FALLBACK_FOLDERS:
|
|
460
|
+
folder_rid = pending_folders.popleft()
|
|
461
|
+
if folder_rid in visited_folders:
|
|
462
|
+
continue
|
|
463
|
+
visited_folders.add(folder_rid)
|
|
464
|
+
|
|
465
|
+
try:
|
|
466
|
+
children = folder_client.children(folder_rid, preview=True)
|
|
467
|
+
except Exception as error:
|
|
468
|
+
if folder_rid == start_folder_rid:
|
|
469
|
+
raise RuntimeError(
|
|
470
|
+
f"Unable to list fallback start folder '{start_folder_rid}': {error}"
|
|
471
|
+
) from error
|
|
472
|
+
logger.debug(
|
|
473
|
+
"Skipping folder '%s' during connection discovery due to error: %s",
|
|
474
|
+
folder_rid,
|
|
475
|
+
error,
|
|
476
|
+
)
|
|
477
|
+
continue
|
|
478
|
+
|
|
479
|
+
for child in children:
|
|
480
|
+
child_rid = getattr(child, "rid", None)
|
|
481
|
+
if not child_rid:
|
|
482
|
+
continue
|
|
483
|
+
|
|
484
|
+
child_type = str(getattr(child, "type", "") or "").lower()
|
|
485
|
+
if self._looks_like_connection_resource(child_rid, child_type):
|
|
486
|
+
discovered_connections.append(
|
|
487
|
+
{
|
|
488
|
+
"rid": child_rid,
|
|
489
|
+
"display_name": getattr(child, "display_name", "N/A"),
|
|
490
|
+
"description": getattr(child, "description", ""),
|
|
491
|
+
"connection_type": child_type or "connection",
|
|
492
|
+
"status": getattr(child, "status", "N/A"),
|
|
493
|
+
"created_time": getattr(child, "created_time", "N/A"),
|
|
494
|
+
"modified_time": getattr(child, "modified_time", "N/A"),
|
|
495
|
+
}
|
|
496
|
+
)
|
|
497
|
+
continue
|
|
498
|
+
|
|
499
|
+
if child_type in {"folder", "compass_folder", "project", "space"}:
|
|
500
|
+
pending_folders.append(child_rid)
|
|
501
|
+
|
|
502
|
+
if pending_folders:
|
|
503
|
+
raise RuntimeError(
|
|
504
|
+
"Connection discovery exceeded folder scan limit "
|
|
505
|
+
f"({self.MAX_FALLBACK_FOLDERS}). "
|
|
506
|
+
"Set PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID to a narrower folder "
|
|
507
|
+
"and retry."
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
return discovered_connections
|
|
511
|
+
|
|
512
|
+
@staticmethod
|
|
513
|
+
def _looks_like_connection_resource(resource_rid: str, resource_type: str) -> bool:
|
|
514
|
+
"""Best-effort detection for connection resources from filesystem entries."""
|
|
515
|
+
return "connection" in resource_type or ".connection." in resource_rid
|
|
516
|
+
|
|
399
517
|
def _format_import_info(self, import_obj: Any) -> Dict[str, Any]:
|
|
400
518
|
"""
|
|
401
519
|
Format import information for display.
|
|
@@ -37,7 +37,8 @@ class FolderService(BaseService):
|
|
|
37
37
|
)
|
|
38
38
|
return self._format_folder_info(folder)
|
|
39
39
|
except Exception as e:
|
|
40
|
-
|
|
40
|
+
detail = self._format_error_detail(e)
|
|
41
|
+
raise RuntimeError(f"Failed to create folder '{display_name}': {detail}")
|
|
41
42
|
|
|
42
43
|
def get_folder(self, folder_rid: str) -> Dict[str, Any]:
|
|
43
44
|
"""
|
|
@@ -53,7 +54,8 @@ class FolderService(BaseService):
|
|
|
53
54
|
folder = self.service.Folder.get(folder_rid, preview=True)
|
|
54
55
|
return self._format_folder_info(folder)
|
|
55
56
|
except Exception as e:
|
|
56
|
-
|
|
57
|
+
detail = self._format_error_detail(e)
|
|
58
|
+
raise RuntimeError(f"Failed to get folder {folder_rid}: {detail}")
|
|
57
59
|
|
|
58
60
|
def list_children(
|
|
59
61
|
self,
|
|
@@ -81,7 +83,10 @@ class FolderService(BaseService):
|
|
|
81
83
|
children.append(self._format_resource_info(child))
|
|
82
84
|
return children
|
|
83
85
|
except Exception as e:
|
|
84
|
-
|
|
86
|
+
detail = self._format_error_detail(e)
|
|
87
|
+
raise RuntimeError(
|
|
88
|
+
f"Failed to list children of folder {folder_rid}: {detail}"
|
|
89
|
+
)
|
|
85
90
|
|
|
86
91
|
def get_folders_batch(self, folder_rids: List[str]) -> List[Dict[str, Any]]:
|
|
87
92
|
"""
|
|
@@ -106,7 +111,8 @@ class FolderService(BaseService):
|
|
|
106
111
|
folders.append(self._format_folder_info(folder))
|
|
107
112
|
return folders
|
|
108
113
|
except Exception as e:
|
|
109
|
-
|
|
114
|
+
detail = self._format_error_detail(e)
|
|
115
|
+
raise RuntimeError(f"Failed to get folders batch: {detail}")
|
|
110
116
|
|
|
111
117
|
def _format_folder_info(self, folder: Any) -> Dict[str, Any]:
|
|
112
118
|
"""
|
|
@@ -170,3 +176,18 @@ class FolderService(BaseService):
|
|
|
170
176
|
if hasattr(timestamp, "time"):
|
|
171
177
|
return str(timestamp.time)
|
|
172
178
|
return str(timestamp)
|
|
179
|
+
|
|
180
|
+
@staticmethod
|
|
181
|
+
def _format_error_detail(error: Exception) -> str:
|
|
182
|
+
"""Format exception details, including fallback for empty SDK error strings."""
|
|
183
|
+
message = str(error).strip()
|
|
184
|
+
if message:
|
|
185
|
+
return message
|
|
186
|
+
|
|
187
|
+
args = getattr(error, "args", ())
|
|
188
|
+
if args:
|
|
189
|
+
joined = " ".join(str(arg) for arg in args if arg is not None)
|
|
190
|
+
if joined:
|
|
191
|
+
return joined
|
|
192
|
+
|
|
193
|
+
return error.__class__.__name__
|
|
@@ -147,14 +147,14 @@ class OrchestrationService(BaseService):
|
|
|
147
147
|
Search results with pagination info
|
|
148
148
|
"""
|
|
149
149
|
try:
|
|
150
|
-
kwargs: Dict[str, Any] = {}
|
|
150
|
+
kwargs: Dict[str, Any] = {"preview": True}
|
|
151
151
|
if page_size is not None:
|
|
152
152
|
kwargs["page_size"] = page_size
|
|
153
153
|
if page_token is not None:
|
|
154
154
|
kwargs["page_token"] = page_token
|
|
155
155
|
kwargs.update(search_params)
|
|
156
156
|
|
|
157
|
-
response = self.
|
|
157
|
+
response = self._search_with_optional_preview(kwargs)
|
|
158
158
|
return self._format_builds_search_response(response)
|
|
159
159
|
except Exception as e:
|
|
160
160
|
raise RuntimeError(f"Failed to search builds: {e}")
|
|
@@ -183,18 +183,39 @@ class OrchestrationService(BaseService):
|
|
|
183
183
|
"""Fetch a single page of builds."""
|
|
184
184
|
kwargs: Dict[str, Any] = {
|
|
185
185
|
"page_size": config.page_size or settings.get("page_size", 20),
|
|
186
|
+
"preview": True,
|
|
186
187
|
}
|
|
187
188
|
if page_token:
|
|
188
189
|
kwargs["page_token"] = page_token
|
|
189
190
|
kwargs.update(search_params)
|
|
190
191
|
|
|
191
|
-
response = self.
|
|
192
|
-
|
|
192
|
+
response = self._search_with_optional_preview(kwargs)
|
|
193
|
+
formatted = self._format_builds_search_response(response)
|
|
194
|
+
return {
|
|
195
|
+
"data": formatted.get("builds", []),
|
|
196
|
+
"next_page_token": formatted.get("next_page_token"),
|
|
197
|
+
}
|
|
193
198
|
|
|
194
199
|
return self._paginate_response(fetch_page, config, progress_callback)
|
|
195
200
|
except Exception as e:
|
|
196
201
|
raise RuntimeError(f"Failed to search builds: {e}")
|
|
197
202
|
|
|
203
|
+
def _search_with_optional_preview(self, kwargs: Dict[str, Any]) -> Any:
|
|
204
|
+
"""
|
|
205
|
+
Execute Build.search with preview compatibility fallback.
|
|
206
|
+
|
|
207
|
+
Some SDK versions reject the `preview` kwarg at call-time even if preview
|
|
208
|
+
mode is enabled via client defaults.
|
|
209
|
+
"""
|
|
210
|
+
try:
|
|
211
|
+
return self.service.Build.search(**kwargs)
|
|
212
|
+
except TypeError as e:
|
|
213
|
+
if "preview" not in str(e):
|
|
214
|
+
raise
|
|
215
|
+
fallback_kwargs = dict(kwargs)
|
|
216
|
+
fallback_kwargs.pop("preview", None)
|
|
217
|
+
return self.service.Build.search(**fallback_kwargs)
|
|
218
|
+
|
|
198
219
|
def get_builds_batch(self, build_rids: List[str]) -> Dict[str, Any]:
|
|
199
220
|
"""
|
|
200
221
|
Get multiple builds in batch.
|
|
@@ -155,20 +155,30 @@ class ProjectService(BaseService):
|
|
|
155
155
|
List of project information dictionaries
|
|
156
156
|
"""
|
|
157
157
|
try:
|
|
158
|
-
projects = []
|
|
159
|
-
list_params: Dict[str, Any] = {"preview": True}
|
|
160
|
-
|
|
161
158
|
if space_rid:
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
159
|
+
return self._list_projects_in_parent(
|
|
160
|
+
parent_folder_rid=space_rid,
|
|
161
|
+
page_size=page_size,
|
|
162
|
+
page_token=page_token,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# page_size/page_token are cursor semantics for a single folder listing.
|
|
166
|
+
# They are not meaningful when aggregating projects across all spaces.
|
|
167
|
+
projects_by_rid: Dict[str, Dict[str, Any]] = {}
|
|
168
|
+
for space in self.service.Space.list(preview=True):
|
|
169
|
+
parent_space_rid = getattr(space, "rid", None)
|
|
170
|
+
if not parent_space_rid:
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
projects = self._list_projects_in_parent(
|
|
174
|
+
parent_folder_rid=parent_space_rid
|
|
175
|
+
)
|
|
176
|
+
for project in projects:
|
|
177
|
+
rid = project.get("rid")
|
|
178
|
+
if rid:
|
|
179
|
+
projects_by_rid[rid] = project
|
|
167
180
|
|
|
168
|
-
|
|
169
|
-
for project in self.service.Project.list(**list_params):
|
|
170
|
-
projects.append(self._format_project_info(project))
|
|
171
|
-
return projects
|
|
181
|
+
return list(projects_by_rid.values())
|
|
172
182
|
except Exception as e:
|
|
173
183
|
raise RuntimeError(f"Failed to list projects: {e}")
|
|
174
184
|
|
|
@@ -353,6 +363,14 @@ class ProjectService(BaseService):
|
|
|
353
363
|
Returns:
|
|
354
364
|
Formatted project information dictionary
|
|
355
365
|
"""
|
|
366
|
+
modified_by = getattr(project, "modified_by", None)
|
|
367
|
+
if modified_by is None:
|
|
368
|
+
modified_by = getattr(project, "updated_by", None)
|
|
369
|
+
|
|
370
|
+
modified_time = getattr(project, "modified_time", None)
|
|
371
|
+
if modified_time is None:
|
|
372
|
+
modified_time = getattr(project, "updated_time", None)
|
|
373
|
+
|
|
356
374
|
return {
|
|
357
375
|
"rid": getattr(project, "rid", None),
|
|
358
376
|
"display_name": getattr(project, "display_name", None),
|
|
@@ -363,14 +381,41 @@ class ProjectService(BaseService):
|
|
|
363
381
|
"created_time": self._format_timestamp(
|
|
364
382
|
getattr(project, "created_time", None)
|
|
365
383
|
),
|
|
366
|
-
"modified_by":
|
|
367
|
-
"modified_time": self._format_timestamp(
|
|
368
|
-
getattr(project, "modified_time", None)
|
|
369
|
-
),
|
|
384
|
+
"modified_by": modified_by,
|
|
385
|
+
"modified_time": self._format_timestamp(modified_time),
|
|
370
386
|
"trash_status": getattr(project, "trash_status", None),
|
|
371
387
|
"type": "project",
|
|
372
388
|
}
|
|
373
389
|
|
|
390
|
+
def _list_projects_in_parent(
|
|
391
|
+
self,
|
|
392
|
+
parent_folder_rid: str,
|
|
393
|
+
page_size: Optional[int] = None,
|
|
394
|
+
page_token: Optional[str] = None,
|
|
395
|
+
) -> List[Dict[str, Any]]:
|
|
396
|
+
"""List project resources directly under a parent folder (space)."""
|
|
397
|
+
list_params: Dict[str, Any] = {"preview": True}
|
|
398
|
+
if page_size:
|
|
399
|
+
list_params["page_size"] = page_size
|
|
400
|
+
if page_token:
|
|
401
|
+
list_params["page_token"] = page_token
|
|
402
|
+
|
|
403
|
+
projects: List[Dict[str, Any]] = []
|
|
404
|
+
for resource in self.service.Folder.children(parent_folder_rid, **list_params):
|
|
405
|
+
if self._is_project_resource(resource):
|
|
406
|
+
projects.append(self._format_project_info(resource))
|
|
407
|
+
return projects
|
|
408
|
+
|
|
409
|
+
@staticmethod
|
|
410
|
+
def _is_project_resource(resource: Any) -> bool:
|
|
411
|
+
"""Check whether a filesystem resource is a project."""
|
|
412
|
+
resource_type = str(getattr(resource, "type", "") or "").upper()
|
|
413
|
+
resource_rid = str(getattr(resource, "rid", "") or "")
|
|
414
|
+
# Fallback to canonical project RID prefix when type is missing.
|
|
415
|
+
return resource_type == "PROJECT" or resource_rid.startswith(
|
|
416
|
+
"ri.compass.main.project."
|
|
417
|
+
)
|
|
418
|
+
|
|
374
419
|
def _format_organization_info(self, organization: Any) -> Dict[str, Any]:
|
|
375
420
|
"""
|
|
376
421
|
Format organization information for consistent output.
|