pltr-cli 0.8.0__tar.gz → 0.9.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.8.0 → pltr_cli-0.9.0}/PKG-INFO +1 -1
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/pyproject.toml +1 -1
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/scripts/release.py +26 -8
- pltr_cli-0.9.0/src/pltr/__init__.py +1 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/dataset.py +55 -2
- pltr_cli-0.9.0/src/pltr/services/base.py +129 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/dataset.py +27 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/uv.lock +1 -1
- pltr_cli-0.8.0/src/pltr/__init__.py +0 -1
- pltr_cli-0.8.0/src/pltr/services/base.py +0 -62
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/.github/workflows/ci.yml +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/.github/workflows/publish.yml +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/.github/workflows/test-publish.yml +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/.gitignore +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/.pre-commit-config.yaml +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/CHANGELOG.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/CLAUDE.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/LICENSE +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/README.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/RELEASE.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/children.csv +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/README.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/api/wrapper.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/examples/csv-upload.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/examples/gallery.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/features/dataset-transactions.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/user-guide/aliases.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/user-guide/authentication.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/user-guide/commands.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/user-guide/quick-start.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/user-guide/troubleshooting.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/docs/user-guide/workflows.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/folder_info.json +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/folders.json +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/mypy.ini +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/__main__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/auth/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/auth/base.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/auth/manager.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/auth/oauth.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/auth/storage.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/auth/token.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/cli.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/admin.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/alias.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/completion.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/configure.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/connectivity.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/folder.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/mediasets.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/ontology.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/orchestration.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/project.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/resource.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/resource_role.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/shell.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/space.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/sql.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/commands/verify.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/config/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/config/aliases.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/config/profiles.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/config/settings.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/admin.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/connectivity.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/folder.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/mediasets.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/ontology.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/orchestration.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/project.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/resource.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/resource_role.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/space.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/services/sql.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/utils/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/utils/alias_resolver.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/utils/completion.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/utils/formatting.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/src/pltr/utils/progress.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/conftest.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/README.md +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/conftest.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/test_auth_flow.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/test_cli_integration.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/test_data_workflows.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/test_data_workflows_simple.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/integration/test_simple_integration.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_auth/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_auth/test_base.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_auth/test_manager.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_auth/test_oauth.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_auth/test_storage.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_auth/test_token.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_admin.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_alias.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_completion.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_connectivity.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_dataset.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_folder.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_ontology.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_orchestration.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_shell.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_sql.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_commands/test_verify_simple.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_config/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_config/test_aliases.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_config/test_profiles.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_config/test_settings.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_admin.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_base.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_connectivity.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_dataset.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_dataset_transactions.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_folder.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_ontology.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_orchestration.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_project.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_resource.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_resource_role.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_space.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_services/test_sql.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_utils/__init__.py +0 -0
- {pltr_cli-0.8.0 → pltr_cli-0.9.0}/tests/test_utils/test_alias_resolver.py +0 -0
|
@@ -152,10 +152,25 @@ def check_tag_exists(version):
|
|
|
152
152
|
return False
|
|
153
153
|
|
|
154
154
|
|
|
155
|
+
def update_uv_lock():
|
|
156
|
+
"""Update uv.lock file after version change"""
|
|
157
|
+
try:
|
|
158
|
+
subprocess.run(["uv", "lock"], check=True, capture_output=True, text=True)
|
|
159
|
+
print("Updated uv.lock file")
|
|
160
|
+
return True
|
|
161
|
+
except subprocess.CalledProcessError as e:
|
|
162
|
+
print(f"Error updating uv.lock: {e.stderr}")
|
|
163
|
+
return False
|
|
164
|
+
except FileNotFoundError:
|
|
165
|
+
print("Warning: uv command not found. Skipping uv.lock update.")
|
|
166
|
+
print("Please ensure uv is installed to keep lock file in sync.")
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
|
|
155
170
|
def create_release_commit_and_tag(version, release_type, push_mode="ask"):
|
|
156
171
|
"""Create release commit and tag"""
|
|
157
172
|
# Stage the version file changes
|
|
158
|
-
run_git_command("git add pyproject.toml src/pltr/__init__.py")
|
|
173
|
+
run_git_command("git add pyproject.toml src/pltr/__init__.py uv.lock")
|
|
159
174
|
|
|
160
175
|
# Create release commit
|
|
161
176
|
commit_message = f"{release_type}: Release version {version}"
|
|
@@ -308,9 +323,10 @@ def main():
|
|
|
308
323
|
print("\nDry run mode - would perform these actions:")
|
|
309
324
|
print(f"1. Update pyproject.toml version to {new_version}")
|
|
310
325
|
print(f"2. Update src/pltr/__init__.py __version__ to {new_version}")
|
|
311
|
-
print(
|
|
312
|
-
print(f"4. Create git
|
|
313
|
-
print("5.
|
|
326
|
+
print("3. Update uv.lock file")
|
|
327
|
+
print(f"4. Create git commit: '{release_type}: Release version {new_version}'")
|
|
328
|
+
print(f"5. Create git tag: v{new_version}")
|
|
329
|
+
print("6. Optionally push to origin")
|
|
314
330
|
return
|
|
315
331
|
|
|
316
332
|
# Check git status
|
|
@@ -335,13 +351,14 @@ def main():
|
|
|
335
351
|
print("This will:")
|
|
336
352
|
print(f"1. Update pyproject.toml version to {new_version}")
|
|
337
353
|
print(f"2. Update src/pltr/__init__.py __version__ to {new_version}")
|
|
338
|
-
print(
|
|
354
|
+
print("3. Update uv.lock file")
|
|
355
|
+
print(f"4. Create git commit and tag v{new_version}")
|
|
339
356
|
if args.push:
|
|
340
|
-
print("
|
|
357
|
+
print("5. Push to origin to trigger GitHub Actions publishing")
|
|
341
358
|
elif args.no_push:
|
|
342
|
-
print("
|
|
359
|
+
print("5. NOT push to origin (--no-push specified)")
|
|
343
360
|
else:
|
|
344
|
-
print("
|
|
361
|
+
print("5. Optionally push to trigger GitHub Actions publishing")
|
|
345
362
|
|
|
346
363
|
if not args.yes:
|
|
347
364
|
confirm = input("\nProceed with release? (y/N): ").strip().lower()
|
|
@@ -362,6 +379,7 @@ def main():
|
|
|
362
379
|
# Perform release
|
|
363
380
|
update_version_in_pyproject(new_version)
|
|
364
381
|
update_version_in_init_py(new_version)
|
|
382
|
+
update_uv_lock() # Update uv.lock with new version
|
|
365
383
|
create_release_commit_and_tag(new_version, release_type, push_mode)
|
|
366
384
|
|
|
367
385
|
print(f"\n✅ Release {new_version} created successfully!")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.9.0"
|
|
@@ -93,11 +93,17 @@ def get_schema(
|
|
|
93
93
|
None, "--output", "-o", help="Output file path"
|
|
94
94
|
),
|
|
95
95
|
):
|
|
96
|
-
"""Get the schema of a dataset."""
|
|
96
|
+
"""Get the schema of a dataset (requires API preview access)."""
|
|
97
97
|
try:
|
|
98
98
|
cache_rid(dataset_rid)
|
|
99
99
|
service = DatasetService(profile=profile)
|
|
100
100
|
|
|
101
|
+
formatter.print_warning(
|
|
102
|
+
"Note: This command requires API preview access. "
|
|
103
|
+
"If you encounter an 'ApiFeaturePreviewUsageOnly' error, "
|
|
104
|
+
"use 'pltr dataset schema apply' instead to infer/apply schema."
|
|
105
|
+
)
|
|
106
|
+
|
|
101
107
|
with SpinnerProgressTracker().track_spinner(
|
|
102
108
|
f"Fetching schema for {dataset_rid}..."
|
|
103
109
|
):
|
|
@@ -120,7 +126,54 @@ def get_schema(
|
|
|
120
126
|
formatter.print_error(f"Authentication error: {e}")
|
|
121
127
|
raise typer.Exit(1)
|
|
122
128
|
except Exception as e:
|
|
123
|
-
|
|
129
|
+
if "ApiFeaturePreviewUsageOnly" in str(e):
|
|
130
|
+
formatter.print_error(
|
|
131
|
+
"This command requires API preview access. "
|
|
132
|
+
"Please use 'pltr dataset schema apply' instead."
|
|
133
|
+
)
|
|
134
|
+
else:
|
|
135
|
+
formatter.print_error(f"Failed to get schema: {e}")
|
|
136
|
+
raise typer.Exit(1)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@schema_app.command("apply")
|
|
140
|
+
def apply_schema(
|
|
141
|
+
dataset_rid: str = typer.Argument(
|
|
142
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
143
|
+
),
|
|
144
|
+
branch: str = typer.Option("master", "--branch", "-b", help="Dataset branch name"),
|
|
145
|
+
profile: Optional[str] = typer.Option(
|
|
146
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
147
|
+
),
|
|
148
|
+
format: str = typer.Option(
|
|
149
|
+
"table",
|
|
150
|
+
"--format",
|
|
151
|
+
"-f",
|
|
152
|
+
help="Output format (table, json, csv)",
|
|
153
|
+
autocompletion=complete_output_format,
|
|
154
|
+
),
|
|
155
|
+
):
|
|
156
|
+
"""Apply/infer schema for a dataset."""
|
|
157
|
+
try:
|
|
158
|
+
cache_rid(dataset_rid)
|
|
159
|
+
service = DatasetService(profile=profile)
|
|
160
|
+
|
|
161
|
+
with SpinnerProgressTracker().track_spinner(
|
|
162
|
+
f"Applying schema to dataset {dataset_rid} on branch '{branch}'..."
|
|
163
|
+
):
|
|
164
|
+
result = service.apply_schema(dataset_rid, branch)
|
|
165
|
+
|
|
166
|
+
formatter.print_success(f"Schema applied successfully to branch '{branch}'")
|
|
167
|
+
|
|
168
|
+
# Display result if available
|
|
169
|
+
if result.get("result"):
|
|
170
|
+
formatter._format_json(result.get("result"))
|
|
171
|
+
|
|
172
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
173
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
174
|
+
raise typer.Exit(1)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
formatter.print_error(f"Failed to apply schema: {e}")
|
|
124
177
|
raise typer.Exit(1)
|
|
125
178
|
|
|
126
179
|
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base service class for Foundry API wrappers.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional, Dict
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from ..auth.manager import AuthManager
|
|
10
|
+
from ..auth.storage import CredentialStorage
|
|
11
|
+
from ..config.profiles import ProfileManager
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseService(ABC):
|
|
15
|
+
"""Base class for Foundry service wrappers."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, profile: Optional[str] = None):
|
|
18
|
+
"""
|
|
19
|
+
Initialize base service.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
profile: Authentication profile name (uses default if not specified)
|
|
23
|
+
"""
|
|
24
|
+
self.profile = profile
|
|
25
|
+
self.auth_manager = AuthManager()
|
|
26
|
+
self._client: Optional[Any] = None
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def client(self) -> Any:
|
|
30
|
+
"""
|
|
31
|
+
Get authenticated Foundry client.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Configured FoundryClient instance
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
ProfileNotFoundError: If profile doesn't exist
|
|
38
|
+
MissingCredentialsError: If credentials are incomplete
|
|
39
|
+
"""
|
|
40
|
+
if self._client is None:
|
|
41
|
+
self._client = self.auth_manager.get_client(self.profile)
|
|
42
|
+
return self._client
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def _get_service(self) -> Any:
|
|
46
|
+
"""
|
|
47
|
+
Get the specific Foundry SDK service instance.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Configured service instance from foundry-platform-sdk
|
|
51
|
+
|
|
52
|
+
This method should be implemented by subclasses to return the
|
|
53
|
+
appropriate service (e.g., client.datasets, client.ontology)
|
|
54
|
+
"""
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def service(self) -> Any:
|
|
59
|
+
"""
|
|
60
|
+
Get the Foundry SDK service instance.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Configured service instance
|
|
64
|
+
"""
|
|
65
|
+
return self._get_service()
|
|
66
|
+
|
|
67
|
+
def _make_request(
|
|
68
|
+
self,
|
|
69
|
+
method: str,
|
|
70
|
+
endpoint: str,
|
|
71
|
+
data: Optional[Dict] = None,
|
|
72
|
+
json_data: Optional[Dict] = None,
|
|
73
|
+
headers: Optional[Dict] = None,
|
|
74
|
+
) -> requests.Response:
|
|
75
|
+
"""
|
|
76
|
+
Make a direct HTTP request to Foundry API.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
method: HTTP method (GET, POST, PUT, DELETE)
|
|
80
|
+
endpoint: API endpoint path (e.g., '/foundry-schema-inference/api/...')
|
|
81
|
+
data: Form data to send
|
|
82
|
+
json_data: JSON data to send
|
|
83
|
+
headers: Additional headers
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Response object
|
|
87
|
+
|
|
88
|
+
Raises:
|
|
89
|
+
requests.HTTPError: If request fails
|
|
90
|
+
"""
|
|
91
|
+
# Get credentials for authentication
|
|
92
|
+
storage = CredentialStorage()
|
|
93
|
+
profile_manager = ProfileManager()
|
|
94
|
+
profile_name = self.profile or profile_manager.get_active_profile()
|
|
95
|
+
if not profile_name:
|
|
96
|
+
from ..auth.base import ProfileNotFoundError
|
|
97
|
+
|
|
98
|
+
raise ProfileNotFoundError(
|
|
99
|
+
"No profile specified and no default profile configured. "
|
|
100
|
+
"Run 'pltr configure configure' to set up authentication."
|
|
101
|
+
)
|
|
102
|
+
credentials = storage.get_profile(profile_name)
|
|
103
|
+
|
|
104
|
+
# Build full URL
|
|
105
|
+
host = credentials.get("host", "").rstrip("/")
|
|
106
|
+
url = f"{host}{endpoint}"
|
|
107
|
+
|
|
108
|
+
# Set up headers with authentication
|
|
109
|
+
request_headers = {
|
|
110
|
+
"Authorization": f"Bearer {credentials.get('token')}",
|
|
111
|
+
"Content-Type": "application/json",
|
|
112
|
+
"Accept": "application/json",
|
|
113
|
+
}
|
|
114
|
+
if headers:
|
|
115
|
+
request_headers.update(headers)
|
|
116
|
+
|
|
117
|
+
# Make the request
|
|
118
|
+
response = requests.request(
|
|
119
|
+
method=method,
|
|
120
|
+
url=url,
|
|
121
|
+
data=data,
|
|
122
|
+
json=json_data,
|
|
123
|
+
headers=request_headers,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Raise an error for bad status codes
|
|
127
|
+
response.raise_for_status()
|
|
128
|
+
|
|
129
|
+
return response
|
|
@@ -56,6 +56,33 @@ class DatasetService(BaseService):
|
|
|
56
56
|
except Exception as e:
|
|
57
57
|
raise RuntimeError(f"Failed to get schema for dataset {dataset_rid}: {e}")
|
|
58
58
|
|
|
59
|
+
def apply_schema(self, dataset_rid: str, branch: str = "master") -> Dict[str, Any]:
|
|
60
|
+
"""
|
|
61
|
+
Apply/infer schema for a dataset using the schema inference API.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
dataset_rid: Dataset Resource Identifier
|
|
65
|
+
branch: Dataset branch name (default: "master")
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Schema inference result
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
endpoint = f"/foundry-schema-inference/api/datasets/{dataset_rid}/branches/{branch}/schema"
|
|
72
|
+
response = self._make_request("POST", endpoint, json_data={})
|
|
73
|
+
|
|
74
|
+
# Parse the response
|
|
75
|
+
result = response.json() if response.text else {}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
"dataset_rid": dataset_rid,
|
|
79
|
+
"branch": branch,
|
|
80
|
+
"status": "Schema applied successfully",
|
|
81
|
+
"result": result,
|
|
82
|
+
}
|
|
83
|
+
except Exception as e:
|
|
84
|
+
raise RuntimeError(f"Failed to apply schema for dataset {dataset_rid}: {e}")
|
|
85
|
+
|
|
59
86
|
def put_schema(
|
|
60
87
|
self,
|
|
61
88
|
dataset_rid: str,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.8.0"
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Base service class for Foundry API wrappers.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from typing import Any, Optional
|
|
6
|
-
from abc import ABC, abstractmethod
|
|
7
|
-
|
|
8
|
-
from ..auth.manager import AuthManager
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class BaseService(ABC):
|
|
12
|
-
"""Base class for Foundry service wrappers."""
|
|
13
|
-
|
|
14
|
-
def __init__(self, profile: Optional[str] = None):
|
|
15
|
-
"""
|
|
16
|
-
Initialize base service.
|
|
17
|
-
|
|
18
|
-
Args:
|
|
19
|
-
profile: Authentication profile name (uses default if not specified)
|
|
20
|
-
"""
|
|
21
|
-
self.profile = profile
|
|
22
|
-
self.auth_manager = AuthManager()
|
|
23
|
-
self._client: Optional[Any] = None
|
|
24
|
-
|
|
25
|
-
@property
|
|
26
|
-
def client(self) -> Any:
|
|
27
|
-
"""
|
|
28
|
-
Get authenticated Foundry client.
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
Configured FoundryClient instance
|
|
32
|
-
|
|
33
|
-
Raises:
|
|
34
|
-
ProfileNotFoundError: If profile doesn't exist
|
|
35
|
-
MissingCredentialsError: If credentials are incomplete
|
|
36
|
-
"""
|
|
37
|
-
if self._client is None:
|
|
38
|
-
self._client = self.auth_manager.get_client(self.profile)
|
|
39
|
-
return self._client
|
|
40
|
-
|
|
41
|
-
@abstractmethod
|
|
42
|
-
def _get_service(self) -> Any:
|
|
43
|
-
"""
|
|
44
|
-
Get the specific Foundry SDK service instance.
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
Configured service instance from foundry-platform-sdk
|
|
48
|
-
|
|
49
|
-
This method should be implemented by subclasses to return the
|
|
50
|
-
appropriate service (e.g., client.datasets, client.ontology)
|
|
51
|
-
"""
|
|
52
|
-
pass
|
|
53
|
-
|
|
54
|
-
@property
|
|
55
|
-
def service(self) -> Any:
|
|
56
|
-
"""
|
|
57
|
-
Get the Foundry SDK service instance.
|
|
58
|
-
|
|
59
|
-
Returns:
|
|
60
|
-
Configured service instance
|
|
61
|
-
"""
|
|
62
|
-
return self._get_service()
|
|
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
|
|
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
|
|
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
|
|
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
|