Skip to content

Commit fde115d

Browse files
fix(application): error handling if application_versions called with … (#178)
* fix(application): error handling if application_versions called with str arg * fix(application): error handling if application_versions called with str arg * fix(application): error handling if application_versions called with str arg * chore(tests): allow retry of another e2e test, given connection closed by server leading to SSL Errors, see https://github.com/aignostics/python-sdk/actions/runs/18486770436/job/52671622634\?pr\=178\#step:16:274
1 parent 6ba8cf3 commit fde115d

4 files changed

Lines changed: 87 additions & 9 deletions

File tree

noxfile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,10 @@ def _generate_readme(session: nox.Session) -> None:
385385
preamble = "\n[//]: # (README.md generated from docs/partials/README_*.md)\n\n"
386386
header = Path("docs/partials/README_header.md").read_text(encoding="utf-8")
387387
main = Path("docs/partials/README_main.md").read_text(encoding="utf-8")
388-
platform_section = Path("docs/partials/README_platform.md").read_text(encoding="utf-8")
388+
platform = Path("docs/partials/README_platform.md").read_text(encoding="utf-8")
389389
glossary = Path("docs/partials/README_glossary.md").read_text(encoding="utf-8")
390390
footer = Path("docs/partials/README_footer.md").read_text(encoding="utf-8")
391-
readme_content = f"{preamble}{header}\n\n{main}\n\n{platform_section}\n\n{footer}\n\n{glossary}"
391+
readme_content = f"{preamble}{header}\n\n{main}\n\n{platform}\n\n{footer}\n\n{glossary}"
392392
Path("README.md").write_text(readme_content, encoding="utf-8")
393393
session.log("Generated README.md file from partials")
394394

src/aignostics/application/_service.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,11 @@ def application_version(
313313
message = f"Application version with ID {application_version_id} not found in application {application_id}"
314314
raise NotFoundException(message)
315315

316-
def application_versions(self, application: Application) -> list[ApplicationVersion]:
316+
def application_versions(self, application: Application | str) -> list[ApplicationVersion]:
317317
"""Get a list of all versions of the given application.
318318
319319
Args:
320-
application (Application): The application to check for versions.
320+
application (Application | str): The application to check for versions.
321321
322322
Returns:
323323
list[ApplicationVersion]: A list of all application versions sorted by semantic versioning (latest first).
@@ -328,18 +328,20 @@ def application_versions(self, application: Application) -> list[ApplicationVers
328328
try:
329329
return self._get_platform_client().applications.versions.list_sorted(application=application)
330330
except Exception as e:
331-
message = f"Failed to retrieve application versions for application '{application.application_id}': {e}"
331+
app_id = application if isinstance(application, str) else application.application_id
332+
message = f"Failed to retrieve application versions for application '{app_id}': {e}"
332333
logger.exception(message)
333334
raise RuntimeError(message) from e
334335

335-
def application_version_latest(self, application: Application) -> ApplicationVersion | None:
336+
def application_version_latest(self, application: Application | str) -> ApplicationVersion | None:
336337
"""Get a latest application version.
337338
338339
Args:
339-
application (Application): The application to check for versions.
340+
application (Application | str): The application to check for versions.
340341
341342
Returns:
342-
ApplicationVersion | None: A list of all application versions.
343+
ApplicationVersion | None: The latest version of the given application,
344+
or None if no latest version found.
343345
344346
Raises:
345347
NotFoundException: If the application with the given ID is not found.

tests/aignostics/application/gui_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ async def test_gui_cli_submit_to_run_result_delete(user: User, runner: CliRunner
139139

140140
@pytest.mark.e2e
141141
@pytest.mark.long_running
142+
@pytest.mark.flaky(retries=1, delay=5)
142143
@pytest.mark.timeout(timeout=60 * 10)
143144
@pytest.mark.sequential
144145
async def test_gui_download_dataset_via_application_to_run_cancel( # noqa: PLR0915

tests/aignostics/application/service_test.py

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from tests.contants_test import HETA_APPLICATION_ID
99

1010

11-
@pytest.mark.e2e
11+
@pytest.mark.unit
1212
def test_application_version_valid_semver_formats(runner: CliRunner) -> None:
1313
"""Test that valid semver formats are accepted."""
1414
from aignostics.application import Service as ApplicationService
@@ -75,6 +75,7 @@ def test_application_version_invalid_semver_formats(runner: CliRunner) -> None:
7575

7676

7777
@pytest.mark.e2e
78+
@pytest.mark.timeout(timeout=60)
7879
def test_application_version_use_latest_fallback(runner: CliRunner) -> None:
7980
"""Test that use_latest_if_no_version_given works correctly."""
8081
service = ApplicationService()
@@ -91,3 +92,77 @@ def test_application_version_use_latest_fallback(runner: CliRunner) -> None:
9192

9293
with pytest.raises(ValueError, match=r"Invalid application version id format"):
9394
service.application_version("invalid-format", use_latest_if_no_version_given=False)
95+
96+
97+
@pytest.mark.e2e
98+
@pytest.mark.flaky(retries=1, delay=5)
99+
@pytest.mark.timeout(timeout=60)
100+
def test_application_versions_with_str_arg(runner: CliRunner, silent_logging: None) -> None:
101+
"""Test that application_versions works correctly when passed a string application ID."""
102+
service = ApplicationService()
103+
104+
# Test with valid application ID as string
105+
versions = service.application_versions(HETA_APPLICATION_ID)
106+
assert isinstance(versions, list)
107+
# If there are versions, verify they are ApplicationVersion objects
108+
if versions:
109+
from aignostics.platform import ApplicationVersion
110+
111+
assert all(isinstance(v, ApplicationVersion) for v in versions)
112+
113+
114+
@pytest.mark.e2e
115+
@pytest.mark.flaky(retries=1, delay=5)
116+
@pytest.mark.timeout(timeout=60)
117+
def test_application_version_latest_with_str_arg(runner: CliRunner, silent_logging: None) -> None:
118+
"""Test that application_version_latest works correctly when passed a string application ID."""
119+
service = ApplicationService()
120+
121+
# Test with valid application ID as string
122+
latest = service.application_version_latest(HETA_APPLICATION_ID)
123+
# May be None if no versions exist, but should not raise an error
124+
if latest is not None:
125+
from aignostics.platform import ApplicationVersion
126+
127+
assert isinstance(latest, ApplicationVersion)
128+
assert latest.application_version_id.startswith(f"{HETA_APPLICATION_ID}:v")
129+
130+
131+
@pytest.mark.unit
132+
def test_application_versions_exception_handling_with_str_arg() -> None:
133+
"""Test that exception handling correctly uses string application ID in error message."""
134+
from unittest.mock import MagicMock, patch
135+
136+
service = ApplicationService()
137+
138+
# Mock the platform client to raise an exception
139+
with patch.object(service, "_get_platform_client") as mock_client:
140+
mock_versions = MagicMock()
141+
mock_versions.list_sorted.side_effect = Exception("Test error")
142+
mock_client.return_value.applications.versions = mock_versions
143+
144+
# Test with string application ID
145+
test_app_id = "test-application-id"
146+
expected_error = rf"Failed to retrieve application versions for application '{test_app_id}'"
147+
with pytest.raises(RuntimeError, match=expected_error):
148+
service.application_versions(test_app_id)
149+
150+
151+
@pytest.mark.unit
152+
def test_application_version_latest_exception_handling_with_str_arg() -> None:
153+
"""Test exception handling in application_version_latest with string application ID."""
154+
from unittest.mock import MagicMock, patch
155+
156+
service = ApplicationService()
157+
158+
# Mock the platform client to raise an exception
159+
with patch.object(service, "_get_platform_client") as mock_client:
160+
mock_versions = MagicMock()
161+
mock_versions.list_sorted.side_effect = Exception("Test error")
162+
mock_client.return_value.applications.versions = mock_versions
163+
164+
# Test with string application ID
165+
test_app_id = "test-application-id"
166+
expected_error = rf"Failed to retrieve application versions for application '{test_app_id}'"
167+
with pytest.raises(RuntimeError, match=expected_error):
168+
service.application_version_latest(test_app_id)

0 commit comments

Comments
 (0)