Skip to content

Commit ecd71ec

Browse files
authored
♻️⬆️ Upgrading parfive (ITISFoundation#2720)
* upgraded parfive version and removed constraing * better error reporting in UI * ParallelDownoader reporters errors in the logs
1 parent c03c97c commit ecd71ec

File tree

4 files changed

+65
-24
lines changed

4 files changed

+65
-24
lines changed

services/web/server/requirements/_base.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ expiringdict
6969
semantic_version
7070

7171
# import/export excel
72-
parfive==1.0.2 ## See note in simcore_service_webserver/exporter/file_downloader.py
72+
parfive
7373
openpyxl
7474
python-magic
7575

services/web/server/requirements/_base.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ orjson==3.5.3
150150
# via -r requirements/_base.in
151151
pamqp==2.3.0
152152
# via aiormq
153-
parfive==1.0.2
153+
parfive==1.5.1
154154
# via -r requirements/_base.in
155155
passlib==1.7.4
156156
# via -r requirements/_base.in
Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import logging
22
from pathlib import Path
33

4-
import parfive
5-
from aiofiles import os as aiofiles_os
64
from aiohttp.web import Application
75
from parfive.downloader import Downloader
86

@@ -13,44 +11,32 @@
1311
log = logging.getLogger(__name__)
1412

1513

16-
if parfive.__version__ != "1.0.2":
17-
raise RuntimeError(
18-
"Parfive was upgraded, please make sure this version supports "
19-
"aiofiles otherwise it will block the main loop while downloading files. "
20-
"If such condition is not met please do not upgrade! "
21-
"A PR to parfive will be submitted by GitHK and this should be no longer required."
22-
)
23-
24-
2514
class ParallelDownloader:
2615
def __init__(self):
2716
self.downloader = Downloader(
2817
progress=False, file_progress=False, notebook=False, overwrite=True
2918
)
3019
self.total_files_added = 0
3120

32-
async def append_file(self, link: str, download_path: Path):
21+
async def append_file(self, link: str, download_path: Path) -> None:
3322
await makedirs(download_path.parent, exist_ok=True)
3423
self.downloader.enqueue_file(
3524
url=link, path=download_path.parent, filename=download_path.name
3625
)
3726
self.total_files_added += 1
3827

39-
async def download_files(self, app: Application):
28+
async def download_files(self, app: Application) -> None:
4029
"""starts the download and waits for all files to finish"""
41-
42-
# run this async, parfive will support aiofiles in the future as stated above
43-
wrapped_function = aiofiles_os.wrap(self.downloader.download)
4430
exporter_settings = get_settings(app)
45-
results = await wrapped_function(
31+
results = await self.downloader.run_download(
4632
timeouts={
4733
"total": exporter_settings.downloader_max_timeout_seconds,
4834
"sock_read": 90, # default as in parfive code
4935
}
5036
)
51-
log.debug("Download results %s", results)
5237

53-
if len(results) != self.total_files_added:
54-
raise ExporterException(
55-
"Not all files were downloaded. Please check the logs above."
56-
)
38+
log.debug("Download %s using %s", f"{results=}", f"{self.downloader=}")
39+
if len(results) != self.total_files_added or len(results.errors) > 0:
40+
message = f"Not all files were downloaded: {results.errors=}"
41+
log.error(message)
42+
raise ExporterException(message)

services/web/server/tests/integration/01/test_exporter.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import aiopg.sa
3232
import aioredis
3333
import pytest
34+
from _pytest.monkeypatch import MonkeyPatch
3435
from aiohttp.test_utils import TestClient
3536
from models_library.settings.redis import RedisConfig
3637
from pytest_simcore.docker_registry import _pull_push_service
@@ -607,3 +608,57 @@ async def test_import_export_import_duplicate(
607608
duplicated_files_checksums,
608609
condition_operator=operator.eq,
609610
)
611+
612+
613+
@pytest.fixture
614+
def mock_file_downloader(monkeypatch: MonkeyPatch) -> None:
615+
original_append_file = ParallelDownloader.append_file
616+
617+
async def mock_append_file(self, link: str, download_path: Path) -> None:
618+
# making the download fail
619+
link = "http://localhost/missing"
620+
await original_append_file(self, link, download_path)
621+
622+
monkeypatch.setattr(ParallelDownloader, "append_file", mock_append_file)
623+
624+
625+
async def test_download_error_reporting(
626+
client: TestClient,
627+
push_services_to_registry: None,
628+
aiopg_engine: aiopg.sa.engine.Engine,
629+
redis_client: aioredis.Redis,
630+
simcore_services_ready: None,
631+
grant_access_rights: None,
632+
mock_file_downloader: None,
633+
):
634+
await login_user(client)
635+
636+
# not testing agains all versions, results will be the same
637+
export_version = get_exported_projects()[0]
638+
export_file_name = export_version.name
639+
version_from_name = export_file_name.split("#")[0]
640+
641+
assert_error = (
642+
f"The '{version_from_name}' version' is not present in the supported versions: "
643+
f"{SUPPORTED_EXPORTER_VERSIONS}. If it's a new version please remember to add it."
644+
)
645+
assert version_from_name in SUPPORTED_EXPORTER_VERSIONS, assert_error
646+
647+
imported_project_uuid = await import_study_from_file(client, export_version)
648+
649+
headers = {X_PRODUCT_NAME_HEADER: "osparc"}
650+
651+
# export newly imported project
652+
url_export = client.app.router["export_project"].url_for(
653+
project_id=imported_project_uuid
654+
)
655+
656+
assert url_export == URL(API_PREFIX + f"/projects/{imported_project_uuid}:xport")
657+
async with await client.post(
658+
f"{url_export}", headers=headers, timeout=10
659+
) as export_response:
660+
assert export_response.status == 400, await export_response.text()
661+
json_response = await export_response.json()
662+
assert json_response["error"]["logs"][0]["message"].startswith(
663+
"Not all files were downloaded: "
664+
)

0 commit comments

Comments
 (0)