Skip to content
Merged
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
6 changes: 3 additions & 3 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ jobs:

- name: Install ReSDK and its testing dependencies
run: |
python${{ env.PYTHON_VERSION }} -m pip install .[test]
uv venv --python=${{ env.PYTHON_VERSION }}
uv sync --extra=test

- name: Reset Docker credentials store
run: |
Expand Down Expand Up @@ -141,6 +142,5 @@ jobs:
- name: Run tests
run: |
# Make sure `python` refers to the tox environment's Python
export PATH=`pwd`/.tox/py310-e2e-resdk/bin:$PATH
python${{ env.PYTHON_VERSION }} -m pytest --cov=resdk --cov-report=xml:.reports/resdk_e2e_cov.xml \
uv run pytest --cov=resdk --cov-report=xml:.reports/resdk_e2e_cov.xml \
--junit-xml=.reports/resdk_e2e_report.xml tests/functional/**/e2e_*.py
5 changes: 5 additions & 0 deletions docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Added
-----
- Add support for ``Python 3.14``

Fixed
-----
- Fix a bug that prevented the downloading and renaming of
a directory from a data object


===================
22.2.1 - 2025-11-19
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ dependencies = [
"wrapt",
"pytz",
"tzlocal",
"pandas",
"pandas<3.0.0",
"tqdm",
"openpyxl",
"xlrd",
Expand Down
42 changes: 30 additions & 12 deletions src/resdk/resources/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ def download(
field_name: Optional[str] = None,
download_dir: Optional[str] = None,
show_progress: bool = True,
return_dir_names: bool = False,
) -> list[str]:
"""Download Data object's files and directories.

Expand All @@ -270,6 +271,12 @@ def download(
* re.data.get(42).download(file_name='alignment7.bam')
* re.data.get(42).download(field_name='bam')

The function returns a list of downloaded file names. In case the
Data object contains directories, the user can specify to return directory names
instead of file names contained in those directories via the return_dir_names argument.
WARNING: If neither file_name nor field_name is specified and return_dir_names is set
to True, the method will download both directories and files when the Data object
contains both. However, the returned list will include only the directory names.
"""
if file_name and field_name:
raise ValueError("Only one of file_name or field_name may be given.")
Expand All @@ -281,41 +288,52 @@ def download(
files=files, download_dir=download_dir, show_progress=show_progress
)

return file_names
dir_names = self._files_dirs("dir", file_name, field_name)
if dir_names and return_dir_names:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gregorjerse this works as intended, but if a user does not specify a field or file name, only the directory names get returned. This may seem problematic, if the user expects the file names not contained in the directories to be returned as well.

asset_names = dir_names
else:
asset_names = file_names

return asset_names

def download_and_rename(
self,
custom_file_name: str,
custom_asset_name: str,
overwrite_existing: bool = False,
field_name: Optional[str] = None,
file_name: Optional[str] = None,
download_dir: Optional[str] = None,
):
"""Download and rename a single file from the Data object."""
"""Download and rename an asset from the Data object."""

if not field_name and not file_name:
raise ValueError("Either 'file_name' or 'field_name' must be given.")

if download_dir is None:
download_dir = os.getcwd()
destination_file_path = os.path.join(download_dir, custom_file_name)
if os.path.exists(destination_file_path) and not overwrite_existing:
raise FileExistsError(
f"File with path '{destination_file_path}' already exists. Skipping download."
destination_asset_path = os.path.join(download_dir, custom_asset_name)
if os.path.exists(destination_asset_path) and not overwrite_existing:
logging.warning(
f"File or directory with path '{destination_asset_path}' already exists. "
"Skipping download."
)
return

source_file_name = self.download(
source_asset_name = self.download(
file_name=file_name,
field_name=field_name,
download_dir=download_dir,
return_dir_names=True,
)[0]

source_file_path = os.path.join(download_dir, source_file_name)
source_asset_path = os.path.join(download_dir, source_asset_name)

logging.info(f"Renaming file '{source_file_name}' to '{custom_file_name}'.")
logging.info(
f"Renaming the downloaded asset from '{source_asset_name}' to '{custom_asset_name}'."
)
os.rename(
source_file_path,
destination_file_path,
source_asset_path,
destination_asset_path,
)

def stdout(self) -> str:
Expand Down
7 changes: 5 additions & 2 deletions tests/unit/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,16 @@ def test_download_ok(self, data_mock):
with patch("os.rename") as mock_rename:
Data.download_and_rename(
data_mock,
custom_file_name="text_file1.txt",
custom_asset_name="text_file1.txt",
field_name="txt",
download_dir="/some/path/",
)

data_mock.download.assert_called_once_with(
file_name=None, field_name="txt", download_dir="/some/path/"
file_name=None,
field_name="txt",
download_dir="/some/path/",
return_dir_names=True,
)

mock_rename.assert_called_once()
Expand Down