Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/galaxyproject/galaxy into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
gregvonkuster committed Aug 5, 2015
2 parents 2b87e65 + 9ad5c6c commit 45b4a4e
Show file tree
Hide file tree
Showing 23 changed files with 217 additions and 324 deletions.
2 changes: 1 addition & 1 deletion client/galaxy/scripts/mvc/ui/ui-select-library.js
Expand Up @@ -4,7 +4,7 @@ define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-table', 'mvc/ui/ui-list'],

// collection of libraries
var Libraries = Backbone.Collection.extend({
url: galaxy_config.root + 'api/libraries'
url: galaxy_config.root + 'api/libraries?deleted=false'
});

// collection of dataset
Expand Down
173 changes: 0 additions & 173 deletions client/galaxy/style/less/history.less
Expand Up @@ -807,179 +807,6 @@


// ---------------------------------------------------------------------------- older styles
//TODO: these may still apply in mobile display, workflow stuff
body.historyPage {
background: @side-panel-bg;
color: @base-text-color;
margin: 5px;
border: 0;
padding: 0;
}

// Control links at top of history
div.historyLinks {
margin: 5px 5px;
}

// Default history item appearance
div.historyItem {
margin: 0px -5px;
padding: 8px 10px;
border-top: solid @border-default-color 1px;
// border-left: solid @state-queued-border 5px;
border-right: none;
word-wrap: break-word;
background: @state-default-bg;
.state-icon {
display: inline-block;
vertical-align: middle;
width: 16px;
height: 16px;
background-position: 0 1px;
background-repeat: no-repeat;
}
.historyItemTitle {
font-weight: bold;
line-height: 16px;
}
}

.historyItemContainer:last-child div.historyItem {
border-bottom: solid @border-default-color 1px;
}

// Nested history items
div.historyItem div.historyItem {
margin-right: -11px;
}

// Change background/border color depending on state
div.historyItem-ok,
div.historyItem-failed_metadata {
background: @state-success-bg;
.state-icon {
display: none;
}
}

div.historyItem-error {
background: @state-danger-bg;
.state-icon {
.sprite(@data-error);
}
}

div.historyItem-empty {
background: @state-danger-bg;
.state-icon {
.sprite(@data-empty);
}
}

div.historyItem-running {
background: @state-running-bg;
.state-icon {
background-image: url(data_running.gif);
}
}

div.historyItem-setting_metadata {
background: @state-running-bg;
.state-icon {
background-image: url(data_running.gif);
}
}

div.historyItem-upload {
background: @state-info-bg;
.state-icon {
background-image: url(data_upload.gif);
}
}

div.historyItem-queued {
background: @state-default-bg;
.state-icon {
.sprite(@data-queued);
}
}

div.historyItem-noPermission {
filter: alpha(opacity=60);
-moz-opacity: .60;
opacity: .60;
.state-icon {
line-height: 16px;
.fa-icon;
&:before {
content: "\f05e";
}
}
}

div.historyItem-paused {
background: @state-paused-bg;
.state-icon {
line-height: 16px;
.fa-icon;
&:before {
content: "\f04c";
}
}
}

div.historyItem-new {
.state-icon {
line-height: 16px;
.fa-icon;
&:before {
content: "\f071";
}
}
}

// Special case for showing the spinner but not changing the background
div.historyItemTitleBar.spinner .state-icon {
background: url(data_running.gif) 0 1px no-repeat !important;
}

// Buttons
div.historyItemButtons {
float: right;

.icon-button.display {
.sprite(@eye-icon);
}
.icon-button.display:hover {
.sprite(@eye-icon-dark);
}
.icon-button.display_disabled {
.sprite(@eye-icon-grey);
}
.icon-button.delete {
.sprite(@delete-icon);
}
.icon-button.delete:hover {
.sprite(@delete-icon-dark);
}
.icon-button.delete_disabled {
.sprite(@delete-icon-grey);
}
.icon-button.edit {
.sprite(@pencil-icon);
}
.icon-button.edit:hover {
.sprite(@pencil-icon-dark);
}
.icon-button.edit_disabled {
.sprite(@pencil-icon-grey);
}
}

div.historyItemBody div {
padding-top: 2px;
}

