def update( self, trans, payload, **kwd ): """ PUT /api/repository_revisions/{encoded_repository_metadata_id}/{payload} Updates the value of specified columns of the repository_metadata table based on the key / value pairs in payload. """ repository_metadata_id = kwd.get( 'id', None ) try: repository_metadata = metadata_util.get_repository_metadata_by_id( trans, repository_metadata_id ) flush_needed = False for key, new_value in payload.items(): if hasattr( repository_metadata, key ): old_value = getattr( repository_metadata, key ) setattr( repository_metadata, key, new_value ) if key in [ 'tools_functionally_correct', 'time_last_tested' ]: # Automatically update repository_metadata.time_last_tested. repository_metadata.time_last_tested = datetime.datetime.utcnow() flush_needed = True if flush_needed: trans.sa_session.add( repository_metadata ) trans.sa_session.flush() except Exception, e: message = "Error in the Tool Shed repository_revisions API in update: %s" % str( e ) log.error( message, exc_info=True ) trans.response.status = 500 return message
def update(self, trans, payload, **kwd): """ PUT /api/repository_revisions/{encoded_repository_metadata_id}/{payload} Updates the value of specified columns of the repository_metadata table based on the key / value pairs in payload. """ repository_metadata_id = kwd.get('id', None) try: repository_metadata = metadata_util.get_repository_metadata_by_id( trans, repository_metadata_id) flush_needed = False for key, new_value in payload.items(): if hasattr(repository_metadata, key): old_value = getattr(repository_metadata, key) setattr(repository_metadata, key, new_value) if key in [ 'tools_functionally_correct', 'time_last_tested' ]: # Automatically update repository_metadata.time_last_tested. repository_metadata.time_last_tested = datetime.datetime.utcnow( ) flush_needed = True if flush_needed: trans.sa_session.add(repository_metadata) trans.sa_session.flush() except Exception, e: message = "Error in the Tool Shed repository_revisions API in update: %s" % str( e) log.error(message, exc_info=True) trans.response.status = 500 return message
def delete_repository_metadata(self, trans, **kwd): message = escape(kwd.get("message", "")) status = kwd.get("status", "done") id = kwd.get("id", None) if id: ids = util.listify(id) count = 0 for repository_metadata_id in ids: repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, repository_metadata_id) trans.sa_session.delete(repository_metadata) trans.sa_session.flush() count += 1 if count: message = "Deleted %d repository metadata %s" % (count, inflector.cond_plural(len(ids), "record")) else: message = "No repository metadata ids received for deleting." status = "error" trans.response.send_redirect( web.url_for( controller="admin", action="browse_repository_metadata", message=util.sanitize_text(message), status=status, ) )
def generate_workflow_image(trans, workflow_name, repository_metadata_id=None, repository_id=None): """ Return an svg image representation of a workflow dictionary created when the workflow was exported. This method is called from both Galaxy and the tool shed. When called from the tool shed, repository_metadata_id will have a value and repository_id will be None. When called from Galaxy, repository_metadata_id will be None and repository_id will have a value. """ workflow_name = encoding_util.tool_shed_decode(workflow_name) if trans.webapp.name == 'tool_shed': # We're in the tool shed. repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, repository_metadata_id) repository_id = trans.security.encode_id(repository_metadata.repository_id) changeset_revision = repository_metadata.changeset_revision metadata = repository_metadata.metadata else: # We're in Galaxy. repository = repository_util.get_tool_shed_repository_by_id(trans.app, repository_id) changeset_revision = repository.changeset_revision metadata = repository.metadata # metadata[ 'workflows' ] is a list of tuples where each contained tuple is # [ <relative path to the .ga file in the repository>, <exported workflow dict> ] for workflow_tup in metadata['workflows']: workflow_dict = workflow_tup[1] if workflow_dict['name'] == workflow_name: break if 'tools' in metadata: tools_metadata = metadata['tools'] else: tools_metadata = [] workflow, missing_tool_tups = get_workflow_from_dict(trans=trans, workflow_dict=workflow_dict, tools_metadata=tools_metadata, repository_id=repository_id, changeset_revision=changeset_revision) workflow_canvas = WorkflowCanvas() canvas = workflow_canvas.canvas # Store px width for boxes of each step. for step in workflow.steps: step.upgrade_messages = {} module = module_factory.from_workflow_step(trans, repository_id, changeset_revision, tools_metadata, step) tool_errors = module.type == 'tool' and not module.tool module_data_inputs = get_workflow_data_inputs(step, module) module_data_outputs = get_workflow_data_outputs(step, module, workflow.steps) module_name = get_workflow_module_name(module, missing_tool_tups) workflow_canvas.populate_data_for_step( step, module_name, module_data_inputs, module_data_outputs, tool_errors=tool_errors ) workflow_canvas.add_steps(highlight_errors=True) workflow_canvas.finish() trans.response.set_content_type("image/svg+xml") return canvas.tostring()
def update(self, trans, payload, **kwd): """ PUT /api/repository_revisions/{encoded_repository_metadata_id}/{payload} Updates the value of specified columns of the repository_metadata table based on the key / value pairs in payload. :param id: the encoded id of the `RepositoryMetadata` object """ repository_metadata_id = kwd.get('id', None) if repository_metadata_id is None: raise HTTPBadRequest(detail="Missing required parameter 'id'.") repository_metadata = metadata_util.get_repository_metadata_by_id( trans.app, repository_metadata_id) if repository_metadata is None: decoded_repository_metadata_id = trans.security.decode_id( repository_metadata_id) log.debug('Cannot locate repository_metadata with id %s' % str(decoded_repository_metadata_id)) return {} else: decoded_repository_metadata_id = repository_metadata.id flush_needed = False for key, new_value in payload.items(): if key == 'time_last_tested': repository_metadata.time_last_tested = datetime.datetime.utcnow( ) flush_needed = True elif hasattr(repository_metadata, key): # log information when setting attributes associated with the Tool Shed's install and test framework. if key in [ 'do_not_test', 'includes_tools', 'missing_test_components', 'test_install_error', 'tools_functionally_correct' ]: log.debug( 'Setting repository_metadata column %s to value %s for changeset_revision %s via the Tool Shed API.' % (str(key), str(new_value), str(repository_metadata.changeset_revision))) setattr(repository_metadata, key, new_value) flush_needed = True if flush_needed: log.debug( 'Updating repository_metadata record with id %s and changeset_revision %s.' % (str(decoded_repository_metadata_id), str(repository_metadata.changeset_revision))) trans.sa_session.add(repository_metadata) trans.sa_session.flush() trans.sa_session.refresh(repository_metadata) repository_metadata_dict = repository_metadata.to_dict( view='element', value_mapper=self.__get_value_mapper(trans)) repository_metadata_dict['url'] = web.url_for( controller='repository_revisions', action='show', id=repository_metadata_id) return repository_metadata_dict
def generate_workflow_image( trans, workflow_name, repository_metadata_id=None, repository_id=None ): """ Return an svg image representation of a workflow dictionary created when the workflow was exported. This method is called from both Galaxy and the tool shed. When called from the tool shed, repository_metadata_id will have a value and repository_id will be None. When called from Galaxy, repository_metadata_id will be None and repository_id will have a value. """ workflow_name = encoding_util.tool_shed_decode( workflow_name ) if trans.webapp.name == 'tool_shed': # We're in the tool shed. repository_metadata = metadata_util.get_repository_metadata_by_id( trans.app, repository_metadata_id ) repository_id = trans.security.encode_id( repository_metadata.repository_id ) changeset_revision = repository_metadata.changeset_revision metadata = repository_metadata.metadata else: # We're in Galaxy. repository = suc.get_tool_shed_repository_by_id( trans.app, repository_id ) changeset_revision = repository.changeset_revision metadata = repository.metadata # metadata[ 'workflows' ] is a list of tuples where each contained tuple is # [ <relative path to the .ga file in the repository>, <exported workflow dict> ] for workflow_tup in metadata[ 'workflows' ]: workflow_dict = workflow_tup[1] if workflow_dict[ 'name' ] == workflow_name: break if 'tools' in metadata: tools_metadata = metadata[ 'tools' ] else: tools_metadata = [] workflow, missing_tool_tups = get_workflow_from_dict( trans=trans, workflow_dict=workflow_dict, tools_metadata=tools_metadata, repository_id=repository_id, changeset_revision=changeset_revision ) workflow_canvas = WorkflowCanvas() canvas = workflow_canvas.canvas # Store px width for boxes of each step. for step in workflow.steps: step.upgrade_messages = {} module = module_factory.from_workflow_step( trans, repository_id, changeset_revision, tools_metadata, step ) tool_errors = module.type == 'tool' and not module.tool module_data_inputs = get_workflow_data_inputs( step, module ) module_data_outputs = get_workflow_data_outputs( step, module, workflow.steps ) module_name = get_workflow_module_name( module, missing_tool_tups ) workflow_canvas.populate_data_for_step( step, module_name, module_data_inputs, module_data_outputs, tool_errors=tool_errors ) workflow_canvas.add_steps( highlight_errors=True ) workflow_canvas.finish( ) trans.response.set_content_type( "image/svg+xml" ) return canvas.tostring()
def browse_repository_metadata( self, trans, **kwd ): if 'operation' in kwd: operation = kwd[ 'operation' ].lower() if operation == "delete": return self.delete_repository_metadata( trans, **kwd ) if operation == "view_or_manage_repository_revision": # The received id is a RepositoryMetadata object id, so we need to get the # associated Repository and redirect to view_or_manage_repository with the # changeset_revision. repository_metadata = metadata_util.get_repository_metadata_by_id( trans, kwd[ 'id' ] ) repository = repository_metadata.repository kwd[ 'id' ] = trans.security.encode_id( repository.id ) kwd[ 'changeset_revision' ] = repository_metadata.changeset_revision kwd[ 'operation' ] = 'view_or_manage_repository' return trans.response.send_redirect( web.url_for( controller='repository', action='browse_repositories', **kwd ) ) return self.repository_metadata_grid( trans, **kwd )
def browse_repository_metadata( self, trans, **kwd ): if 'operation' in kwd: operation = kwd[ 'operation' ].lower() if operation == "delete": return self.delete_repository_metadata( trans, **kwd ) if operation == "view_or_manage_repository_revision": # The received id is a RepositoryMetadata object id, so we need to get the # associated Repository and redirect to view_or_manage_repository with the # changeset_revision. repository_metadata = metadata_util.get_repository_metadata_by_id( trans.app, kwd[ 'id' ] ) repository = repository_metadata.repository kwd[ 'id' ] = trans.security.encode_id( repository.id ) kwd[ 'changeset_revision' ] = repository_metadata.changeset_revision kwd[ 'operation' ] = 'view_or_manage_repository' return trans.response.send_redirect( web.url_for( controller='repository', action='browse_repositories', **kwd ) ) return self.repository_metadata_grid( trans, **kwd )
def show(self, trans, id, **kwd): """ GET /api/repository_revisions/{encoded_repository_metadata_id} Displays information about a repository_metadata record in the Tool Shed. :param id: the encoded id of the `RepositoryMetadata` object """ # Example URL: http://localhost:9009/api/repository_revisions/bb125606ff9ea620 repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, id) if repository_metadata is None: log.debug('Cannot locate repository_metadata with id %s' % str(id)) return {} encoded_repository_id = trans.security.encode_id(repository_metadata.repository_id) repository_metadata_dict = repository_metadata.to_dict(view='element', value_mapper=self.__get_value_mapper(trans)) repository_metadata_dict['url'] = web.url_for(controller='repositories', action='show', id=encoded_repository_id) return repository_metadata_dict
def show(self, trans, id, **kwd): """ GET /api/repository_revisions/{encoded_repository_metadata_id} Displays information about a repository_metadata record in the Tool Shed. :param id: the encoded id of the `RepositoryMetadata` object """ # Example URL: http://localhost:9009/api/repository_revisions/bb125606ff9ea620 repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, id) if repository_metadata is None: log.debug('Cannot locate repository_metadata with id %s' % str(id)) return {} encoded_repository_id = trans.security.encode_id(repository_metadata.repository_id) repository_metadata_dict = repository_metadata.to_dict(view='element', value_mapper=self.__get_value_mapper(trans)) repository_metadata_dict['url'] = web.url_for(controller='repositories', action='show', id=encoded_repository_id) return repository_metadata_dict
def update( self, trans, payload, **kwd ): """ PUT /api/repository_revisions/{encoded_repository_metadata_id}/{payload} Updates the value of specified columns of the repository_metadata table based on the key / value pairs in payload. :param id: the encoded id of the `RepositoryMetadata` object """ repository_metadata_id = kwd.get( 'id', None ) if repository_metadata_id is None: raise HTTPBadRequest( detail="Missing required parameter 'id'." ) repository_metadata = metadata_util.get_repository_metadata_by_id( trans.app, repository_metadata_id ) if repository_metadata is None: decoded_repository_metadata_id = trans.security.decode_id( repository_metadata_id ) log.debug( 'Cannot locate repository_metadata with id %s' % str( decoded_repository_metadata_id ) ) return {} else: decoded_repository_metadata_id = repository_metadata.id flush_needed = False for key, new_value in payload.items(): if key == 'time_last_tested': repository_metadata.time_last_tested = datetime.datetime.utcnow() flush_needed = True elif hasattr( repository_metadata, key ): # log information when setting attributes associated with the Tool Shed's install and test framework. if key in [ 'do_not_test', 'includes_tools', 'missing_test_components', 'test_install_error', 'tools_functionally_correct' ]: log.debug( 'Setting repository_metadata column %s to value %s for changeset_revision %s via the Tool Shed API.' % ( str( key ), str( new_value ), str( repository_metadata.changeset_revision ) ) ) setattr( repository_metadata, key, new_value ) flush_needed = True if flush_needed: log.debug( 'Updating repository_metadata record with id %s and changeset_revision %s.' % ( str( decoded_repository_metadata_id ), str( repository_metadata.changeset_revision ) ) ) trans.sa_session.add( repository_metadata ) trans.sa_session.flush() trans.sa_session.refresh( repository_metadata ) repository_metadata_dict = repository_metadata.to_dict( view='element', value_mapper=self.__get_value_mapper( trans ) ) repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revisions', action='show', id=repository_metadata_id ) return repository_metadata_dict
def show( self, trans, id, **kwd ): """ GET /api/repository_revisions/{encoded_repository_metadata_id} Displays information about a repository_metadata record in the Tool Shed. :param id: the encoded id of the `RepositoryMetadata` object """ # Example URL: http://localhost:9009/api/repository_revisions/bb125606ff9ea620 try: repository_metadata = metadata_util.get_repository_metadata_by_id( trans, id ) repository_metadata_dict = repository_metadata.as_dict( value_mapper=default_value_mapper( trans, repository_metadata ) ) repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revisions', action='show', id=trans.security.encode_id( repository_metadata.id ) ) return repository_metadata_dict except Exception, e: message = "Error in the Tool Shed repository_revisions API in show: %s" % str( e ) log.error( message, exc_info=True ) trans.response.status = 500 return message
def delete_repository_metadata( self, trans, **kwd ): message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) id = kwd.get( 'id', None ) if id: ids = util.listify( id ) count = 0 for repository_metadata_id in ids: repository_metadata = metadata_util.get_repository_metadata_by_id( trans, repository_metadata_id ) trans.sa_session.delete( repository_metadata ) trans.sa_session.flush() count += 1 if count: message = "Deleted %d repository metadata %s" % ( count, inflector.cond_plural( len( ids ), "record" ) ) else: message = "No repository metadata ids received for deleting." status = 'error' trans.response.send_redirect( web.url_for( controller='admin', action='browse_repository_metadata', message=util.sanitize_text( message ), status=status ) )
def delete_repository_metadata( self, trans, **kwd ): message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) id = kwd.get( 'id', None ) if id: ids = util.listify( id ) count = 0 for repository_metadata_id in ids: repository_metadata = metadata_util.get_repository_metadata_by_id( trans.app, repository_metadata_id ) trans.sa_session.delete( repository_metadata ) trans.sa_session.flush() count += 1 if count: message = "Deleted %d repository metadata %s" % ( count, inflector.cond_plural( len( ids ), "record" ) ) else: message = "No repository metadata ids received for deleting." status = 'error' trans.response.send_redirect( web.url_for( controller='admin', action='browse_repository_metadata', message=util.sanitize_text( message ), status=status ) )
def show(self, trans, id, **kwd): """ GET /api/repository_revisions/{encoded_repository_metadata_id} Displays information about a repository_metadata record in the Tool Shed. :param id: the encoded id of the `RepositoryMetadata` object """ # Example URL: http://localhost:9009/api/repository_revisions/bb125606ff9ea620 try: repository_metadata = metadata_util.get_repository_metadata_by_id( trans, id) repository_metadata_dict = repository_metadata.as_dict( value_mapper=default_value_mapper(trans, repository_metadata)) repository_metadata_dict['url'] = web.url_for( controller='repository_revisions', action='show', id=trans.security.encode_id(repository_metadata.id)) return repository_metadata_dict except Exception, e: message = "Error in the Tool Shed repository_revisions API in show: %s" % str( e) log.error(message, exc_info=True) trans.response.status = 500 return message
def generate_workflow_image(trans, workflow_name, repository_metadata_id=None, repository_id=None): """ Return an svg image representation of a workflow dictionary created when the workflow was exported. This method is called from both Galaxy and the tool shed. When called from the tool shed, repository_metadata_id will have a value and repository_id will be None. When called from Galaxy, repository_metadata_id will be None and repository_id will have a value. """ workflow_name = encoding_util.tool_shed_decode(workflow_name) if trans.webapp.name == "tool_shed": # We're in the tool shed. repository_metadata = metadata_util.get_repository_metadata_by_id(trans, repository_metadata_id) repository_id = trans.security.encode_id(repository_metadata.repository_id) changeset_revision = repository_metadata.changeset_revision metadata = repository_metadata.metadata else: # We're in Galaxy. repository = suc.get_tool_shed_repository_by_id(trans, repository_id) changeset_revision = repository.changeset_revision metadata = repository.metadata # metadata[ 'workflows' ] is a list of tuples where each contained tuple is # [ <relative path to the .ga file in the repository>, <exported workflow dict> ] for workflow_tup in metadata["workflows"]: workflow_dict = workflow_tup[1] if workflow_dict["name"] == workflow_name: break if "tools" in metadata: tools_metadata = metadata["tools"] else: tools_metadata = [] workflow, missing_tool_tups = get_workflow_from_dict( trans=trans, workflow_dict=workflow_dict, tools_metadata=tools_metadata, repository_id=repository_id, changeset_revision=changeset_revision, ) data = [] canvas = svgfig.canvas(style="stroke:black; fill:none; stroke-width:1px; stroke-linejoin:round; text-anchor:left") text = svgfig.SVG("g") connectors = svgfig.SVG("g") boxes = svgfig.SVG("g") svgfig.Text.defaults["font-size"] = "10px" in_pos = {} out_pos = {} margin = 5 # Spacing between input/outputs. line_px = 16 # Store px width for boxes of each step. widths = {} max_width, max_x, max_y = 0, 0, 0 for step in workflow.steps: step.upgrade_messages = {} module = module_factory.from_workflow_step(trans, repository_id, changeset_revision, tools_metadata, step) tool_errors = module.type == "tool" and not module.tool module_data_inputs = get_workflow_data_inputs(step, module) module_data_outputs = get_workflow_data_outputs(step, module, workflow.steps) step_dict = { "id": step.order_index, "data_inputs": module_data_inputs, "data_outputs": module_data_outputs, "position": step.position, "tool_errors": tool_errors, } input_conn_dict = {} for conn in step.input_connections: input_conn_dict[conn.input_name] = dict(id=conn.output_step.order_index, output_name=conn.output_name) step_dict["input_connections"] = input_conn_dict data.append(step_dict) x, y = step.position["left"], step.position["top"] count = 0 module_name = get_workflow_module_name(module, missing_tool_tups) max_len = len(module_name) * 1.5 text.append(svgfig.Text(x, y + 20, module_name, **{"font-size": "14px"}).SVG()) y += 45 for di in module_data_inputs: cur_y = y + count * line_px if step.order_index not in in_pos: in_pos[step.order_index] = {} in_pos[step.order_index][di["name"]] = (x, cur_y) text.append(svgfig.Text(x, cur_y, di["label"]).SVG()) count += 1 max_len = max(max_len, len(di["label"])) if len(module.get_data_inputs()) > 0: y += 15 for do in module_data_outputs: cur_y = y + count * line_px if step.order_index not in out_pos: out_pos[step.order_index] = {} out_pos[step.order_index][do["name"]] = (x, cur_y) text.append(svgfig.Text(x, cur_y, do["name"]).SVG()) count += 1 max_len = max(max_len, len(do["name"])) widths[step.order_index] = max_len * 5.5 max_x = max(max_x, step.position["left"]) max_y = max(max_y, step.position["top"]) max_width = max(max_width, widths[step.order_index]) for step_dict in data: tool_unavailable = step_dict["tool_errors"] width = widths[step_dict["id"]] x, y = step_dict["position"]["left"], step_dict["position"]["top"] # Only highlight missing tools if displaying in the tool shed. if trans.webapp.name == "tool_shed" and tool_unavailable: fill = "#EBBCB2" else: fill = "#EBD9B2" boxes.append(svgfig.Rect(x - margin, y, x + width - margin, y + 30, fill=fill).SVG()) box_height = (len(step_dict["data_inputs"]) + len(step_dict["data_outputs"])) * line_px + margin # Draw separator line. if len(step_dict["data_inputs"]) > 0: box_height += 15 sep_y = y + len(step_dict["data_inputs"]) * line_px + 40 text.append(svgfig.Line(x - margin, sep_y, x + width - margin, sep_y).SVG()) # Define an input/output box. boxes.append(svgfig.Rect(x - margin, y + 30, x + width - margin, y + 30 + box_height, fill="#ffffff").SVG()) for conn, output_dict in step_dict["input_connections"].iteritems(): in_coords = in_pos[step_dict["id"]][conn] # out_pos_index will be a step number like 1, 2, 3... out_pos_index = output_dict["id"] # out_pos_name will be a string like 'o', 'o2', etc. out_pos_name = output_dict["output_name"] if out_pos_index in out_pos: # out_conn_index_dict will be something like: # 7: {'o': (824.5, 618)} out_conn_index_dict = out_pos[out_pos_index] if out_pos_name in out_conn_index_dict: out_conn_pos = out_pos[out_pos_index][out_pos_name] else: # Take any key / value pair available in out_conn_index_dict. # A problem will result if the dictionary is empty. if out_conn_index_dict.keys(): key = out_conn_index_dict.keys()[0] out_conn_pos = out_pos[out_pos_index][key] adjusted = (out_conn_pos[0] + widths[output_dict["id"]], out_conn_pos[1]) text.append( svgfig.SVG( "circle", cx=out_conn_pos[0] + widths[output_dict["id"]] - margin, cy=out_conn_pos[1] - margin, r=5, fill="#ffffff", ) ) connectors.append( svgfig.Line(adjusted[0], adjusted[1] - margin, in_coords[0] - 10, in_coords[1], arrow_end="true").SVG() ) canvas.append(connectors) canvas.append(boxes) canvas.append(text) width, height = (max_x + max_width + 50), max_y + 300 canvas["width"] = "%s px" % width canvas["height"] = "%s px" % height canvas["viewBox"] = "0 0 %s %s" % (width, height) trans.response.set_content_type("image/svg+xml") return canvas.standalone_xml()
def repository_dependencies(self, trans, id, **kwd): """ GET /api/repository_revisions/{encoded repository_metadata id}/repository_dependencies Returns a list of dictionaries that each define a specific downloadable revision of a repository in the Tool Shed. This method returns dictionaries with more information in them than other methods in this controller. The information about repository_metdata is enhanced to include information about the repository (e.g., name, owner, etc) associated with the repository_metadata record. :param id: the encoded id of the `RepositoryMetadata` object """ # Example URL: http://localhost:9009/api/repository_revisions/repository_dependencies/bb125606ff9ea620 repository_dependencies_dicts = [] repository_metadata = metadata_util.get_repository_metadata_by_id( trans.app, id) if repository_metadata is None: log.debug('Invalid repository_metadata id received: %s' % str(id)) return repository_dependencies_dicts metadata = repository_metadata.metadata if metadata is None: log.debug( 'The repository_metadata record with id %s has no metadata.' % str(id)) return repository_dependencies_dicts if 'repository_dependencies' in metadata: rd_tups = metadata['repository_dependencies'][ 'repository_dependencies'] for rd_tup in rd_tups: tool_shed, name, owner, changeset_revision = rd_tup[0:4] repository_dependency = repository_util.get_repository_by_name_and_owner( trans.app, name, owner) if repository_dependency is None: log.dbug( 'Cannot locate repository dependency %s owned by %s.' % (name, owner)) continue repository_dependency_id = trans.security.encode_id( repository_dependency.id) repository_dependency_repository_metadata = \ metadata_util.get_repository_metadata_by_changeset_revision(trans.app, repository_dependency_id, changeset_revision) if repository_dependency_repository_metadata is None: # The changeset_revision column in the repository_metadata table has been updated with a new # value value, so find the changeset_revision to which we need to update. new_changeset_revision = metadata_util.get_next_downloadable_changeset_revision( trans.app, repository_dependency, changeset_revision) if new_changeset_revision != changeset_revision: repository_dependency_repository_metadata = \ metadata_util.get_repository_metadata_by_changeset_revision(trans.app, repository_dependency_id, new_changeset_revision) changeset_revision = new_changeset_revision else: decoded_repository_dependency_id = trans.security.decode_id( repository_dependency_id) debug_msg = 'Cannot locate repository_metadata with id %d for repository dependency %s owned by %s ' % \ (decoded_repository_dependency_id, str(name), str(owner)) debug_msg += 'using either of these changeset_revisions: %s, %s.' % \ (str(changeset_revision), str(new_changeset_revision)) log.debug(debug_msg) continue repository_dependency_metadata_dict = \ repository_dependency_repository_metadata.to_dict(view='element', value_mapper=self.__get_value_mapper(trans)) repository_dependency_dict = repository_dependency.to_dict( view='element', value_mapper=self.__get_value_mapper(trans)) # We need to be careful with the entries in our repository_dependency_dict here since this Tool Shed API # controller is working with repository_metadata records. The above to_dict() method returns a dictionary # with an id entry for the repository record. However, all of the other methods in this controller have # the id entry associated with a repository_metadata record id. To avoid confusion, we'll update the # repository_dependency_metadata_dict with entries from the repository_dependency_dict without using the # Python dictionary update() method because we do not want to overwrite existing entries. for k, v in repository_dependency_dict.items(): if k not in repository_dependency_metadata_dict: repository_dependency_metadata_dict[k] = v repository_dependency_metadata_dict['url'] = web.url_for( controller='repositories', action='show', id=repository_dependency_id) repository_dependencies_dicts.append( repository_dependency_metadata_dict) return repository_dependencies_dicts
def generate_workflow_image(trans, workflow_name, repository_metadata_id=None, repository_id=None): """ Return an svg image representation of a workflow dictionary created when the workflow was exported. This method is called from both Galaxy and the tool shed. When called from the tool shed, repository_metadata_id will have a value and repository_id will be None. When called from Galaxy, repository_metadata_id will be None and repository_id will have a value. """ workflow_name = encoding_util.tool_shed_decode(workflow_name) if trans.webapp.name == 'tool_shed': # We're in the tool shed. repository_metadata = metadata_util.get_repository_metadata_by_id( trans, repository_metadata_id) repository_id = trans.security.encode_id( repository_metadata.repository_id) changeset_revision = repository_metadata.changeset_revision metadata = repository_metadata.metadata else: # We're in Galaxy. repository = suc.get_tool_shed_repository_by_id(trans, repository_id) changeset_revision = repository.changeset_revision metadata = repository.metadata # metadata[ 'workflows' ] is a list of tuples where each contained tuple is # [ <relative path to the .ga file in the repository>, <exported workflow dict> ] for workflow_tup in metadata['workflows']: workflow_dict = workflow_tup[1] if workflow_dict['name'] == workflow_name: break if 'tools' in metadata: tools_metadata = metadata['tools'] else: tools_metadata = [] workflow, missing_tool_tups = get_workflow_from_dict( trans=trans, workflow_dict=workflow_dict, tools_metadata=tools_metadata, repository_id=repository_id, changeset_revision=changeset_revision) data = [] canvas = svgfig.canvas( style= "stroke:black; fill:none; stroke-width:1px; stroke-linejoin:round; text-anchor:left" ) text = svgfig.SVG("g") connectors = svgfig.SVG("g") boxes = svgfig.SVG("g") svgfig.Text.defaults["font-size"] = "10px" in_pos = {} out_pos = {} margin = 5 # Spacing between input/outputs. line_px = 16 # Store px width for boxes of each step. widths = {} max_width, max_x, max_y = 0, 0, 0 for step in workflow.steps: step.upgrade_messages = {} module = module_factory.from_workflow_step(trans, repository_id, changeset_revision, tools_metadata, step) tool_errors = module.type == 'tool' and not module.tool module_data_inputs = get_workflow_data_inputs(step, module) module_data_outputs = get_workflow_data_outputs( step, module, workflow.steps) step_dict = { 'id': step.order_index, 'data_inputs': module_data_inputs, 'data_outputs': module_data_outputs, 'position': step.position, 'tool_errors': tool_errors } input_conn_dict = {} for conn in step.input_connections: input_conn_dict[conn.input_name] = dict( id=conn.output_step.order_index, output_name=conn.output_name) step_dict['input_connections'] = input_conn_dict data.append(step_dict) x, y = step.position['left'], step.position['top'] count = 0 module_name = get_workflow_module_name(module, missing_tool_tups) max_len = len(module_name) * 1.5 text.append( svgfig.Text(x, y + 20, module_name, **{ "font-size": "14px" }).SVG()) y += 45 for di in module_data_inputs: cur_y = y + count * line_px if step.order_index not in in_pos: in_pos[step.order_index] = {} in_pos[step.order_index][di['name']] = (x, cur_y) text.append(svgfig.Text(x, cur_y, di['label']).SVG()) count += 1 max_len = max(max_len, len(di['label'])) if len(module.get_data_inputs()) > 0: y += 15 for do in module_data_outputs: cur_y = y + count * line_px if step.order_index not in out_pos: out_pos[step.order_index] = {} out_pos[step.order_index][do['name']] = (x, cur_y) text.append(svgfig.Text(x, cur_y, do['name']).SVG()) count += 1 max_len = max(max_len, len(do['name'])) widths[step.order_index] = max_len * 5.5 max_x = max(max_x, step.position['left']) max_y = max(max_y, step.position['top']) max_width = max(max_width, widths[step.order_index]) for step_dict in data: tool_unavailable = step_dict['tool_errors'] width = widths[step_dict['id']] x, y = step_dict['position']['left'], step_dict['position']['top'] # Only highlight missing tools if displaying in the tool shed. if trans.webapp.name == 'tool_shed' and tool_unavailable: fill = "#EBBCB2" else: fill = "#EBD9B2" boxes.append( svgfig.Rect(x - margin, y, x + width - margin, y + 30, fill=fill).SVG()) box_height = (len(step_dict['data_inputs']) + len(step_dict['data_outputs'])) * line_px + margin # Draw separator line. if len(step_dict['data_inputs']) > 0: box_height += 15 sep_y = y + len(step_dict['data_inputs']) * line_px + 40 text.append( svgfig.Line(x - margin, sep_y, x + width - margin, sep_y).SVG()) # Define an input/output box. boxes.append( svgfig.Rect(x - margin, y + 30, x + width - margin, y + 30 + box_height, fill="#ffffff").SVG()) for conn, output_dict in step_dict['input_connections'].iteritems(): in_coords = in_pos[step_dict['id']][conn] # out_pos_index will be a step number like 1, 2, 3... out_pos_index = output_dict['id'] # out_pos_name will be a string like 'o', 'o2', etc. out_pos_name = output_dict['output_name'] if out_pos_index in out_pos: # out_conn_index_dict will be something like: # 7: {'o': (824.5, 618)} out_conn_index_dict = out_pos[out_pos_index] if out_pos_name in out_conn_index_dict: out_conn_pos = out_pos[out_pos_index][out_pos_name] else: # Take any key / value pair available in out_conn_index_dict. # A problem will result if the dictionary is empty. if out_conn_index_dict.keys(): key = out_conn_index_dict.keys()[0] out_conn_pos = out_pos[out_pos_index][key] adjusted = (out_conn_pos[0] + widths[output_dict['id']], out_conn_pos[1]) text.append( svgfig.SVG("circle", cx=out_conn_pos[0] + widths[output_dict['id']] - margin, cy=out_conn_pos[1] - margin, r=5, fill="#ffffff")) connectors.append( svgfig.Line(adjusted[0], adjusted[1] - margin, in_coords[0] - 10, in_coords[1], arrow_end="true").SVG()) canvas.append(connectors) canvas.append(boxes) canvas.append(text) width, height = (max_x + max_width + 50), max_y + 300 canvas['width'] = "%s px" % width canvas['height'] = "%s px" % height canvas['viewBox'] = "0 0 %s %s" % (width, height) trans.response.set_content_type("image/svg+xml") return canvas.standalone_xml()
def repository_dependencies(self, trans, id, **kwd): """ GET /api/repository_revisions/{encoded repository_metadata id}/repository_dependencies Returns a list of dictionaries that each define a specific downloadable revision of a repository in the Tool Shed. This method returns dictionaries with more information in them than other methods in this controller. The information about repository_metdata is enhanced to include information about the repository (e.g., name, owner, etc) associated with the repository_metadata record. :param id: the encoded id of the `RepositoryMetadata` object """ # Example URL: http://localhost:9009/api/repository_revisions/repository_dependencies/bb125606ff9ea620 repository_dependencies_dicts = [] repository_metadata = metadata_util.get_repository_metadata_by_id(trans.app, id) if repository_metadata is None: log.debug('Invalid repository_metadata id received: %s' % str(id)) return repository_dependencies_dicts metadata = repository_metadata.metadata if metadata is None: log.debug('The repository_metadata record with id %s has no metadata.' % str(id)) return repository_dependencies_dicts if 'repository_dependencies' in metadata: rd_tups = metadata['repository_dependencies']['repository_dependencies'] for rd_tup in rd_tups: tool_shed, name, owner, changeset_revision = rd_tup[0:4] repository_dependency = repository_util.get_repository_by_name_and_owner(trans.app, name, owner) if repository_dependency is None: log.dbug('Cannot locate repository dependency %s owned by %s.' % (name, owner)) continue repository_dependency_id = trans.security.encode_id(repository_dependency.id) repository_dependency_repository_metadata = \ metadata_util.get_repository_metadata_by_changeset_revision(trans.app, repository_dependency_id, changeset_revision) if repository_dependency_repository_metadata is None: # The changeset_revision column in the repository_metadata table has been updated with a new # value value, so find the changeset_revision to which we need to update. repo = hg_util.get_repo_for_repository(trans.app, repository=repository_dependency, repo_path=None, create=False) new_changeset_revision = metadata_util.get_next_downloadable_changeset_revision(repository_dependency, repo, changeset_revision) if new_changeset_revision != changeset_revision: repository_dependency_repository_metadata = \ metadata_util.get_repository_metadata_by_changeset_revision(trans.app, repository_dependency_id, new_changeset_revision) changeset_revision = new_changeset_revision else: decoded_repository_dependency_id = trans.security.decode_id(repository_dependency_id) debug_msg = 'Cannot locate repository_metadata with id %d for repository dependency %s owned by %s ' % \ (decoded_repository_dependency_id, str(name), str(owner)) debug_msg += 'using either of these changeset_revisions: %s, %s.' % \ (str(changeset_revision), str(new_changeset_revision)) log.debug(debug_msg) continue repository_dependency_metadata_dict = \ repository_dependency_repository_metadata.to_dict(view='element', value_mapper=self.__get_value_mapper(trans)) repository_dependency_dict = repository_dependency.to_dict(view='element', value_mapper=self.__get_value_mapper(trans)) # We need to be careful with the entries in our repository_dependency_dict here since this Tool Shed API # controller is working with repository_metadata records. The above to_dict() method returns a dictionary # with an id entry for the repository record. However, all of the other methods in this controller have # the id entry associated with a repository_metadata record id. To avoid confusion, we'll update the # repository_dependency_metadata_dict with entries from the repository_dependency_dict without using the # Python dictionary update() method because we do not want to overwrite existing entries. for k, v in repository_dependency_dict.items(): if k not in repository_dependency_metadata_dict: repository_dependency_metadata_dict[k] = v repository_dependency_metadata_dict['url'] = web.url_for(controller='repositories', action='show', id=repository_dependency_id) repository_dependencies_dicts.append(repository_dependency_metadata_dict) return repository_dependencies_dicts