Skip to content

Commit cedbf0b

Browse files
committed
WIP: Dapi for TAPIS v3
1 parent e425bf6 commit cedbf0b

24 files changed

+1567
-11171
lines changed

.github/workflows/build-test.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ jobs:
66
strategy:
77
fail-fast: false
88
matrix:
9-
python-version: ["3.9"]
10-
poetry-version: ["1.6.1"]
9+
python-version: ["3.13"]
10+
poetry-version: ["2.1.2"]
1111
os: [ubuntu-latest]
1212
runs-on: ${{ matrix.os }}
1313
steps:
@@ -23,5 +23,4 @@ jobs:
2323
run: poetry install
2424
- name: Lint with black
2525
run: poetry run black --check .
26-
- name: Run the automated tests
27-
run: poetry run pytest -v
26+

dapi/__init__.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
"""
22
Dapi - A Python wrapper for interacting with DesignSafe resources via the Tapis API.
33
"""
4-
# Import the renamed client class
54
from .client import DSClient
6-
from .exceptions import DapiException, FileOperationError, JobSubmissionError, JobMonitorError
7-
# Import JobDefinition here too for easier access like dapi.JobDefinition
8-
from .jobs import JobDefinition
95

10-
__version__ = "1.1.0" # Example version
6+
# Import exceptions from the exceptions module
7+
# Make sure ALL exceptions you want to expose are listed here
8+
from .exceptions import (
9+
DapiException,
10+
AuthenticationError,
11+
FileOperationError,
12+
AppDiscoveryError,
13+
JobSubmissionError,
14+
JobMonitorError,
15+
)
1116

17+
18+
__version__ = "1.0.0"
19+
20+
# Define what gets imported with 'from dapi import *'
21+
# Also helps linters and clarifies the public API
1222
__all__ = [
13-
"DSClient", # Export the renamed class
14-
"JobDefinition", # Export JobDefinition
23+
"DSClient",
24+
# List ALL exported exceptions here
1525
"DapiException",
26+
"AuthenticationError",
1627
"FileOperationError",
28+
"AppDiscoveryError",
1729
"JobSubmissionError",
1830
"JobMonitorError",
19-
]
31+
]

dapi/apps.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import List, Any, Optional
44
from .exceptions import AppDiscoveryError
55