pre.peek {
background: white;
color: black;
Expand Down
5 changes: 4 additions & 1 deletion lib/galaxy/jobs/__init__.py
Expand Up @@ -95,7 +95,7 @@ def get_resource_group( self ):
def config_exception(e, file):
abs_path = os.path.abspath(file)
message = 'Problem parsing the XML in file %s, ' % abs_path
message += 'please correct the indicated portion of the file and restart Galaxy.'
message += 'please correct the indicated portion of the file and restart Galaxy. '
message += str(e)
log.exception(message)
return Exception(message)
Expand Down Expand Up @@ -192,6 +192,9 @@ def __parse_job_conf_xml(self, tree):
else:
self.handlers[tag] = [id]

# Must define at least one handler to have a default.
if not self.handlers:
raise ValueError("Job configuration file defines no valid handler elements.")
# Determine the default handler(s)
self.default_handler_id = self.__get_default(handlers, self.handlers.keys())

Expand Down
9 changes: 9 additions & 0 deletions lib/galaxy/jobs/actions/post.py
Expand Up @@ -399,9 +399,18 @@ def execute(cls, app, sa_session, action, job, replacement_dict):
# concurrently, sometimes non-terminal steps won't be cleaned up
# because of the lag in job state updates.
wfi = job.workflow_invocation_step.workflow_invocation
if wfi.active:
log.debug("Workflow still scheduling so new jobs may appear, skipping deletion of intermediate files.")
# Still evaluating workflow so we don't yet have all workflow invocation
# steps to start looking at.
return
if wfi.workflow.has_outputs_defined():
jobs_to_check = [wfistep.job for wfistep in wfi.steps if not wfistep.workflow_step.workflow_outputs]
for j2c in jobs_to_check:
if j2c is None:
# Job not yet created, this will be re-evaluated after subsequent jobs in
# workflow.
return
for input_dataset in [x.dataset for x in j2c.input_datasets if x.dataset.creating_job.workflow_invocation_step and x.dataset.creating_job.workflow_invocation_step.workflow_invocation == wfi]:
safe_to_delete = True
for job_to_check in [d_j.job for d_j in input_dataset.dependent_jobs]:
Expand Down
66 changes: 12 additions & 54 deletions lib/galaxy/managers/histories.py
Expand Up @@ -122,55 +122,6 @@ def set_current_by_id( self, trans, history_id ):
"""
return self.set_current( trans, self.by_id( history_id ) )

# TODO: replace or move to serializer
def _get_history_data( self, trans, history ):
"""
Returns a dictionary containing ``history`` and ``contents``, serialized
history and an array of serialized history contents respectively.
"""
# TODO: instantiate here? really?
history_serializer = HistorySerializer( self.app )
hda_serializer = hdas.HDASerializer( self.app )
history_dictionary = {}
contents_dictionaries = []
try:
history_dictionary = history_serializer.serialize_to_view( history, view='detailed',
user=trans.user, trans=trans )

for content in history.contents_iter( types=[ 'dataset', 'dataset_collection' ] ):
contents_dict = {}
if isinstance( content, model.HistoryDatasetAssociation ):
contents_dict = hda_serializer.serialize_to_view(content, view='detailed', user=trans.user, trans=trans )
hda_annotation = hda_serializer.serialize_annotation( content, 'annotation', user=history.user )
contents_dict[ 'annotation' ] = hda_annotation
elif isinstance( content, model.HistoryDatasetCollectionAssociation ):
try:
service = self.app.dataset_collections_service
collection = service.get_dataset_collection_instance(
trans=trans,
instance_type='history',
id=self.app.security.encode_id( content.id ),
)
serializer = collections_util.dictify_dataset_collection_instance
contents_dict = serializer( collection,
security=self.app.security,
parent=collection.history,
view="element" )
except Exception, exc:
log.exception( "Error in history API at listing dataset collection: %s", exc )
# TODO: return some dict with the error
contents_dictionaries.append( contents_dict )

except Exception, exc:
user_id = str( trans.user.id ) if trans.user else '(anonymous)'
log.exception( 'Error bootstrapping history for user %s: %s', user_id, str( exc ) )
message = ( 'An error occurred getting the history data from the server. '
'Please contact a Galaxy administrator if the problem persists.' )
history_dictionary[ 'error' ] = message

return { 'history': history_dictionary,
'contents': contents_dictionaries }

# container interface
def _filter_to_contained( self, container, content_class ):
return content_class.history == container
Expand Down Expand Up @@ -322,14 +273,21 @@ def serialize_history_state( self, history, key, **context ):

return state

def serialize_contents( self, history, *args, **context ):
def serialize_contents( self, history, key, trans=None, **context ):
contents_dictionaries = []
for content in history.contents_iter( types=[ 'dataset', 'dataset_collection' ] ):
contents_dict = {}

if isinstance( content, model.HistoryDatasetAssociation ):
contents_dict = self.hda_serializer.serialize_to_view( content, view='detailed', **context )
# elif isinstance( content, model.HistoryDatasetCollectionAssociation ):
# contents_dict = self._serialize_collection( trans, content )
contents_dict = self.hda_serializer.serialize_to_view( content,
view='detailed', trans=trans, **context )
# TODO: work out: shouldn't history annotations *always* use user=history.user? why anything else?
hda_annotation = self.hda_serializer.serialize_annotation( content, 'annotation', user=history.user )
contents_dict[ 'annotation' ] = hda_annotation

elif isinstance( content, model.HistoryDatasetCollectionAssociation ):
contents_dict = self._serialize_collection( trans, content )

contents_dictionaries.append( contents_dict )
return contents_dictionaries

Expand All @@ -342,7 +300,7 @@ def _serialize_collection( self, trans, collection ):
id=self.app.security.encode_id( collection.id ),
)
return collections_util.dictify_dataset_collection_instance( dataset_collection_instance,
security=self.app.security, parent=dataset_collection_instance.history, view="element" )
security=self.app.security, parent=dataset_collection_instance.history, view="element" )


class HistoryDeserializer( sharable.SharableModelDeserializer, deletable.PurgableDeserializerMixin ):
Expand Down
46 changes: 43 additions & 3 deletions lib/galaxy/webapps/galaxy/api/histories.py
Expand Up @@ -8,7 +8,7 @@
pkg_resources.require( "Paste" )

pkg_resources.require( "SQLAlchemy >= 0.4" )
from sqlalchemy import true, false, desc
from sqlalchemy import true, false, desc, asc

from galaxy import exceptions
from galaxy.web import _future_expose_api as expose_api
Expand Down Expand Up @@ -90,6 +90,23 @@ def index( self, trans, deleted='False', **kwd ):
skip the first ( offset - 1 ) items and begin returning
at the Nth item
The list returned can be ordered using the optional parameter:
order: string containing one of the valid ordering attributes followed
(optionally) by '-asc' or '-dsc' for ascending and descending
order respectively. Orders can be stacked as a comma-
separated list of values.
..example:
To sort by name descending then create time descending:
'?order=name-dsc,create_time'
The ordering attributes and their default orders are:
create_time defaults to 'create_time-dsc'
update_time defaults to 'update_time-dsc'
name defaults to 'name-asc'
'order' defaults to 'create_time-dsc'
..example:
limit and offset can be combined. Skip the first two and return five:
'?limit=5&offset=3'
Expand All @@ -116,8 +133,7 @@ def index( self, trans, deleted='False', **kwd ):
# and any sent in from the query string
filters += self.history_filters.parse_filters( filter_params )

# TODO: eventually make order_by a param as well
order_by = desc( self.app.model.History.create_time )
order_by = self._parse_order_by( kwd.get( 'order', 'create_time-dsc' ) )
histories = self.history_manager.list( filters=filters, order_by=order_by, limit=limit, offset=offset )

rval = []
Expand Down Expand Up @@ -402,3 +418,27 @@ def archive_download( self, trans, id, jeha_id, **kwds ):
raise exceptions.MessageException( "Export not available or not yet ready." )

return self.serve_ready_history_export( trans, jeha )

def _parse_order_by( self, order_by_string ):
ORDER_BY_SEP_CHAR = ','
if ORDER_BY_SEP_CHAR in order_by_string:
return [ self._parse_single_order_by( o ) for o in order_by_string.split( ORDER_BY_SEP_CHAR ) ]
return self._parse_single_order_by( order_by_string )

def _parse_single_order_by( self, order_by_string ):
History = self.history_manager.model_class
# TODO: formalize and generalize into managers
if order_by_string in ( 'create_time', 'create_time-dsc' ):
return desc( History.create_time )
if order_by_string == 'create_time-asc':
return asc( History.create_time )
if order_by_string in ( 'update_time', 'update_time-dsc' ):
return desc( History.update_time )
if order_by_string == 'update_time-asc':
return asc( History.update_time )
if order_by_string in ( 'name', 'name-asc' ):
return asc( History.name )
if order_by_string == 'name-dsc':
return desc( History.name )
raise exceptions.RequestParameterInvalidException( 'Unkown order_by',
controller='history', order_by=order_by_string )

0 comments on commit 45b4a4e

Please sign in to comment.