ada package
Subpackages
- ada.services package
- Submodules
- ada.services.checksum module
- ada.services.events module
- ada.services.labels module
- ada.services.namespace module
NamespaceServiceNamespaceService.delete()NamespaceService.get_file_type()NamespaceService.get_files_in_dir()NamespaceService.get_pnfs_id()NamespaceService.get_subdirs()NamespaceService.is_dir()NamespaceService.is_online()NamespaceService.list()NamespaceService.longlist()NamespaceService.mkdir()NamespaceService.mv()NamespaceService.stat()NamespaceService.with_files_in_dir()
- ada.services.staging module
- ada.services.system module
- ada.services.xattr module
- Module contents
Submodules
ada.api module
Low-level HTTP client for the dCache REST API.
Wraps httpx and provides:
- URL encoding of dCache paths
- JSON response parsing
- HTTP status code to exception mapping
- Debug logging of all requests
- SSE streaming support
- class ada.api.DcacheAPI(base_url: str, auth: AuthProvider, debug: bool = False)
Bases:
objectLow-level HTTP client for the dCache REST API.
All service modules use this client to make API calls. It handles authentication, error mapping, and optional debug logging.
- close() None
Close the underlying HTTP client.
- delete(endpoint: str) Any
Perform a DELETE request.
- static encode_path(path: str) str
URL-encode a dCache namespace path.
- get(endpoint: str, params: dict[str, str] | None = None, accept: str = 'application/json') Any
Perform a GET request.
- patch(endpoint: str, json: dict[str, Any] | None = None) Any
Perform a PATCH request.
- post(endpoint: str, json: dict[str, Any] | None = None, data: str | None = None, content_type: str = 'application/json', accept: str = 'application/json') Any
Perform a POST request.
- post_raw(endpoint: str, json: dict[str, Any] | None = None) Response
POST that returns the raw httpx.Response (for bulk requests needing headers).
- stream_sse(endpoint: str, last_event_id: str | None = None, timeout: int = 3600) Iterator[dict[str, str]]
Open an SSE connection and yield parsed events.
Each yielded dict has keys:
event,data,id(all optional).
ada.auth module
Authentication providers for ADA.
Implements the strategy pattern with an abstract AuthProvider base
and concrete implementations for token, netrc, and proxy authentication.
- Precedence (matching Bash):
Explicit arguments (highest)
Environment variables
Config file values (lowest)
- class ada.auth.AuthProvider
Bases:
ABCAbstract base for all authentication methods.
- get_httpx_auth() Any
Return an httpx auth object, if applicable (e.g., BasicAuth).
- get_ssl_context() Any
Return an SSL context for client certificate auth, if applicable.
- abstractmethod headers() dict[str, str]
Return HTTP headers for authentication.
- abstractmethod method_name() str
Human-readable name like ‘token’, ‘netrc’, ‘proxy’.
- validate(command: str | None = None) None
Validate credentials before use. Override in subclasses.
- view_token() dict[str, Any]
Decode and return token properties for display.
- class ada.auth.NetrcAuth(netrcfile: str | None = None, hostname: str | None = None)
Bases:
AuthProviderNetrc-based username/password (Basic) authentication.
- get_httpx_auth() Any
Parse netrc and return httpx BasicAuth for the API host.
- headers() dict[str, str]
Return HTTP headers for authentication.
- method_name() str
Human-readable name like ‘token’, ‘netrc’, ‘proxy’.
- class ada.auth.ProxyAuth(proxyfile: str | None = None, certdir: str | None = None, igtf: bool = True)
Bases:
AuthProviderX.509 proxy certificate authentication.
- get_ssl_context() Any
Return an SSL context configured with the proxy certificate.
- headers() dict[str, str]
Return HTTP headers for authentication.
- method_name() str
Human-readable name like ‘token’, ‘netrc’, ‘proxy’.
- class ada.auth.TokenAuth(token: str, source: str = 'direct')
Bases:
AuthProviderBearer token authentication (JWT/OIDC or Macaroon).
- headers() dict[str, str]
Return HTTP headers for authentication.
- method_name() str
Human-readable name like ‘token’, ‘netrc’, ‘proxy’.
- validate(command: str | None = None) None
Validate credentials before use. Override in subclasses.
- view_token() dict[str, Any]
Decode and return token properties for display.
- class ada.auth.TokenFileAuth(tokenfile: str)
Bases:
TokenAuthReads token from a file (rclone config format or plain bearer token).
- ada.auth.decode_jwt(token: str) dict[str, Any]
Decode a JWT and return payload with human-readable timestamps.
Converts
exp,nbf, andiatfields from Unix timestamps to ISO 8601 strings (matching the Bashjq .exp |= todatebehavior).
- ada.auth.decode_jwt_payload(token: str) dict[str, Any]
Decode the payload section of a JWT token.
Does NOT verify the signature — this is for inspection only, matching the Bash version’s behavior.
- Returns:
Decoded payload as a dict.
- Raises:
AdaAuthError: If the token cannot be decoded.
- ada.auth.decode_macaroon(token: str) dict[str, str]
Decode a Macaroon and return its properties as a dict.
Parses the decoded text for known fields like
before:,activity:,path:,id:, etc.
- ada.auth.decode_macaroon_raw(token: str) str
Decode a Macaroon token to its raw text representation.
- Replicates the Bash decoding logic:
base64 -d | awk ‘{print substr($0, 5)}’ | grep -v ‘signature’ | tr -d ‘0’
- Returns:
Decoded macaroon text (caveats, etc.).
- Raises:
AdaAuthError: If the token cannot be decoded.
- ada.auth.extract_macaroon_expiry(decoded_text: str) int | None
Extract the expiration timestamp from decoded Macaroon text.
Looks for
before:caveat with ISO 8601 timestamp.- Returns:
Unix timestamp as int, or None if not found.
- ada.auth.get_jwt_expiry(token: str) int | None
Extract the expiration timestamp (exp) from a JWT.
- Returns:
Unix timestamp as int, or None if not present.
- ada.auth.get_jwt_scope(token: str) str
Extract the scope claim from a JWT.
- Returns:
The scope string, or empty string if not present.
- ada.auth.is_jwt(token: str) bool
Check if a token looks like a JWT (three dot-separated base64url parts).
- ada.auth.is_macaroon(token: str) bool
Check if a token looks like a Macaroon (not a JWT).
- ada.auth.resolve_auth(token: str | None = None, tokenfile: str | None = None, netrc: str | None = None, proxy: str | None = None, config: AdaConfig | None = None) AuthProvider
Resolve authentication method from args, env vars, and config.
- Precedence (from high to low):
Explicit arguments (token, tokenfile, netrc, proxy)
Environment variables ($BEARER_TOKEN, $ada_tokenfile, $ada_netrcfile)
Config file values (tokenfile, netrcfile)
- Raises:
AdaAuthError: If no authentication method can be resolved.
- ada.auth.validate_token(token: str, source: str = '', command: str | None = None) None
Validate a token (JWT or Macaroon) for expiry and permissions.
- Args:
token: The raw token string. source: Description of where the token came from (for error messages). command: The command being executed (e.g., “stage”), used to check
command-specific permissions.
- Raises:
AdaTokenExpiredError: If the token has expired or is about to expire. AdaTokenPermissionError: If the token lacks required permissions. AdaAuthError: If the token cannot be decoded.
ada.client module
AdaClient: main entry point for using ADA as a library.
Composes all services and provides a high-level interface for interacting with dCache. Fully independent of the CLI layer.
Usage:
from ada import AdaClient
with AdaClient(api="https://...", tokenfile="/path/to/token") as client:
files = client.list("/pnfs/data/mydir")
client.stage("/pnfs/data/mydir/file.dat", lifetime="7D")
info = client.whoami()
- class ada.client.AdaClient(api: str | None = None, tokenfile: str | None = None, token: str | None = None, netrc: str | None = None, proxy: str | None = None, igtf: bool = True, config_paths: list[str] | None = None, debug: bool = False)
Bases:
objectHigh-level client for the dCache REST API.
Can be used as a context manager for automatic cleanup:
with AdaClient(...) as client: client.list("/data")
- checksum(paths: str | list[str] | None = None, recursive: bool = False, from_file: str | None = None) list[Checksum]
Get checksums for file(s).
- close() None
Close the underlying HTTP client.
- delete(path: str, recursive: bool = False, force: bool = False) None
Delete a file or directory.
- delete_request(request_id: str) None
Delete a bulk request.
- find_label(path: str, regex: str, recursive: bool = False) list[tuple[str, list[str]]]
Find files with labels matching a regex.
- find_xattr(path: str, key: str, regex: str, recursive: bool = False, all_keys: bool = False) list[tuple[str, dict[str, str]]]
Find files with extended attributes matching a regex.
- list(path: str) list[str]
List directory contents.
- list_labels(path: str, label: str | None = None) list[str]
List labels attached to a file.
- list_xattr(path: str, key: str | None = None) dict[str, str]
List extended attributes of a file.
- longlist(paths: str | list[str] | None = None, from_file: str | None = None) list[FileInfo]
Get detailed file listing.
- mkdir(path: str, recursive: bool = False) str
Create a directory.
- mv(source: str, destination: str) str
Move or rename a file/directory.
- remove_label(path: str, label: str = '', all_labels: bool = False) str
Remove label(s) from a file.
- remove_xattr(path: str, key: str = '', all_keys: bool = False) str
Remove extended attribute(s) from a file.
- set_label(path: str, label: str) str
Attach a label to a file.
- set_xattr(path: str, attributes: dict[str, str] | str) str
Set extended attributes on a file.
- stage(paths: str | list[str] | None = None, recursive: bool = False, lifetime: str = '7D', from_file: str | None = None) BulkRequest
Stage files from tape to disk.
- stat_request(request_id: str) BulkRequestStatus
Get bulk request status.
- unstage(paths: str | list[str] | None = None, recursive: bool = False, request_id: str | None = None, from_file: str | None = None) BulkRequest
Unstage files — release disk pins.
- view_token() dict
Decode and display the current token.
ada.config module
Configuration loading for ADA.
Supports the same key=value file format as the Bash version so that
existing ~/.ada/ada.conf files continue to work without changes.
- Precedence (lowest to highest):
Bundled default config (<package>/etc/ada.conf)
System-wide config (/etc/ada.conf)
User config (~/.ada/ada.conf)
Environment variables (ada_api, ada_debug, etc.)
Constructor arguments (handled by caller)
- class ada.config.AdaConfig(api: str = '', debug: bool = False, igtf: bool = True, channel_timeout: int = 3600, tokenfile: str | None = None, netrcfile: str | None = None, curl_options: list[str] = <factory>)
Bases:
objectConfiguration for ADA, assembled from files + env + CLI args.
- api: str = ''
- channel_timeout: int = 3600
- curl_options: list[str]
- debug: bool = False
- igtf: bool = True
- netrcfile: str | None = None
- tokenfile: str | None = None
- validate() None
Validate configuration values.
- Raises:
AdaConfigError: If the API URL is set but has an invalid format.
ada.exceptions module
Exception hierarchy for ADA.
All exceptions inherit from AdaError, allowing callers to catch broad or specific error categories as needed.
- exception ada.exceptions.AdaAPIError(message: str, status_code: int = 0, response_body: str = '')
Bases:
AdaErrordCache API returned an error.
- exception ada.exceptions.AdaAuthError
Bases:
AdaErrorAuthentication setup error (missing file, invalid format).
- exception ada.exceptions.AdaAuthenticationError
Bases:
AdaErrorServer rejected credentials (HTTP 401).
- exception ada.exceptions.AdaError
Bases:
ExceptionBase exception for all ADA errors.
- exception ada.exceptions.AdaForbiddenError(message: str, response_body: str = '')
Bases:
AdaAPIErrorAccess forbidden (HTTP 403).
- exception ada.exceptions.AdaNotFoundError(message: str)
Bases:
AdaAPIErrorResource not found (HTTP 404).
- exception ada.exceptions.AdaSecurityError
Bases:
AdaErrorSecurity violation (e.g., world-readable credentials).
- exception ada.exceptions.AdaTokenExpiredError(message: str, seconds_ago: int = 0)
Bases:
AdaAuthErrorToken has expired or is about to expire.
- exception ada.exceptions.AdaTokenPermissionError
Bases:
AdaAuthErrorToken lacks required permissions (e.g., storage.stage).
ada.models module
Data models for ADA.
All models are frozen dataclasses representing dCache API entities.
- class ada.models.BulkRequest(request_id: str, request_url: str, activity: str, targets: tuple[str, ...] = ())
Bases:
objectResult of a bulk (stage/unstage) operation.
- activity: str
- request_id: str
- request_url: str
- targets: tuple[str, ...] = ()
- class ada.models.BulkRequestStatus(uid: str, status: str, targets: tuple[dict, ...]=(), raw: dict = <factory>)
Bases:
objectStatus of a bulk request.
- raw: dict
- status: str
- targets: tuple[dict, ...] = ()
- uid: str
- class ada.models.Channel(channel_id: str, channel_url: str, name: str | None = None, timeout: int | None = None)
Bases:
objectSSE event channel.
- channel_id: str
- channel_url: str
- name: str | None = None
- timeout: int | None = None
- class ada.models.Checksum(path: str, checksum_type: str, value: str)
Bases:
objectFile checksum.
- checksum_type: str
- path: str
- value: str
- class ada.models.FileInfo(path: str, file_type: FileType, size: int | None = None, mtime: datetime | None = None, pnfs_id: str | None = None, current_qos: str | None = None, target_qos: str | None = None, locality: Locality | None = None, labels: tuple[str, ...]=(), extended_attributes: dict[str, str]=<factory>, checksums: tuple[~ada.models.Checksum, ...]=())
Bases:
objectRepresents a file or directory in dCache.
- current_qos: str | None = None
- extended_attributes: dict[str, str]
- labels: tuple[str, ...] = ()
- mtime: datetime | None = None
- path: str
- pnfs_id: str | None = None
- size: int | None = None
- target_qos: str | None = None
- class ada.models.FileType(*values)
Bases:
str,EnumFiletype in dCache.
- DIR = 'DIR'
- LINK = 'LINK'
- REGULAR = 'REGULAR'
- class ada.models.Locality(*values)
Bases:
str,EnumLocality of file in dCache.
- NEARLINE = 'NEARLINE'
- ONLINE = 'ONLINE'
- ONLINE_AND_NEARLINE = 'ONLINE_AND_NEARLINE'
- UNAVAILABLE = 'UNAVAILABLE'
- class ada.models.QuotaInfo(quota_type: str, id: int, custodial: int, custodial_limit: int | None, replica: int, replica_limit: int | None)
Bases:
objectStorage quota information.
- custodial: int
- custodial_limit: int | None
- id: int
- quota_type: str
- replica: int
- replica_limit: int | None
- class ada.models.SSEEvent(event_type: str, event_id: str | None = None, path: str | None = None, object_name: str | None = None, mask: str | None = None, cookie: str | None = None, raw_data: dict | None = None)
Bases:
objectA parsed Server-Sent Event.
- cookie: str | None = None
- event_id: str | None = None
- event_type: str
- mask: str | None = None
- object_name: str | None = None
- path: str | None = None
- raw_data: dict | None = None
- class ada.models.SpaceInfo(total: int, free: int, precious: int, removable: int)
Bases:
objectPool group space information.
- free: int
- precious: int
- removable: int
- total: int
- class ada.models.Subscription(subscription_id: str, event_type: str, path: str)
Bases:
objectSSE event subscription within a channel.
- event_type: str
- path: str
- subscription_id: str
- class ada.models.UserInfo(status: str, uid: int | None = None, gids: tuple[int, ...]=(), username: str | None = None, home: str | None = None, root: str | None = None, raw: dict = <factory>)
Bases:
objectUser identity from whoami.
- gids: tuple[int, ...] = ()
- home: str | None = None
- raw: dict
- root: str | None = None
- status: str
- uid: int | None = None
- username: str | None = None
ada.utils module
Utility functions for ADA.
Provides URL encoding, file permission checks, JSON conversion helpers, and human-readable size formatting.
- ada.utils.check_config_permissions(filepath: str) None
Verify a config file is not world-writable.
Config files are allowed to be world-readable but not world-writable.
- ada.utils.check_file_permissions(filepath: str, *, check_readable: bool = True) None
Verify a file is not world-readable or world-writable.
Replicates the Bash security checks on token files, netrc files, and config files.
- Args:
filepath: Path to check. check_readable: If True, also checks world-readable bit.
- Raises:
AdaSecurityError: If the file has insecure permissions. FileNotFoundError: If the file does not exist.
- ada.utils.encode_path(path: str) str
URL-encode a dCache namespace path.
Equivalent to the Bash
urlencodefunction (jq -sRr @uri). Encodes all characters including/so the entire path becomes a single URL path segment (e.g.,/pnfs/data→%2Fpnfs%2Fdata).
- ada.utils.human_readable_size(size_bytes: int) str
Convert bytes to a human-readable string (e.g., ‘1.5 GiB’).
- ada.utils.normalize_path(path: str) str
Normalize a dCache path by removing trailing slashes and double slashes.
- ada.utils.parse_lifetime(lifetime_str: str) tuple[int, str]
Parse a lifetime string like ‘7D’, ‘24H’, ‘30M’ into (value, unit).
- Returns:
Tuple of (numeric_value, unit_character).
- Raises:
AdaValidationError: If the format is invalid.
- ada.utils.read_file_list(filepath: str) list[str]
Read a file containing one path per line.
Strips whitespace and ignores empty lines and comments (lines starting with #).
- ada.utils.resolve_paths(paths: str | list[str] | None = None, from_file: str | None = None) list[str]
Resolve paths from arguments or file list.
- ada.utils.to_json(input_str: str) dict[str, str]
Convert various metadata formats to a JSON dict.
Supports: - JSON format:
{"key": "value"}- key=value pairs (one per line, or comma-separated) - Tab-separated key/value pairsReplicates the Bash
to_jsonfunction.
Module contents
ADA - Advanced dCache API tool
- class ada.AdaClient(api: str | None = None, tokenfile: str | None = None, token: str | None = None, netrc: str | None = None, proxy: str | None = None, igtf: bool = True, config_paths: list[str] | None = None, debug: bool = False)
Bases:
objectHigh-level client for the dCache REST API.
Can be used as a context manager for automatic cleanup:
with AdaClient(...) as client: client.list("/data")
- checksum(paths: str | list[str] | None = None, recursive: bool = False, from_file: str | None = None) list[Checksum]
Get checksums for file(s).
- close() None
Close the underlying HTTP client.
- delete(path: str, recursive: bool = False, force: bool = False) None
Delete a file or directory.
- delete_request(request_id: str) None
Delete a bulk request.
- find_label(path: str, regex: str, recursive: bool = False) list[tuple[str, list[str]]]
Find files with labels matching a regex.
- find_xattr(path: str, key: str, regex: str, recursive: bool = False, all_keys: bool = False) list[tuple[str, dict[str, str]]]
Find files with extended attributes matching a regex.
- list(path: str) list[str]
List directory contents.
- list_labels(path: str, label: str | None = None) list[str]
List labels attached to a file.
- list_xattr(path: str, key: str | None = None) dict[str, str]
List extended attributes of a file.
- longlist(paths: str | list[str] | None = None, from_file: str | None = None) list[FileInfo]
Get detailed file listing.
- mkdir(path: str, recursive: bool = False) str
Create a directory.
- mv(source: str, destination: str) str
Move or rename a file/directory.
- remove_label(path: str, label: str = '', all_labels: bool = False) str
Remove label(s) from a file.
- remove_xattr(path: str, key: str = '', all_keys: bool = False) str
Remove extended attribute(s) from a file.
- set_label(path: str, label: str) str
Attach a label to a file.
- set_xattr(path: str, attributes: dict[str, str] | str) str
Set extended attributes on a file.
- stage(paths: str | list[str] | None = None, recursive: bool = False, lifetime: str = '7D', from_file: str | None = None) BulkRequest
Stage files from tape to disk.
- stat_request(request_id: str) BulkRequestStatus
Get bulk request status.
- unstage(paths: str | list[str] | None = None, recursive: bool = False, request_id: str | None = None, from_file: str | None = None) BulkRequest
Unstage files — release disk pins.
- view_token() dict
Decode and display the current token.