mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Fix Display Application link generation
for metadata files and use same interface also for datasets,
which should effectively give us test coverage?
Fixes:
```
Stack Trace(most recent call first)
AttributeError: 'Bunch' object has no attribute 'get_file_name'
File "starlette/applications.py", line 122, in __call__
await self.middleware_stack(scope, receive, send)
File "starlette/middleware/errors.py", line 184, in __call__
raise exc
File "starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "starlette_context/middleware/raw_middleware.py", line 93, in __call__
await self.app(scope, receive, send_wrapper)
File "starlette/middleware/base.py", line 109, in __call__
await response(scope, receive, send)
File "starlette/responses.py", line 270, in __call__
async with anyio.create_task_group() as task_group:
File "anyio/_backends/_asyncio.py", line 597, in __aexit__
raise exceptions[0]
File "starlette/responses.py", line 273, in wrap
await func()
File "starlette/middleware/base.py", line 134, in stream_response
return await super().stream_response(send)
File "starlette/responses.py", line 262, in stream_response
async for chunk in self.body_iterator:
File "starlette/middleware/base.py", line 98, in body_stream
raise app_exc
File "starlette/middleware/base.py", line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error)
File "starlette/middleware/exceptions.py", line 79, in __call__
raise exc
File "starlette/middleware/exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "fastapi/middleware/asyncexitstack.py", line 20, in __call__
raise e
File "fastapi/middleware/asyncexitstack.py", line 17, in __call__
await self.app(scope, receive, send)
File "starlette/routing.py", line 718, in __call__
await route.handle(scope, receive, send)
File "starlette/routing.py", line 443, in handle
await self.app(scope, receive, send)
File "a2wsgi/wsgi.py", line 157, in __call__
return await responder(scope, receive, send)
File "a2wsgi/wsgi.py", line 198, in __call__
raise self.exc_info[0].with_traceback(
File "galaxy/web/framework/middleware/error.py", line 165, in __call__
app_iter = self.application(environ, sr_checker)
File "galaxy/web/framework/middleware/statsd.py", line 29, in __call__
req = self.application(environ, start_response)
File "/cvmfs/main.galaxyproject.org/venv/lib/python3.11/site-packages/paste/httpexceptions.py", line 640, in __call__
return self.application(environ, start_response)
File "galaxy/web/framework/base.py", line 173, in __call__
return self.handle_request(request_id, path_info, environ, start_response)
File "galaxy/web/framework/base.py", line 262, in handle_request
body = method(trans, **kwargs)
File "galaxy/web/framework/decorators.py", line 138, in set_nocache_headers
return func(self, trans, *args, **kwargs)
File "galaxy/webapps/galaxy/controllers/dataset.py", line 677, in display_application
file_name = value.get_file_name()
File "galaxy/datatypes/display_applications/parameters.py", line 256, in __getattr__
return getattr(self.value, key)
```
from https://sentry.galaxyproject.org/share/issue/c68d4f4d94f941c09e6eb5f62b163a69/
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
# Contains parameters that are used in Display Applications
|
||||
import mimetypes
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from galaxy.model.base import transaction
|
||||
from galaxy.schema.schema import DatasetState
|
||||
from galaxy.util import string_as_bool
|
||||
from galaxy.util.bunch import Bunch
|
||||
from galaxy.util.template import fill_template
|
||||
|
||||
DEFAULT_DATASET_NAME = "dataset"
|
||||
@@ -57,6 +58,13 @@ class DisplayApplicationParameter:
|
||||
return fill_template(self.url, context=other_values)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DatasetLikeObject:
|
||||
file_name: str
|
||||
state: DatasetState
|
||||
extension: str
|
||||
|
||||
|
||||
class DisplayApplicationDataParameter(DisplayApplicationParameter):
|
||||
"""Parameter that returns a file_name containing the requested content"""
|
||||
|
||||
@@ -95,27 +103,29 @@ class DisplayApplicationDataParameter(DisplayApplicationParameter):
|
||||
)
|
||||
return None
|
||||
|
||||
def _get_dataset_like_object(self, other_values):
|
||||
def _get_dataset_like_object(self, other_values) -> Optional[DatasetLikeObject]:
|
||||
# this returned object has file_name, state, and states attributes equivalent to a DatasetAssociation
|
||||
data = other_values.get(self.dataset, None)
|
||||
assert data, "Base dataset could not be found in values provided to DisplayApplicationDataParameter"
|
||||
if isinstance(data, DisplayDataValueWrapper):
|
||||
data = data.value
|
||||
if data.state != data.states.OK:
|
||||
if data.state != DatasetState.OK:
|
||||
return None
|
||||
if self.metadata:
|
||||
rval = getattr(data.metadata, self.metadata, None)
|
||||
assert rval, f'Unknown metadata name "{self.metadata}" provided for dataset type "{data.ext}".'
|
||||
return Bunch(file_name=rval.get_file_name(), state=data.state, states=data.states, extension="data")
|
||||
elif self.extensions and (self.force_conversion or not isinstance(data.datatype, self.formats)):
|
||||
return DatasetLikeObject(file_name=rval.get_file_name(), state=data.state, extension="data")
|
||||
elif (
|
||||
self.formats and self.extensions and (self.force_conversion or not isinstance(data.datatype, self.formats))
|
||||
):
|
||||
for ext in self.extensions:
|
||||
rval = data.get_converted_files_by_type(ext)
|
||||
if rval:
|
||||
return rval
|
||||
return DatasetLikeObject(file_name=rval.get_file_name(), state=rval.state, extension=rval.extension)
|
||||
direct_match, target_ext, _ = data.find_conversion_destination(self.formats)
|
||||
assert direct_match or target_ext is not None, f"No conversion path found for data param: {self.name}"
|
||||
return None
|
||||
return data
|
||||
return DatasetLikeObject(file_name=data.get_file_name(), state=data.state, extension=data.extension)
|
||||
|
||||
def get_value(self, other_values, dataset_hash, user_hash, trans):
|
||||
data = self._get_dataset_like_object(other_values)
|
||||
@@ -154,22 +164,22 @@ class DisplayApplicationDataParameter(DisplayApplicationParameter):
|
||||
trans.sa_session.add(assoc)
|
||||
with transaction(trans.sa_session):
|
||||
trans.sa_session.commit()
|
||||
elif converted_dataset and converted_dataset.state == converted_dataset.states.ERROR:
|
||||
elif converted_dataset and converted_dataset.state == DatasetState.ERROR:
|
||||
raise Exception(f"Dataset conversion failed for data parameter: {self.name}")
|
||||
return self.get_value(other_values, dataset_hash, user_hash, trans)
|
||||
|
||||
def is_preparing(self, other_values):
|
||||
value = self._get_dataset_like_object(other_values)
|
||||
if value and value.state in (value.states.NEW, value.states.UPLOAD, value.states.QUEUED, value.states.RUNNING):
|
||||
if value and value.state in (DatasetState.NEW, DatasetState.UPLOAD, DatasetState.QUEUED, DatasetState.RUNNING):
|
||||
return True
|
||||
return False
|
||||
|
||||
def ready(self, other_values):
|
||||
value = self._get_dataset_like_object(other_values)
|
||||
if value:
|
||||
if value.state == value.states.OK:
|
||||
if value.state == DatasetState.OK:
|
||||
return True
|
||||
elif value.state == value.states.ERROR:
|
||||
elif value.state == DatasetState.ERROR:
|
||||
raise Exception(f"A data display parameter is in the error state: {self.name}")
|
||||
return False
|
||||
|
||||
|
||||
@@ -674,7 +674,7 @@ class DatasetInterface(BaseUIController, UsesAnnotations, UsesItemRatings, UsesE
|
||||
), f"Extra file content requested ({action_param_extra}), but allow_extra_files_access is False."
|
||||
file_name = os.path.join(value.extra_files_path, action_param_extra)
|
||||
else:
|
||||
file_name = value.get_file_name()
|
||||
file_name = value.file_name
|
||||
content_length = os.path.getsize(file_name)
|
||||
rval = open(file_name, "rb")
|
||||
except OSError as e:
|
||||
|
||||
Reference in New Issue
Block a user