feat: replace CordraPy with http requests

This commit is contained in:
daniel
2025-06-29 14:47:43 +02:00
parent cc06e1eace
commit 53cbb53178
6 changed files with 111 additions and 102 deletions

View File

@@ -1,12 +1,15 @@
"""Cordra client wrapper using CordraPy."""
"""Cordra client wrapper using HTTP requests."""
import logging
from typing import Any
import cordra
import requests
from pydantic import BaseModel, Field
from .config import CordraConfig
logger = logging.getLogger(__name__)
class DigitalObject(BaseModel):
"""Model for a Cordra digital object."""
@@ -30,7 +33,7 @@ class CordraNotFoundError(CordraClientError):
class CordraClient:
"""Client for interacting with Cordra repository."""
"""Client for interacting with Cordra repository using HTTP requests."""
def __init__(self, config: CordraConfig) -> None:
"""Initialize the Cordra client.
@@ -39,6 +42,14 @@ class CordraClient:
config: Configuration settings for the Cordra connection
"""
self.config = config
self.session = requests.Session()
self.session.verify = config.verify_ssl
# Set up authentication
if config.username and config.password:
self.session.auth = (config.username, config.password)
elif config.username or config.password:
logger.warning("Only username or password provided, not both. Authentication may fail.")
async def get_object(self, object_id: str) -> DigitalObject:
"""Retrieve a digital object by its ID.
@@ -54,28 +65,34 @@ class CordraClient:
CordraClientError: For other API errors
"""
try:
cordra_obj: dict[str, Any] = cordra.CordraObject.read(
host=self.config.cordra_url, #type: ignore
obj_id=object_id,
username=self.config.username,
password=self.config.password,
verify=self.config.verify_ssl,
full=True # Get full object details including metadata, paylods, etc.
)
# Build URL: cordra_base_url/objects/prefix/postfix
url = f"{self.config.cordra_url}/objects/{object_id}"
# Add full=true parameter to get complete object details
params = {"full": "true"}
response = self.session.get(url, params=params, timeout=self.config.timeout)
if response.status_code == 404:
raise CordraNotFoundError(f"Object not found: {object_id}")
response.raise_for_status()
cordra_obj = response.json()
return DigitalObject(
id=object_id,
type=cordra_obj['type'],
content=cordra_obj['content'],
type=cordra_obj.get('type', ''),
content=cordra_obj.get('content', cordra_obj),
metadata=cordra_obj.get('metadata'),
acl=cordra_obj.get('acl'),
payloads=cordra_obj.get('payloads'),
)
except CordraNotFoundError:
raise
except requests.RequestException as e:
raise CordraClientError(f"Failed to retrieve object {object_id}: {e}") from e
except Exception as e:
error_msg = str(e).lower()
if 'not found' in error_msg or '404' in error_msg:
raise CordraNotFoundError(f"Object not found: {object_id}") from e
raise CordraClientError(f"Failed to retrieve object {object_id}: {e}") from e
async def find(self, query: str) -> list[dict[str, Any]]:
@@ -91,19 +108,22 @@ class CordraClient:
CordraClientError: If there's an API error
"""
try:
# Use CordraPy to find objects
# TODO - need to handle pagination, but the CordraPy API does not support it.
response: dict[str, Any] = cordra.CordraObject.find(
self.config.cordra_url, # type: ignore
query
)
# Use HTTP GET request to search endpoint
url = f"{self.config.cordra_url}/search"
params = {"query": query}
response = self.session.get(url, params=params, timeout=self.config.timeout)
response.raise_for_status()
search_result = response.json()
# Extract the results array from the response
if isinstance(response, dict) and 'results' in response:
return response['results']
if isinstance(search_result, dict) and 'results' in search_result:
return search_result['results']
else:
return []
except Exception as e:
except requests.RequestException as e:
raise CordraClientError(f"Failed to search with query '{query}': {e}") from e
except Exception as e:
raise CordraClientError(f"Failed to search with query '{query}': {e}") from e

View File

@@ -59,8 +59,8 @@ async def list_cordra_schemas() -> str:
# Extract the names from the schema objects
schema_names = []
for schema in schemas:
if isinstance(schema, dict) and 'name' in schema:
schema_names.append(schema['name'])
if isinstance(schema, dict) and 'content' in schema and 'name' in schema['content']:
schema_names.append(schema['content']['name'])
result = {
"schemas": schema_names,