6+
67
def find_apps(
78
t: Tapis, search_term: str, list_type: str = "ALL", verbose: bool = True
89
) -> List[Tapis]:
@@ -24,24 +25,34 @@ def find_apps(
2425
try:
2526
# Use id.like for partial matching, ensure search term is handled
2627
search_query = f"(id.like.*{search_term}*)" if search_term else None
27-
results = t.apps.getApps(search=search_query, listType=list_type, select="id,version,owner") # Select fewer fields for speed
28+
results = t.apps.getApps(
29+
search=search_query, listType=list_type, select="id,version,owner"
30+
) # Select fewer fields for speed
2831

2932
if verbose:
3033
if not results:
31-
print(f"No apps found matching '{search_term}' with listType '{list_type}'")
34+
print(
35+
f"No apps found matching '{search_term}' with listType '{list_type}'"
36+
)
3237
else:
3338
print(f"\nFound {len(results)} matching apps:")
3439
for app in results:
3540
print(f"- {app.id} (Version: {app.version}, Owner: {app.owner})")
3641
print()
3742
return results
3843
except BaseTapyException as e:
39-
raise AppDiscoveryError(f"Failed to search for apps matching '{search_term}': {e}") from e
44+
raise AppDiscoveryError(
45+
f"Failed to search for apps matching '{search_term}': {e}"
46+
) from e
4047
except Exception as e:
41-
raise AppDiscoveryError(f"An unexpected error occurred while searching for apps: {e}") from e
48+
raise AppDiscoveryError(
49+
f"An unexpected error occurred while searching for apps: {e}"
50+
) from e
4251

4352

44-
def get_app_details(t: Tapis, app_id: str, app_version: Optional[str] = None, verbose: bool = True) -> Optional[Tapis]:
53+
def get_app_details(
54+
t: Tapis, app_id: str, app_version: Optional[str] = None, verbose: bool = True
55+
) -> Optional[Tapis]:
4556
"""
4657
Get detailed information for a specific app ID and version (or latest).
4758
@@ -68,23 +79,31 @@ def get_app_details(t: Tapis, app_id: str, app_version: Optional[str] = None, ve
6879
print(f" ID: {app_info.id}")
6980
print(f" Version: {app_info.version}")
7081
print(f" Owner: {app_info.owner}")
71-
if hasattr(app_info, 'jobAttributes') and hasattr(app_info.jobAttributes, 'execSystemId'):
72-
print(f" Execution System: {app_info.jobAttributes.execSystemId}")
82+
if hasattr(app_info, "jobAttributes") and hasattr(
83+
app_info.jobAttributes, "execSystemId"
84+
):
85+
print(f" Execution System: {app_info.jobAttributes.execSystemId}")
7386
else:
74-
print(" Execution System: Not specified in jobAttributes")
87+
print(" Execution System: Not specified in jobAttributes")
7588
print(f" Description: {app_info.description}")
7689
return app_info
7790
except BaseTapyException as e:
7891
# Check for 404 specifically
79-
if hasattr(e, 'response') and e.response and e.response.status_code == 404:
80-
print(f"App '{app_id}' (Version: {app_version or 'latest'}) not found.")
81-
# Optionally, try searching for similar apps
82-
# print("\nAttempting to find similar apps:")
83-
# find_apps(t, app_id, verbose=True)
84-
return None
92+
if hasattr(e, "response") and e.response and e.response.status_code == 404:
93+
print(f"App '{app_id}' (Version: {app_version or 'latest'}) not found.")
94+
# Optionally, try searching for similar apps
95+
# print("\nAttempting to find similar apps:")
96+
# find_apps(t, app_id, verbose=True)
97+
return None
8598
else:
86-
print(f"Error getting app info for '{app_id}' (Version: {app_version or 'latest'}): {e}")
87-
raise AppDiscoveryError(f"Failed to get details for app '{app_id}': {e}") from e
99+
print(
100+
f"Error getting app info for '{app_id}' (Version: {app_version or 'latest'}): {e}"
101+
)
102+
raise AppDiscoveryError(
103+
f"Failed to get details for app '{app_id}': {e}"
104+
) from e
88105
except Exception as e:
89106
print(f"An unexpected error occurred getting app info for '{app_id}': {e}")
90-
raise AppDiscoveryError(f"Unexpected error getting details for app '{app_id}': {e}") from e
107+
raise AppDiscoveryError(
108+
f"Unexpected error getting details for app '{app_id}': {e}"
109+
) from e

dapi/auth.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
from dotenv import load_dotenv
66
from .exceptions import AuthenticationError
77

8-
def init(base_url: str = "https://designsafe.tapis.io",
9-
username: str = None,
10-
password: str = None,
11-
env_file: str = None) -> Tapis:
8+
9+
def init(
10+
base_url: str = "https://designsafe.tapis.io",
11+
username: str = None,
12+
password: str = None,
13+
env_file: str = None,
14+
) -> Tapis:
1215
"""
1316
Initialize and authenticate a Tapis client for DesignSafe.
1417
@@ -49,20 +52,21 @@ def init(base_url: str = "https://designsafe.tapis.io",
4952
try:
5053
final_password = getpass("Enter DesignSafe Password: ")
5154
except (EOFError, KeyboardInterrupt):
52-
raise AuthenticationError("Password input cancelled.")
53-
except Exception: # Fallback for non-terminal environments
54-
final_password = input("Enter DesignSafe Password: ")
55-
55+
raise AuthenticationError("Password input cancelled.")
56+
except Exception: # Fallback for non-terminal environments
57+
final_password = input("Enter DesignSafe Password: ")
5658

5759
if not final_username or not final_password:
5860
raise AuthenticationError("Username and password are required.")
5961

6062
# Initialize Tapis object
6163
try:
62-
t = Tapis(base_url=base_url,
63-
username=final_username,
64-
password=final_password,
65-
download_latest_specs=False) # Avoid slow spec downloads by default
64+
t = Tapis(
65+
base_url=base_url,
66+
username=final_username,
67+
password=final_password,
68+
download_latest_specs=False,
69+
) # Avoid slow spec downloads by default
6670

6771
# Attempt to get tokens to verify credentials
6872
t.get_tokens()
@@ -74,4 +78,6 @@ def init(base_url: str = "https://designsafe.tapis.io",
7478
raise AuthenticationError(f"Tapis authentication failed: {e}") from e
7579
except Exception as e:
7680
# Catch other potential errors
77-
raise AuthenticationError(f"An unexpected error occurred during authentication: {e}") from e
81+
raise AuthenticationError(
82+
f"An unexpected error occurred during authentication: {e}"
83+
) from e

0 commit comments

Comments
 (0)