This repository has been archived by the owner on Nov 7, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move the direct path transform to a contrib package.
Add tests for the GirderFileId transform and for the new contrib.GirderFileIdAllowDirect transform.
- Loading branch information
Showing
9 changed files
with
179 additions
and
36 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import os | ||
|
||
import girder_client | ||
import mock | ||
import pytest | ||
|
||
from girder_worker_utils.transforms.contrib import girder_io | ||
|
||
|
||
@pytest.fixture | ||
def mock_file_load(): | ||
from girder.models.file import File | ||
with mock.patch.object(File(), 'load') as load: | ||
load.return_value = {'name': 'the_name'} | ||
yield load | ||
|
||
|
||
@pytest.fixture | ||
def mock_file_getLocalFilePath(): | ||
from girder.models.file import File | ||
with mock.patch.object(File(), 'getLocalFilePath') as getLocalFilePath: | ||
getLocalFilePath.return_value = os.path.realpath(__file__) | ||
yield getLocalFilePath | ||
|
||
|
||
@pytest.fixture | ||
def mock_gc(): | ||
return mock.MagicMock(spec=girder_client.GirderClient) | ||
|
||
|
||
@pytest.fixture | ||
def mock_rmtree(): | ||
with mock.patch('shutil.rmtree') as rmtree: | ||
yield rmtree | ||
|
||
|
||
def test_GirderFileIdAllowDirect_without_env( | ||
mock_gc, mock_rmtree, mock_file_load, mock_file_getLocalFilePath): | ||
t = girder_io.GirderFileIdAllowDirect(_id='the_id', gc=mock_gc) | ||
t.transform() | ||
mock_gc.downloadFile.assert_called_once() | ||
assert 'the_id' in mock_gc.downloadFile.call_args[0] | ||
mock_rmtree.assert_not_called() | ||
t.cleanup() | ||
mock_rmtree.assert_called_once() | ||
|
||
|
||
@mock.patch.dict(os.environ, {'GW_DIRECT_PATHS': 'true'}) | ||
def test_GirderFileIdAllowDirect_with_env( | ||
mock_gc, mock_rmtree, mock_file_load, mock_file_getLocalFilePath): | ||
t = girder_io.GirderFileIdAllowDirect(_id='the_id', gc=mock_gc) | ||
t.transform() | ||
mock_gc.downloadFile.assert_not_called() | ||
t.cleanup() | ||
mock_rmtree.assert_not_called() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import os | ||
import shutil | ||
import tempfile | ||
|
||
from ..girder_io import GirderClientTransform | ||
|
||
|
||
class GirderFileIdAllowDirect(GirderClientTransform): | ||
""" | ||
This transform either uses direct path to access a file, if possible and | ||
allowed, or downloads a Girder File to the local machine and passes its | ||
local path into the function. | ||
WARNING: if a direct path is used, the task MUST NOT modify the file. It | ||
is the resposibility of the user of this transform to ensure tasks treat | ||
files as read-only. | ||
:param _id: The ID of the file to download. | ||
:type _id: str | ||
""" | ||
def __init__(self, _id, **kwargs): | ||
super(GirderFileIdAllowDirect, self).__init__(**kwargs) | ||
from girder.models.file import File | ||
from girder.exceptions import FilePathException | ||
self.file_id = _id | ||
file = File().load(self.file_id, force=True) | ||
# Store the original file name so that, if downloading the file, the | ||
# extension can be preserved. | ||
self.file_name = file['name'] | ||
try: | ||
# Add a local file path if direct paths are allowed | ||
self.local_file_path = File().getLocalFilePath(file) | ||
except FilePathException: | ||
self.local_file_path = None | ||
|
||
def _repr_model_(self): | ||
if self.local_file_path: | ||
return "{}({!r}) - {!r} - {!r}".format( | ||
self.__class__.__name__, self.file_id, self.file_name, self.local_file_path) | ||
return "{}({!r}) - {!r}".format(self.__class__.__name__, self.file_id, self.file_name) | ||
|
||
def _allowDirectPath(self): | ||
""" | ||
Check if the worker environment permits direct paths. This just checks | ||
if the environment variable GW_DIRECT_PATHS is set to a non-empry | ||
value. | ||
""" | ||
if os.environ.get('GW_DIRECT_PATHS'): | ||
return True | ||
return False | ||
|
||
def transform(self): | ||
# Don't download if self.local_file_path is set and direct paths are | ||
# allowed. | ||
if (self.local_file_path and self._allowDirectPath() and | ||
os.path.isfile(self.local_file_path)): | ||
self.temp_dir_path = None | ||
self.file_path = self.local_file_path | ||
else: | ||
self.temp_dir_path = tempfile.mkdtemp() | ||
self.file_path = os.path.join(self.temp_dir_path, '{}{}'.format( | ||
self.file_id, os.path.splitext(self.file_name)[1])) | ||
self.gc.downloadFile(self.file_id, self.file_path) | ||
return self.file_path | ||
|
||
def cleanup(self): | ||
if self.temp_dir_path: | ||
shutil.rmtree(self.temp_dir_path, ignore_errors=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ flake8 | |
flake8-blind-except | ||
flake8-docstrings | ||
flake8-import-order | ||
girder | ||
mock | ||
pytest | ||
pytest-cov |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters