Skip to content
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

✨ Add download-study-logs-fcn #163

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
9c15998
update workflow before publishing python package
bisgaard-itis Oct 23, 2023
ab1bc1e
Merge branch 'master' of github.com:bisgaard-itis/osparc-simcore-clients
bisgaard-itis Oct 23, 2023
60c4f60
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Oct 23, 2023
3aa7d70
fix dependency issue and bump version
bisgaard-itis Oct 23, 2023
a9810d4
Merge branch 'master' of github.com:bisgaard-itis/osparc-simcore-clients
bisgaard-itis Oct 23, 2023
5d2ceb2
point to website in project description
bisgaard-itis Oct 23, 2023
185195c
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Oct 23, 2023
f58c10f
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Oct 26, 2023
fdd75b7
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Oct 27, 2023
11e369d
fix broken dependency
bisgaard-itis Nov 2, 2023
e844983
improve doc
bisgaard-itis Nov 2, 2023
c798687
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 2, 2023
55bdba4
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
9ce0911
add github token to download artifacts
bisgaard-itis Nov 3, 2023
39210ef
ensure only read-access @wvangeit
bisgaard-itis Nov 3, 2023
50c487f
yet another attempt at downloading artifacts
bisgaard-itis Nov 3, 2023
128a1a7
resolve merge conflicts
bisgaard-itis Nov 3, 2023
3d8d1eb
make sure to use repo that ran the trigger wf
bisgaard-itis Nov 3, 2023
3f2b07a
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
48cf475
another attempt at fixing
bisgaard-itis Nov 3, 2023
77d1e81
change owner
bisgaard-itis Nov 3, 2023
21b446b
change repo owner
bisgaard-itis Nov 3, 2023
10b5ce0
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
d90cccc
allow publishing to testpypi also when pr
bisgaard-itis Nov 3, 2023
b1561a4
minor change
bisgaard-itis Nov 3, 2023
2db2d81
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
a22c0c4
revert minor (but breaking) change
bisgaard-itis Nov 3, 2023
9a6a1e0
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
a83b349
minor fix
bisgaard-itis Nov 3, 2023
e4e07d7
Merge branch 'master' of github.com:bisgaard-itis/osparc-simcore-clients
bisgaard-itis Nov 3, 2023
0bd41d9
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
565a00e
add debug messages
bisgaard-itis Nov 3, 2023
f8fd235
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
a3e668f
another debug message
bisgaard-itis Nov 3, 2023
7a77a55
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
1e03c59
hopefully the final version
bisgaard-itis Nov 3, 2023
fe3f2b0
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
a0c8668
final fix
bisgaard-itis Nov 3, 2023
aa312f6
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
86a6f79
minor fix
bisgaard-itis Nov 3, 2023
5a341c6
move master and tag to individual jobs
bisgaard-itis Nov 3, 2023
abfc0a4
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
c823bff
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
817d236
add debug messages
bisgaard-itis Nov 3, 2023
ee3c218
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 3, 2023
5988a7c
dev->post
bisgaard-itis Nov 3, 2023
b6ce6c5
add python script for determining semantic version
bisgaard-itis Nov 6, 2023
08dd828
minor changes
bisgaard-itis Nov 6, 2023
a411cca
minor changes
bisgaard-itis Nov 6, 2023
d482706
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
0f7db5a
improve error handling and add version file to artifacts
bisgaard-itis Nov 6, 2023
9e88276
check if release
bisgaard-itis Nov 6, 2023
9b84b5c
minor fix
bisgaard-itis Nov 6, 2023
0264d2d
ensure to enter venv
bisgaard-itis Nov 6, 2023
20d095f
also when tagging
bisgaard-itis Nov 6, 2023
f513b51
source venv in publishin workflow
bisgaard-itis Nov 6, 2023
f3ea1f6
ensure only master
bisgaard-itis Nov 6, 2023
0ee27ea
add script for testing 'pure' semver
bisgaard-itis Nov 6, 2023
b683f49
adapt workflows to new python script
bisgaard-itis Nov 6, 2023
2f4d002
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
113313c
minor change
bisgaard-itis Nov 6, 2023
57579c7
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
ba5312f
attempt to evaluate expressions correctly
bisgaard-itis Nov 6, 2023
43e143d
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
9f5e181
several fixes to fix tests
bisgaard-itis Nov 6, 2023
8411cb9
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
14c32d5
ensure repo is checked out in publish workflow
bisgaard-itis Nov 6, 2023
cf79e93
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
99e4ca0
several small fixes
bisgaard-itis Nov 6, 2023
bbbecc9
cleanup
bisgaard-itis Nov 6, 2023
5c85d32
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
adfb76a
debug
bisgaard-itis Nov 6, 2023
b153609
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
ff20bad
minor cleanup
bisgaard-itis Nov 6, 2023
c30f0e9
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
7c0e7aa
mionr changes
bisgaard-itis Nov 6, 2023
c48ba12
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
0e15e33
add debug message
bisgaard-itis Nov 6, 2023
787fbf5
minor change
bisgaard-itis Nov 6, 2023
d2fbe1f
resolve conflicts
bisgaard-itis Nov 6, 2023
2ddf381
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
19f2545
minor change
bisgaard-itis Nov 6, 2023
efee6c4
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
0d761d3
yet another try
bisgaard-itis Nov 6, 2023
5a90aae
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
c29c5e6
minor change
bisgaard-itis Nov 6, 2023
52924e1
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
482c367
minor change
bisgaard-itis Nov 6, 2023
8fda0d0
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
22d9173
minor change
bisgaard-itis Nov 6, 2023
3bfe395
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 6, 2023
ea346f9
mionr change
bisgaard-itis Nov 6, 2023
1c46a9e
minor changes
bisgaard-itis Nov 6, 2023
630ee16
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 7, 2023
be216bc
correct workflow run id
bisgaard-itis Nov 7, 2023
3df8511
cosmetic change
bisgaard-itis Nov 7, 2023
5318be6
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 7, 2023
33df63c
avoid using gh
bisgaard-itis Nov 7, 2023
9157b4a
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 7, 2023
ff97cc3
change to a single job for publishing
bisgaard-itis Nov 7, 2023
efb58f8
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 7, 2023
8f97bdd
minor cleanup
bisgaard-itis Nov 7, 2023
cfbe546
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 7, 2023
52e6bd1
Merge branch 'ITISFoundation:master' into master
bisgaard-itis Nov 9, 2023
b011d68
merge itis/master into master
bisgaard-itis Nov 22, 2023
ce76b43
merge itis/master into master
bisgaard-itis Dec 5, 2023
a915631
merge itis/master into master
bisgaard-itis Dec 8, 2023
a08216f
merge itis/master into master
bisgaard-itis Jan 8, 2024
958c8c6
swap loops in clean up jobs
bisgaard-itis Jan 9, 2024
a2b9c53
correction
bisgaard-itis Jan 9, 2024
0404b74
merge itis/master into master
bisgaard-itis Jan 10, 2024
b845806
merge itis/master into master
bisgaard-itis Jan 10, 2024
9dba891
merge itis/master into master
bisgaard-itis Jan 23, 2024
6fe4a20
merge itis/master into master
bisgaard-itis Feb 26, 2024
e1a2f2d
update server compatibility to new url
bisgaard-itis Feb 28, 2024
e066bd0
merge itis/master into master
bisgaard-itis Feb 29, 2024
1c56fcb
minor change to trigger ci
bisgaard-itis Feb 29, 2024
111656d
merge itis/master into master
bisgaard-itis Mar 4, 2024
ccfd63c
merge itis/master into master
bisgaard-itis Mar 20, 2024
f4e0302
merge itis/master into master
bisgaard-itis Mar 21, 2024
13cca02
merge itis/master into master
bisgaard-itis Mar 22, 2024
2976700
merge itis/master into master
bisgaard-itis Mar 22, 2024
5de49e8
merge itis/master into master
bisgaard-itis Apr 15, 2024
0597d44
merge itis/master into master
bisgaard-itis Apr 16, 2024
b7ba4b1
merge itis/master into master
bisgaard-itis Apr 30, 2024
c01d67e
merge itis/master into master
bisgaard-itis May 27, 2024
ff6080c
merge itis/master into master
bisgaard-itis May 31, 2024
ee891c1
merge itis/master into master
bisgaard-itis May 31, 2024
e9a388d
merge itis/master into master
bisgaard-itis Jun 5, 2024
46b178e
merge itis/master into master
bisgaard-itis Jun 5, 2024
583a789
merge itis/master into master
bisgaard-itis Jun 6, 2024
e8c4318
merge itis/master into master
bisgaard-itis Jun 25, 2024
646efa4
update openapi.json
bisgaard-itis Jun 25, 2024
69a5266
update openapi.json
bisgaard-itis Jun 25, 2024
d41030a
add ensure_unique_names fcn
bisgaard-itis Jun 25, 2024
8f83dc6
bugfix and improve tsst
bisgaard-itis Jun 25, 2024
fb9465a
minor fixes
bisgaard-itis Jun 25, 2024
ad199ca
minor change
bisgaard-itis Jun 25, 2024
9d89415
last fixes
bisgaard-itis Jun 25, 2024
738479d
merge itis/master into master
bisgaard-itis Jun 25, 2024
bacd050
merge master
bisgaard-itis Jun 25, 2024
cc8a506
add synchronous version of the method
bisgaard-itis Jun 25, 2024
bc33ad3
@pcrespov private method and default limits+offsets
bisgaard-itis Jun 26, 2024
5ea7e24
add type annotations
bisgaard-itis Jun 26, 2024
f4dcc7c
@pcrespov add progressbar when downloading logs
bisgaard-itis Jun 26, 2024
a1660ff
add more useful log
bisgaard-itis Jun 26, 2024
5b62e53
minor changes
bisgaard-itis Jun 26, 2024
92ee397
add pylint exceptions
bisgaard-itis Jun 26, 2024
e56808f
use pytest.fail @pcrespov
bisgaard-itis Jun 26, 2024
2ca4c54
ensure unique file names directly in method
bisgaard-itis Jun 26, 2024
c3dcf51
use Optional instead of |
bisgaard-itis Jun 26, 2024
320ceb9
remove superfluous file
bisgaard-itis Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 236 additions & 22 deletions api/openapi.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions clients/python/client/osparc/_files_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async def upload_file_async(
configuration=self.api_client.configuration, timeout=timeout_seconds
) as session:
with logging_redirect_tqdm():
_logger.info("Uploading %s in %i chunks", file.name, n_urls)
_logger.info("Uploading %s in %i chunk(s)", file.name, n_urls)
async for chunck, size in tqdm(
file_chunk_generator(file, chunk_size),
total=n_urls,
Expand Down Expand Up @@ -206,15 +206,15 @@ def _search_files(
sha256_checksum: Optional[str] = None,
timeout_seconds: int = DEFAULT_TIMEOUT_SECONDS,
) -> PaginationGenerator:
def pagination_method():
def _pagination_method():
return super(FilesApi, self).search_files_page(
file_id=file_id,
sha256_checksum=sha256_checksum,
_request_timeout=timeout_seconds,
)

return PaginationGenerator(
first_page_callback=pagination_method,
first_page_callback=_pagination_method,
api_client=self.api_client,
base_url=self.api_client.configuration.host,
auth=self._auth,
Expand Down
3 changes: 3 additions & 0 deletions clients/python/client/osparc/_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ async def delete(self, *args, **kwargs) -> httpx.Response:
async def patch(self, *args, **kwargs) -> httpx.Response:
return await self._request(self._client.patch, *args, **kwargs)

async def get(self, *args, **kwargs) -> httpx.Response:
return await self._request(self._client.get, *args, **kwargs)

def _wait_callback(self, retry_state: tenacity.RetryCallState) -> int:
assert retry_state.outcome is not None
response: httpx.Response = retry_state.outcome.exception().response
Expand Down
23 changes: 17 additions & 6 deletions clients/python/client/osparc/_solvers_api.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
from typing import Any, List, Optional

import httpx
from osparc_client import OnePageSolverPort, SolverPort
from osparc_client import JobInputs, OnePageSolverPort, SolverPort
from osparc_client import SolversApi as _SolversApi

from . import ApiClient
from ._models import ParentProjectInfo
from ._utils import PaginationGenerator, dev_feature, dev_features_enabled
from ._utils import (
_DEFAULT_PAGINATION_LIMIT,
_DEFAULT_PAGINATION_OFFSET,
PaginationGenerator,
dev_feature,
dev_features_enabled,
)


class SolversApi(_SolversApi):
Expand Down Expand Up @@ -60,18 +66,23 @@ def jobs(self, solver_key: str, version: str) -> PaginationGenerator:
(its "length")
"""

def pagination_method():
def _pagination_method():
return super(SolversApi, self).get_jobs_page(
solver_key=solver_key, version=version, limit=20, offset=0
solver_key=solver_key,
version=version,
limit=_DEFAULT_PAGINATION_LIMIT,
offset=_DEFAULT_PAGINATION_OFFSET,
)

return PaginationGenerator(
first_page_callback=pagination_method,
first_page_callback=_pagination_method,
api_client=self.api_client,
base_url=self.api_client.configuration.host,
auth=self._auth,
)

def create_job(self, solver_key, version, job_inputs, **kwargs):
def create_job(
self, solver_key: str, version: str, job_inputs: JobInputs, **kwargs
):
kwargs = {**kwargs, **ParentProjectInfo().model_dump(exclude_none=True)}
return super().create_job(solver_key, version, job_inputs, **kwargs)
104 changes: 100 additions & 4 deletions clients/python/client/osparc/_studies_api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
from typing import Any
import asyncio
import logging
from pathlib import Path
from tempfile import mkdtemp
from typing import Any, Optional

import httpx
from osparc_client import ApiClient, JobInputs, JobLogsMap, PageStudy
from osparc_client import StudiesApi as _StudiesApi
from tqdm.asyncio import tqdm_asyncio

from ._http_client import AsyncHttpClient
from ._models import ParentProjectInfo
from ._utils import dev_features_enabled
from ._utils import (
_DEFAULT_PAGINATION_LIMIT,
_DEFAULT_PAGINATION_OFFSET,
PaginationGenerator,
dev_features_enabled,
)

_logger = logging.getLogger(__name__)


class StudiesApi(_StudiesApi):
Expand All @@ -24,15 +39,96 @@ class StudiesApi(_StudiesApi):
"stop_study_job",
]

def __init__(self, api_client: Optional[ApiClient] = None):
"""Construct object

Args:
api_client (ApiClient, optinal): osparc.ApiClient object
"""
self._super: _StudiesApi = super()
self._super.__init__(api_client)
user: Optional[str] = self.api_client.configuration.username
passwd: Optional[str] = self.api_client.configuration.password
self._auth: Optional[httpx.BasicAuth] = (
httpx.BasicAuth(username=user, password=passwd)
if (user is not None and passwd is not None)
else None
)

def __getattribute__(self, name: str) -> Any:
if (name in StudiesApi._dev_features) and (not dev_features_enabled()):
raise NotImplementedError(f"StudiesApi.{name} is still under development")
return super().__getattribute__(name)

def create_study_job(self, study_id, job_inputs, **kwargs):
def create_study_job(self, study_id: str, job_inputs: JobInputs, **kwargs):
kwargs = {**kwargs, **ParentProjectInfo().model_dump(exclude_none=True)}
return super().create_study_job(study_id, job_inputs, **kwargs)

def clone_study(self, study_id, **kwargs):
def clone_study(self, study_id: str, **kwargs):
kwargs = {**kwargs, **ParentProjectInfo().model_dump(exclude_none=True)}
return super().clone_study(study_id, **kwargs)

def studies(self) -> PaginationGenerator:
def _pagination_method():
page_study = super(StudiesApi, self).list_studies(
limit=_DEFAULT_PAGINATION_LIMIT, offset=_DEFAULT_PAGINATION_OFFSET
)
assert isinstance(page_study, PageStudy) # nosec
return page_study
bisgaard-itis marked this conversation as resolved.
Show resolved Hide resolved

return PaginationGenerator(
first_page_callback=_pagination_method,
api_client=self.api_client,
base_url=self.api_client.configuration.host,
auth=self._auth,
)

def get_study_job_output_logfiles(self, study_id: str, job_id: str) -> Path:
return asyncio.run(
self.get_study_job_output_logfiles_async(study_id=study_id, job_id=job_id)
)

async def get_study_job_output_logfiles_async(
self, study_id: str, job_id: str, download_dir: Optional[Path] = None
) -> Path:
"""Download study logs. The log from each node will
appear as a file with the node's name in the directory"""
if download_dir is not None and not download_dir.is_dir():
raise RuntimeError(f"{download_dir=} must be a valid directory")
logs_map = super().get_study_job_output_logfile(study_id, job_id)
assert isinstance(logs_map, JobLogsMap) # nosec
bisgaard-itis marked this conversation as resolved.
Show resolved Hide resolved
log_links = logs_map.log_links
assert log_links # nosec

folder = download_dir or Path(mkdtemp()).resolve()
assert folder.is_dir() # nosec
async with AsyncHttpClient(
configuration=self.api_client.configuration
) as client:

async def _download(unique_node_name: str, download_link: str) -> None:
bisgaard-itis marked this conversation as resolved.
Show resolved Hide resolved
response = await client.get(download_link)
response.raise_for_status()
file = folder / unique_node_name
ct = 1
while file.exists():
file = file.with_stem(f"{file.stem}({ct})")
ct += 1
file.touch()
for chunk in response.iter_bytes():
file.write_bytes(chunk)

tasks = [
asyncio.create_task(_download(link.node_name, link.download_link))
for link in log_links
]
_logger.info(
"Downloading log files for study_id=%s and job_id=%s...",
study_id,
job_id,
)
await tqdm_asyncio.gather(
*tasks, disable=(not _logger.isEnabledFor(logging.INFO))
)

return folder
3 changes: 3 additions & 0 deletions clients/python/client/osparc/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
_MB = _KB * 1024 # in bytes
_GB = _MB * 1024 # in bytes

_DEFAULT_PAGINATION_LIMIT: int = 20
_DEFAULT_PAGINATION_OFFSET: int = 0

DEFAULT_TIMEOUT_SECONDS: int = 30 * 60

Page = Union[PageJob, PageFile, PageSolver, PageStudy]
Expand Down
29 changes: 28 additions & 1 deletion clients/python/test/e2e/conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# pylint: disable=protected-access
# pylint: disable=redefined-outer-name
# pylint: disable=too-many-arguments
# pylint: disable=unused-argument
# pylint: disable=unused-variable
# pylint: disable=too-many-arguments

import logging
import os
from pathlib import Path
from typing import Iterable
from uuid import UUID

import osparc
import pytest
Expand Down Expand Up @@ -71,3 +73,28 @@ def sleeper(api_client: osparc.ApiClient) -> osparc.Solver:
"simcore/services/comp/itis/sleeper", "2.0.2"
) # type: ignore
return sleeper


@pytest.fixture
def sleeper_study_id(api_client: osparc.ApiClient) -> UUID:
"""Simple sleeper study template which takes
as input a single file containing a single integer"""
_test_study_title = "sleeper_test_study"
bisgaard-itis marked this conversation as resolved.
Show resolved Hide resolved
study_api = osparc.StudiesApi(api_client=api_client)
for study in study_api.studies():
if study.title == _test_study_title:
return UUID(study.uid)
pytest.fail(f"Could not find {_test_study_title} study")


@pytest.fixture
def file_with_number(
tmp_path: Path, api_client: osparc.ApiClient
) -> Iterable[osparc.File]:
files_api = osparc.FilesApi(api_client=api_client)
file = tmp_path / "file_with_number.txt"
file.write_text("1")
server_file = files_api.upload_file(file)
yield server_file

files_api.delete_file(server_file.id)
6 changes: 6 additions & 0 deletions clients/python/test/e2e/test_files_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# pylint: disable=protected-access
# pylint: disable=redefined-outer-name
# pylint: disable=too-many-arguments
# pylint: disable=unused-argument
# pylint: disable=unused-variable

import hashlib
from pathlib import Path

Expand Down
6 changes: 6 additions & 0 deletions clients/python/test/e2e/test_notebooks.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# pylint: disable=protected-access
# pylint: disable=redefined-outer-name
# pylint: disable=too-many-arguments
# pylint: disable=unused-argument
# pylint: disable=unused-variable

import shutil
import sys
from pathlib import Path
Expand Down
8 changes: 7 additions & 1 deletion clients/python/test/e2e/test_solvers_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# pylint: disable=protected-access
# pylint: disable=redefined-outer-name
# pylint: disable=too-many-arguments
# pylint: disable=unused-argument
# pylint: disable=unused-variable

import json

import osparc
Expand Down Expand Up @@ -64,7 +70,7 @@ async def test_logstreaming(
nloglines: int = 0
url = f"/v0/solvers/{sleeper.id}/releases/{sleeper.version}/jobs/{job.id}/logstream"
print(f"starting logstreaming from {url}...")

async with async_client.stream(
"GET",
url,
Expand Down
63 changes: 63 additions & 0 deletions clients/python/test/e2e/test_studies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# pylint: disable=protected-access
# pylint: disable=redefined-outer-name
# pylint: disable=too-many-arguments
# pylint: disable=unused-argument
# pylint: disable=unused-variable

import shutil
from pathlib import Path
from uuid import UUID

import osparc
import pytest
import tenacity
from _utils import skip_if_osparc_version
from packaging.version import Version


@skip_if_osparc_version(at_least=Version("0.6.6"))
@pytest.mark.parametrize("download_dir", [True, False])
async def test_studies_logs(
api_client: osparc.ApiClient,
file_with_number: osparc.File,
sleeper_study_id: UUID,
download_dir: bool,
tmp_path: Path,
):
studies_api = osparc.StudiesApi(api_client=api_client)
job_inputs = osparc.JobInputs(
values={
"input_file": file_with_number,
}
)
job = studies_api.create_study_job(
study_id=f"{sleeper_study_id}", job_inputs=job_inputs
)
assert isinstance(job, osparc.Job)
print(f"Running study job: {job.id}")
status = studies_api.start_study_job(study_id=f"{sleeper_study_id}", job_id=job.id)
assert isinstance(status, osparc.JobStatus)
async for attempt in tenacity.AsyncRetrying(
reraise=True,
wait=tenacity.wait_fixed(1),
stop=tenacity.stop_after_delay(30),
retry=tenacity.retry_if_exception_type(AssertionError),
):
with attempt:
status = studies_api.inspect_study_job(
study_id=f"{sleeper_study_id}", job_id=job.id
)
assert isinstance(status, osparc.JobStatus)
assert status.stopped_at is not None
assert status.state == "SUCCESS"
try:
log_dir = await studies_api.get_study_job_output_logfiles_async(
study_id=f"{sleeper_study_id}",
job_id=job.id,
download_dir=tmp_path if download_dir else None,
)
assert log_dir.is_dir()
n_logfiles = sum(1 for _ in log_dir.rglob("*") if _.is_file())
assert n_logfiles > 0
finally:
shutil.rmtree(log_dir)
Loading