Repository navigation
feat: support overriding HTTP headers and User-Agent (#98) #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| from databusclient.api.utils import ( | ||
| fetch_databus_jsonld, | ||
| get_databus_id_parts_from_file_url, | ||
| get_default_headers, | ||
| ) | ||
|
|
||
|
|
||
|
|
@@ -23,16 +24,18 @@ class DeleteQueue: | |
| Allows adding multiple databus URIs to a queue and executing their deletion in batch. | ||
| """ | ||
|
|
||
| def __init__(self, databus_key: str, manifest_context=None): | ||
| def __init__(self, databus_key: str, manifest_context=None, headers=None): | ||
| """Create a DeleteQueue bound to a given Databus API key. | ||
|
|
||
| Args: | ||
| databus_key: API key used to authenticate deletion requests. | ||
| manifest_context: Optional ManifestContext to record deletion | ||
| outcomes into. Passed through to _delete_list on execute(). | ||
| headers: Optional custom HTTP headers to send with deletion requests. | ||
| """ | ||
| self.databus_key = databus_key | ||
| self.manifest_context = manifest_context | ||
| self.headers = headers | ||
| self.queue: set[str] = set() | ||
|
|
||
| def add_uri(self, databusURI: str): | ||
|
|
@@ -122,6 +125,7 @@ def _delete_resource( | |
| force: bool = False, | ||
| queue: DeleteQueue = None, | ||
| manifest_context=None, | ||
| headers=None, | ||
| ): | ||
| """Delete a single Databus resource (version, artifact, group). | ||
|
|
||
|
|
@@ -159,8 +163,11 @@ def _delete_resource( | |
| return | ||
|
|
||
| print(f"[DELETE] {databusURI}") | ||
| headers = {"accept": "*/*", "X-API-KEY": databus_key} | ||
| response = requests.delete(databusURI, headers=headers, timeout=30) | ||
| req_headers = get_default_headers(headers) | ||
| if "accept" not in req_headers and "Accept" not in req_headers: | ||
| req_headers["accept"] = "*/*" | ||
| req_headers["X-API-KEY"] = databus_key | ||
| response = requests.delete(databusURI, headers=req_headers, timeout=30) | ||
|
|
||
| if response.status_code in (200, 204): | ||
| print(f"Successfully deleted: {databusURI}") | ||
|
|
@@ -179,6 +186,7 @@ def _delete_list( | |
| force: bool = False, | ||
| queue: DeleteQueue = None, | ||
| manifest_context=None, | ||
| headers=None, | ||
| ): | ||
| """Delete a list of Databus resources. | ||
|
|
||
|
|
@@ -191,7 +199,7 @@ def _delete_list( | |
| """ | ||
| for databusURI in databusURIs: | ||
| _delete_resource( | ||
| databusURI, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context | ||
| databusURI, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context, headers=headers | ||
| ) | ||
|
|
||
|
|
||
|
|
@@ -202,6 +210,7 @@ def _delete_artifact( | |
| force: bool = False, | ||
| queue: DeleteQueue = None, | ||
| manifest_context=None, | ||
| headers=None, | ||
| ): | ||
| """Delete an artifact and all its versions. | ||
|
|
||
|
|
@@ -215,7 +224,7 @@ def _delete_artifact( | |
| force: If True, skip confirmation prompt and proceed with deletion. | ||
| queue: If queue is provided, add the URI to the queue instead of deleting immediately. | ||
| """ | ||
| artifact_body = fetch_databus_jsonld(databusURI, databus_key) | ||
| artifact_body = fetch_databus_jsonld(databusURI, databus_key, headers=headers) | ||
|
|
||
| json_dict = json.loads(artifact_body) | ||
| versions = json_dict.get("databus:hasVersion") | ||
|
|
@@ -235,7 +244,7 @@ def _delete_artifact( | |
| else: | ||
| # Delete all versions | ||
| _delete_list( | ||
| version_uris, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context | ||
| version_uris, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context, headers=headers | ||
| ) | ||
|
|
||
| # Finally, delete the artifact itself | ||
|
|
@@ -249,6 +258,7 @@ def _delete_group( | |
| force: bool = False, | ||
| queue: DeleteQueue = None, | ||
| manifest_context=None, | ||
| headers=None, | ||
| ): | ||
| """Delete a group and all its artifacts and versions. | ||
|
|
||
|
|
@@ -262,7 +272,7 @@ def _delete_group( | |
| force: If True, skip confirmation prompt and proceed with deletion. | ||
| queue: If queue is provided, add the URI to the queue instead of deleting immediately. | ||
| """ | ||
| group_body = fetch_databus_jsonld(databusURI, databus_key) | ||
| group_body = fetch_databus_jsonld(databusURI, databus_key, headers=headers) | ||
|
|
||
| json_dict = json.loads(group_body) | ||
| artifacts = json_dict.get("databus:hasArtifact", []) | ||
|
|
@@ -286,7 +296,14 @@ def _delete_group( | |
| _delete_resource(databusURI, databus_key, dry_run=dry_run, force=force, queue=queue,manifest_context=manifest_context) | ||
|
|
||
|
|
||
| def delete(databusURIs: List[str], databus_key: str, dry_run: bool, force: bool, manifest_context=None): | ||
| def delete( | ||
| databusURIs: List[str], | ||
| databus_key: str, | ||
| dry_run: bool = False, | ||
| force: bool = False, | ||
| manifest_context=None, | ||
| headers=None, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pass headers through recursive artifact and group deletion. The public
|
||
| ): | ||
| """Delete a dataset from the databus. | ||
|
|
||
| Delete a group, artifact, or version identified by the given databus URI. | ||
|
|
@@ -299,7 +316,7 @@ def delete(databusURIs: List[str], databus_key: str, dry_run: bool, force: bool, | |
| force: If True, skip confirmation prompt and proceed with deletion. | ||
| """ | ||
|
|
||
| queue = DeleteQueue(databus_key, manifest_context=manifest_context) | ||
| queue = DeleteQueue(databus_key, manifest_context=manifest_context, headers=headers) | ||
|
|
||
| for databusURI in databusURIs: | ||
| _host, _account, group, artifact, version, file = ( | ||
|
|
@@ -309,14 +326,14 @@ def delete(databusURIs: List[str], databus_key: str, dry_run: bool, force: bool, | |
| if group == "collections" and artifact is not None: | ||
| print(f"Deleting collection: {databusURI}") | ||
| _delete_resource( | ||
| databusURI, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context | ||
| databusURI, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context, headers=headers | ||
| ) | ||
| elif file is not None: | ||
| print(f"Deleting file is not supported via API: {databusURI}") | ||
| elif version is not None: | ||
| print(f"Deleting version: {databusURI}") | ||
| _delete_resource( | ||
| databusURI, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context | ||
| databusURI, databus_key, dry_run=dry_run, force=force, queue=queue, manifest_context=manifest_context, headers=headers | ||
| ) | ||
| elif artifact is not None: | ||
| print(f"Deleting artifact and all its versions: {databusURI}") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,12 @@ | |
| import hashlib | ||
| import json | ||
| from enum import Enum | ||
| from typing import Dict, List, Optional, Tuple, Union | ||
| from typing import Any, Dict, Iterable, List, Optional, Tuple, Union | ||
|
|
||
| import requests | ||
|
|
||
| from databusclient.api.utils import get_default_headers | ||
|
|
||
| _debug = False | ||
|
|
||
|
|
||
|
|
@@ -176,14 +178,17 @@ def _get_file_stats(distribution_str: str) -> Tuple[Optional[str], Optional[int] | |
| return sha256sum, content_length | ||
|
|
||
|
|
||
| def _load_file_stats(url: str) -> Tuple[str, int]: | ||
| def _load_file_stats( | ||
| url: str, headers: Union[Dict[str, Any], Iterable[str], None] = None | ||
|
Comment on lines
+181
to
+182
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pass deploy headers into fallback file-stat requests.
|
||
| ) -> Tuple[str, int]: | ||
| """Download the file at ``url`` and compute its SHA-256 and length. | ||
|
|
||
| This is used as a fallback when the caller did not supply checksum/size | ||
| information in the CLI or metadata file. | ||
| """ | ||
|
|
||
| resp = requests.get(url, timeout=30) | ||
| req_headers = get_default_headers(headers) | ||
| resp = requests.get(url, headers=req_headers, timeout=30) | ||
| if resp.status_code >= 400: | ||
| raise requests.exceptions.RequestException(response=resp) | ||
|
|
||
|
|
@@ -463,6 +468,7 @@ def deploy( | |
| verify_parts: bool = False, | ||
| log_level: DeployLogLevel = DeployLogLevel.debug, | ||
| debug: bool = False, | ||
| headers: Union[Dict[str, Any], Iterable[str], None] = None, | ||
| ) -> None: | ||
| """Deploys a dataset to the databus. The endpoint is inferred from the DataID identifier. | ||
| Parameters | ||
|
|
@@ -479,7 +485,10 @@ def deploy( | |
| controls whether output shold be printed to the console (stdout) | ||
| """ | ||
|
|
||
| headers = {"X-API-KEY": f"{api_key}", "Content-Type": "application/json"} | ||
| req_headers = get_default_headers(headers) | ||
| req_headers["X-API-KEY"] = f"{api_key}" | ||
| if "Content-Type" not in req_headers: | ||
| req_headers["Content-Type"] = "application/json" | ||
| data = json.dumps(dataid) | ||
|
|
||
| try: | ||
|
|
@@ -491,7 +500,7 @@ def deploy( | |
| base | ||
| + f"/api/publish?verify-parts={str(verify_parts).lower()}&log-level={log_level.name}" | ||
| ) | ||
| resp = requests.post(api_uri, data=data, headers=headers, timeout=30) | ||
| resp = requests.post(api_uri, data=data, headers=req_headers, timeout=30) | ||
|
|
||
| if debug or _debug: | ||
| try: | ||
|
|
@@ -517,6 +526,7 @@ def deploy_from_metadata( | |
| artifact_version_description: str, | ||
| license_url: str, | ||
| apikey: str, | ||
| headers: Union[Dict[str, Any], Iterable[str], None] = None, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forward metadata deploy headers to
|
||
| ) -> None: | ||
| """ | ||
| Deploy a dataset from metadata entries. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forward stored headers when executing the delete queue.
DeleteQueuestoresheaders, butexecute()does not passself.headersto_delete_list. Normal deletion queues each URI before issuing its DELETE requests. Those requests therefore never receive CLI, API, or workflow header overrides. Passheaders=self.headersfromexecute().