Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 24 additions & 10 deletions src/ansys/dynamicreporting/core/utils/report_remote_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,9 @@ def put_objects(self, in_objects):
r = self._http_session.put(url, auth=auth, files=files)
except Exception as e:
logger.debug(f"Warning: {str(e)}")
r = requests.Response()
r.status_code = requests.codes.client_closed_request
self._last_error = str(e)
success = requests.codes.client_closed_request
continue
ret = r.status_code
# we map 201 (created) to 200 (ok) to simplify error handling...
if ret == requests.codes.created:
Expand Down Expand Up @@ -749,6 +750,7 @@ def copy_items(
progress.setMaximum(nobjs)

for obj in copy_list:
fileobj = None
try:
if progress:
progress.setValue(n)
Expand All @@ -759,20 +761,32 @@ def copy_items(
file_url = getattr(obj, "fileurl", None)
if file_url:
# need to pull the file from this url...
obj.fileobj = tempfile.NamedTemporaryFile()
if source.get_file(obj, obj.fileobj) != requests.codes.ok:
obj.fileobj = None
self.put_objects([obj])
# clean up temp file
fileobj = getattr(obj, "fileobj", None)
if fileobj:
fileobj.close()
fileobj = tempfile.SpooledTemporaryFile()
obj.fileobj = fileobj
file_status = source.get_file(obj, fileobj)
if file_status != requests.codes.ok:
if print_allowed():
print(f"Failure while copying {obj}: unable to fetch file payload")
Comment on lines +768 to +769
return False
ret = self.put_objects([obj])
if ret != requests.codes.ok:
error_text = self.get_last_error()
if print_allowed():
if error_text:
print(f"Failure while copying {obj}: {error_text}")
else:
print(f"Failure while copying {obj}: server returned status {ret}")
return False
if type(obj) not in skip_count_types:
n += 1
except Exception as e:
if print_allowed():
print(f"Failure while copying {obj}: {e}")
return False
finally:
if fileobj:
fileobj.close()
obj.fileobj = None
if progress:
progress.setValue(nobjs)
return True
Expand Down
77 changes: 77 additions & 0 deletions tests/test_report_remote_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,38 @@
from ansys.dynamicreporting.core.utils.exceptions import BadRequestError, DBCreationFailedError


class _CopyItemsSource:
def __init__(self, *, file_status=requests.codes.ok, payload=b"payload") -> None:
self.file_status = file_status
self.payload = payload
self.item = ro.ItemREST()
self.item.guid = str(uuid.uuid4())
self.item.session = str(uuid.uuid4())
self.item.dataset = str(uuid.uuid4())
self.item.fileurl = "image.png"
self.dataset = ro.DatasetREST()
self.dataset.guid = self.item.dataset
self.session = ro.SessionREST()
self.session.guid = self.item.session

def get_objects(self, objtype, query=None):
if objtype is ro.ItemREST:
return [self.item]
return []

def get_object_from_guid(self, guid, objtype=None):
if objtype is ro.DatasetREST and guid == self.dataset.guid:
return self.dataset
if objtype is ro.SessionREST and guid == self.session.guid:
return self.session
return None

def get_file(self, obj, fileobj):
if self.file_status == requests.codes.ok:
fileobj.write(self.payload)
return self.file_status


def test_copy_item(adr_service_query, tmp_path, get_exec) -> None:
db_dir = tmp_path / "test_copy_item"
port = 8000 + randint(0, 3999)
Expand Down Expand Up @@ -73,6 +105,51 @@ def test_copy_item(adr_service_query, tmp_path, get_exec) -> None:
assert success


def test_copy_items_uses_requests_compatible_temp_file(monkeypatch) -> None:
server = r.Server()
source = _CopyItemsSource()

def fake_put_objects(objects) -> int:
obj = objects[0]
if isinstance(obj, ro.ItemREST):
prepared = requests.Request(
"PUT",
"http://example.test/item/api_payload/test-guid",
files={"file": ("image.png", obj.fileobj)},
).prepare()
assert prepared.headers["Content-Length"]
return requests.codes.ok

monkeypatch.setattr(server, "put_objects", fake_put_objects)

assert server.copy_items(source=source, obj_type="item", progress=False, progress_qt=False)


def test_copy_items_returns_false_on_item_upload_failure(monkeypatch) -> None:
server = r.Server()
source = _CopyItemsSource()

def fake_put_objects(objects) -> int:
obj = objects[0]
if isinstance(obj, ro.ItemREST):
server._last_error = "upload failed"
return requests.codes.client_closed_request
return requests.codes.ok

monkeypatch.setattr(server, "put_objects", fake_put_objects)

assert not server.copy_items(source=source, obj_type="item", progress=False, progress_qt=False)


def test_copy_items_returns_false_on_file_download_failure(monkeypatch) -> None:
server = r.Server()
source = _CopyItemsSource(file_status=requests.codes.service_unavailable)

monkeypatch.setattr(server, "put_objects", lambda objects: requests.codes.ok)

assert not server.copy_items(source=source, obj_type="item", progress=False, progress_qt=False)


@pytest.mark.ado_test
def test_start_stop(tmp_path, get_exec) -> None:
db_dir = tmp_path / "test_start_stop"
Expand Down
Loading