[hg] galaxy 2577: Merge trunk
details: http://www.bx.psu.edu/hg/galaxy/rev/5b6146705e80 changeset: 2577:5b6146705e80 user: Kanwei Li <kanwei@gmail.com> date: Thu Aug 13 13:44:04 2009 -0400 description: Merge trunk 14 file(s) affected in this change: templates/admin/library/create_info_template.mako templates/admin/library/edit_info_template.mako templates/admin/library/info_permissions.mako templates/admin/library/info_template_permissions.mako templates/admin/library/new_info.mako templates/admin/library/new_info_template.mako templates/history/grid.mako templates/history/list_shared.mako templates/library/create_info_template.mako templates/library/edit_info_template.mako templates/library/info_permissions.mako templates/library/info_template_permissions.mako templates/library/new_info.mako templates/library/new_info_template.mako diffs (truncated from 7699 to 3000 lines): diff -r f1f2d1de5f3e -r 5b6146705e80 cron/updateucsc.sh.sample --- a/cron/updateucsc.sh.sample Thu Aug 13 13:43:25 2009 -0400 +++ b/cron/updateucsc.sh.sample Thu Aug 13 13:44:04 2009 -0400 @@ -9,8 +9,20 @@ export PYTHONPATH=${GALAXY}/lib # setup directories -mkdir ${GALAXY}/tool-data/shared/ucsc/new -mkdir ${GALAXY}/tool-data/shared/ucsc/chrom/new +echo "Creating required directories." +DIRS=" +${GALAXY}/tool-data/shared/ucsc/new +${GALAXY}/tool-data/shared/ucsc/chrom +${GALAXY}/tool-data/shared/ucsc/chrom/new +" +for dir in $DIRS; do + if [ ! -d $dir ]; then + echo "Creating $dir" + mkdir $dir + else + echo "$dir already exists, continuing." + fi +done date echo "Updating UCSC shared data tables." diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/app.py --- a/lib/galaxy/app.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/app.py Thu Aug 13 13:44:04 2009 -0400 @@ -37,6 +37,8 @@ self.toolbox = tools.ToolBox( self.config.tool_config, self.config.tool_path, self ) # Load datatype converters self.datatypes_registry.load_datatype_converters( self.toolbox ) + #load external metadata tool + self.datatypes_registry.load_external_metadata_tool( self.toolbox ) # Load datatype indexers self.datatypes_registry.load_datatype_indexers( self.toolbox ) #Load security policy diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/datatypes/registry.py --- a/lib/galaxy/datatypes/registry.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/datatypes/registry.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,7 +1,7 @@ """ Provides mapping between extensions and datatypes, mime-types, etc. """ -import os +import os, tempfile import logging import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo import galaxy.util @@ -18,6 +18,7 @@ self.datatype_converters = odict() self.datatype_indexers = odict() self.converters = [] + self.set_external_metadata_tool = None self.indexers = [] self.sniff_order = [] self.upload_file_formats = [] @@ -251,6 +252,31 @@ self.datatype_converters[source_datatype][target_datatype] = converter self.log.debug( "Loaded converter: %s", converter.id ) + def load_external_metadata_tool( self, toolbox ): + """Adds a tool which is used to set external metadata""" + #we need to be able to add a job to the queue to set metadata. The queue will currently only accept jobs with an associated tool. + #We'll create a special tool to be used for Auto-Detecting metadata; this is less than ideal, but effective + #Properly building a tool without relying on parsing an XML file is near impossible...so we'll create a temporary file + tool_xml_text = """ + <tool id="__SET_METADATA__" name="Set External Metadata" version="1.0.0" tool_type="set_metadata"> + <type class="SetMetadataTool" module="galaxy.tools"/> + <action module="galaxy.tools.actions.metadata" class="SetMetadataToolAction"/> + <command>$__SET_EXTERNAL_METADATA_COMMAND_LINE__</command> + <inputs> + <param format="data" name="input1" type="data" label="File to set metadata on."/> + <param name="__ORIGINAL_DATASET_STATE__" type="hidden" value=""/> + <param name="__SET_EXTERNAL_METADATA_COMMAND_LINE__" type="hidden" value=""/> + </inputs> + </tool> + """ + tmp_name = tempfile.NamedTemporaryFile() + tmp_name.write( tool_xml_text ) + tmp_name.flush() + set_meta_tool = toolbox.load_tool( tmp_name.name ) + toolbox.tools_by_id[ set_meta_tool.id ] = set_meta_tool + self.set_external_metadata_tool = set_meta_tool + self.log.debug( "Loaded external metadata tool: %s", self.set_external_metadata_tool.id ) + def load_datatype_indexers( self, toolbox ): """Adds indexers from self.indexers to the toolbox from app""" for elem in self.indexers: diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/datatypes/sequence.py --- a/lib/galaxy/datatypes/sequence.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/datatypes/sequence.py Thu Aug 13 13:44:04 2009 -0400 @@ -334,28 +334,37 @@ """ #these metadata values are not accessable by users, always overwrite + try: + maf_reader = bx.align.maf.Reader( open( dataset.file_name ) ) + except: + return #not a maf file species = [] species_chromosomes = {} indexes = bx.interval_index_file.Indexes() - try: - maf_reader = bx.align.maf.Reader( open( dataset.file_name ) ) - while True: - pos = maf_reader.file.tell() - block = maf_reader.next() - if block is None: break - for c in block.components: - spec = c.src - chrom = None - if "." in spec: - spec, chrom = spec.split( ".", 1 ) - if spec not in species: - species.append(spec) - species_chromosomes[spec] = [] - if chrom and chrom not in species_chromosomes[spec]: - species_chromosomes[spec].append( chrom ) - indexes.add( c.src, c.forward_strand_start, c.forward_strand_end, pos, max=c.src_size ) - except: #bad MAF file - pass + while True: + pos = maf_reader.file.tell() + block = maf_reader.next() + if block is None: break + for c in block.components: + spec = c.src + chrom = None + if "." in spec: + spec, chrom = spec.split( ".", 1 ) + if spec not in species: + species.append(spec) + species_chromosomes[spec] = [] + if chrom and chrom not in species_chromosomes[spec]: + species_chromosomes[spec].append( chrom ) + forward_strand_start = c.forward_strand_start + forward_strand_end = c.forward_strand_end + try: + forward_strand_start = int( forward_strand_start ) + forward_strand_end = int( forward_strand_end ) + except ValueError: + continue #start and end are not integers, can't add component to index, goto next component + if forward_strand_end > forward_strand_start: + #require positive length; i.e. certain lines have start = end = 0 and cannot be indexed + indexes.add( c.src, forward_strand_start, forward_strand_end, pos, max=c.src_size ) dataset.metadata.species = species #only overwrite the contents if our newly determined chromosomes don't match stored chrom_file = dataset.metadata.species_chromosomes diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/jobs/__init__.py --- a/lib/galaxy/jobs/__init__.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/jobs/__init__.py Thu Aug 13 13:44:04 2009 -0400 @@ -274,7 +274,7 @@ elif idata.state == idata.states.ERROR: job_wrapper.fail( "input data %d is in error state" % ( idata.hid ) ) return JOB_INPUT_ERROR - elif idata.state != idata.states.OK: + elif idata.state != idata.states.OK and not ( idata.state == idata.states.SETTING_METADATA and job.tool_id is not None and job.tool_id == self.app.datatypes_registry.set_external_metadata_tool.id ): # need to requeue return JOB_WAIT return JOB_READY @@ -543,7 +543,7 @@ # Certain tools require tasks to be completed after job execution # ( this used to be performed in the "exec_after_process" hook, but hooks are deprecated ). if self.tool.tool_type is not None: - self.tool.exec_after_process( self.queue.app, inp_data, out_data, param_dict ) + self.tool.exec_after_process( self.queue.app, inp_data, out_data, param_dict, job = job ) # Call 'exec_after_process' hook self.tool.call_hook( 'exec_after_process', self.queue.app, inp_data=inp_data, out_data=out_data, param_dict=param_dict, diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/jobs/runners/local.py --- a/lib/galaxy/jobs/runners/local.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/jobs/runners/local.py Thu Aug 13 13:44:04 2009 -0400 @@ -104,7 +104,7 @@ #run the metadata setting script here #this is terminatable when output dataset/job is deleted #so that long running set_meta()s can be cancelled without having to reboot the server - if job_wrapper.get_state() not in [ model.Job.states.ERROR, model.Job.states.DELETED ] and self.app.config.set_metadata_externally: + if job_wrapper.get_state() not in [ model.Job.states.ERROR, model.Job.states.DELETED ] and self.app.config.set_metadata_externally and job_wrapper.output_paths: external_metadata_script = job_wrapper.setup_external_metadata( output_fnames = job_wrapper.get_output_fnames(), kwds = { 'overwrite' : False } ) #we don't want to overwrite metadata that was copied over in init_meta(), as per established behavior log.debug( 'executing external set_meta script for job %d: %s' % ( job_wrapper.job_id, external_metadata_script ) ) external_metadata_proc = subprocess.Popen( args = external_metadata_script, diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/__init__.py Thu Aug 13 13:44:04 2009 -0400 @@ -310,30 +310,6 @@ raise "Invalid LibraryDatasetDatasetAssociation specified: %s" % library_item.__class__.__name__ self.role = role -class LibraryItemInfoPermissions( object ): - def __init__( self, action, library_item, role ): - # LIBRARY_ADD -> Not Applicable - # LIBRARY_MODIFY -> Can modify LibraryItemInfoElement.contents - # LIBRARY_MANAGE -> Can change permissions on LibraryItemInfo - self.action = action - if isinstance( library_item, LibraryItemInfo ): - self.library_item_info = library_item - else: - raise "Invalid LibraryItemInfo specified: %s" % library_item.__class__.__name__ - self.role = role - -class LibraryItemInfoTemplatePermissions( object ): - def __init__( self, action, library_item, role ): - # LIBRARY_ADD -> Not Applicable - # LIBRARY_MODIFY -> Can add or delete LibraryItemInfoTemplateElements - # LIBRARY_MANAGE -> Can change permissions on LibraryItemInfoTemplate - self.action = action - if isinstance( library_item, LibraryItemInfoTemplate ): - self.library_item_info_template = library_item - else: - raise "Invalid LibraryItemInfoTemplate specified: %s" % library_item.__class__.__name__ - self.role = role - class DefaultUserPermissions( object ): def __init__( self, user, action, role ): self.user = user @@ -354,7 +330,8 @@ OK = 'ok', EMPTY = 'empty', ERROR = 'error', - DISCARDED = 'discarded' ) + DISCARDED = 'discarded', + SETTING_METADATA = 'setting_metadata' ) permitted_actions = get_permitted_actions( filter='DATASET' ) file_path = "/tmp/" engine = None @@ -701,12 +678,10 @@ self.name = name or "Unnamed library" self.description = description self.root_folder = root_folder - def get_library_item_info_templates( self, template_list=[], restrict=False ): - # We only want the next available template in the inheritable hierarchy, so we'll only extend - # template_list if it is empty - if not template_list and self.library_info_template_associations: - template_list.extend( [ lita.library_item_info_template for lita in self.library_info_template_associations if lita.library_item_info_template not in template_list ] ) - return template_list + def get_info_association( self, restrict=False ): + if self.info_association: + return self.info_association[0] + return None class LibraryFolder( object ): def __init__( self, name=None, description=None, item_count=0, order_id=None ): @@ -725,18 +700,19 @@ folder.parent_id = self.id folder.order_id = self.item_count self.item_count += 1 - def get_library_item_info_templates( self, template_list=[], restrict=False ): - # If restrict is True, we'll return only those templates directly associated with this Folder - # We only want the next available template in the inheritable hierarchy, so we'll only extend - # template_list if it is empty - if not template_list and self.library_folder_info_template_associations: - template_list.extend( [ lfita.library_item_info_template for lfita in self.library_folder_info_template_associations if lfita.library_item_info_template not in template_list ] ) - if not template_list and restrict not in [ 'True', True ] and self.parent: - self.parent.get_library_item_info_templates( template_list ) - elif not template_list and restrict not in [ 'True', True, 'folder' ] and self.library_root: - for library_root in self.library_root: - library_root.get_library_item_info_templates( template_list ) - return template_list + def get_info_association( self, restrict=False ): + # If restrict is True, we will return this folder's info_association whether it + # exists or not. If restrict is False, we'll return the next available info_association + # in the inheritable hierarchy + if self.info_association: + return self.info_association[0] + if restrict: + return None + if self.parent: + return self.parent.get_info_association() + if self.library_root: + return self.library_root[0].get_info_association() + return None @property def active_components( self ): return list( self.active_folders ) + list( self.active_datasets ) @@ -796,15 +772,6 @@ if not purged and self.purged: raise Exception( "Cannot unpurge once purged" ) purged = property( get_purged, set_purged ) - def get_library_item_info_templates( self, template_list=[], restrict=False ): - # If restrict is True, we'll return only those templates directly associated with this LibraryDataset - # We only want the next available template in the inheritable hierarchy, so we'll only extend - # template_list if it is empty - if not template_list and self.library_dataset_info_template_associations: - template_list.extend( [ ldita.library_item_info_template for ldita in self.library_dataset_info_template_associations if ldita.library_item_info_template not in template_list ] ) - if not template_list and restrict not in [ 'True', True ]: - self.folder.get_library_item_info_templates( template_list, restrict ) - return template_list class LibraryDatasetDatasetAssociation( DatasetInstance ): def __init__( self, @@ -867,105 +834,34 @@ return ldda def clear_associated_files( self, metadata_safe = False, purge = False ): return - def get_library_item_info_templates( self, template_list=[], restrict=False ): - # If restrict is True, we'll return only those templates directly associated with this LibraryDatasetDatasetAssociation - # We only want the next available template in the inheritable hierarchy, so we'll only extend - # template_list if it is empty - if not template_list and self.library_dataset_dataset_info_template_associations: - template_list.extend( [ lddita.library_item_info_template for lddita in self.library_dataset_dataset_info_template_associations if lddita.library_item_info_template not in template_list ] ) - if not template_list: - self.library_dataset.get_library_item_info_templates( template_list, restrict ) - return template_list - -class LibraryInfoTemplateAssociation( object ): - pass - -class LibraryFolderInfoTemplateAssociation( object ): - pass - -class LibraryDatasetInfoTemplateAssociation( object ): - pass - -class LibraryDatasetDatasetInfoTemplateAssociation( object ): - pass - -class LibraryItemInfoTemplate( object ): - def add_element( self, element = None, name = None, description = None ): - if element: - raise "undefined" - else: - new_elem = LibraryItemInfoTemplateElement() - new_elem.name = name - new_elem.description = description - new_elem.order_id = self.item_count - self.item_count += 1 - self.flush() - new_elem.library_item_info_template_id = self.id - new_elem.flush() - return new_elem - -class LibraryItemInfoTemplateElement( object ): - pass + def get_info_association( self, restrict=False ): + # If restrict is True, we will return this ldda's info_association whether it + # exists or not. If restrict is False, we'll return the next available info_association + # in the inheritable hierarchy + if self.info_association: + return self.info_association[0] + if restrict: + return None + return self.library_dataset.folder.get_info_association() class LibraryInfoAssociation( object ): - def __init__( self, user=None ): - self.user = user - def set_library_item( self, library_item ): - if isinstance( library_item, Library ): - self.library = library_item - else: - raise "Invalid Library specified: %s" % library_item.__class__.__name__ + def __init__( self, library, form_definition, info ): + self.library = library + self.template = form_definition + self.info = info class LibraryFolderInfoAssociation( object ): - def __init__( self, user=None ): - self.user = user - def set_library_item( self, library_item ): - if isinstance( library_item, LibraryFolder ): - self.folder = library_item - else: - raise "Invalid Library specified: %s" % library_item.__class__.__name__ - -class LibraryDatasetInfoAssociation( object ): - def __init__( self, user=None ): - self.user = user - def set_library_item( self, library_item ): - if isinstance( library_item, LibraryDataset ): - self.library_dataset = library_item - else: - raise "Invalid Library specified: %s" % library_item.__class__.__name__ + def __init__( self, folder, form_definition, info ): + self.folder = folder + self.template = form_definition + self.info = info class LibraryDatasetDatasetInfoAssociation( object ): - def __init__( self, user=None ): - self.user = user - def set_library_item( self, library_item ): - if isinstance( library_item, LibraryDatasetDatasetAssociation ): - self.library_dataset_dataset_association = library_item - else: - raise "Invalid Library specified: %s" % library_item.__class__.__name__ + def __init__( self, library_dataset_dataset_association, form_definition, info ): + self.library_dataset_dataset_association = library_dataset_dataset_association + self.template = form_definition + self.info = info -class LibraryItemInfo( object ): - def __init__( self, user=None ): - self.user = user - def get_element_by_template_element( self, template_element, create_element=False ): - for element in self.elements: - if element.library_item_info_template_element == template_element: - return element - if create_element: - # Template elements may have been added to the template after the - # library item initially inherited it, so we'll add the additional - # element to the library item - element = LibraryItemInfoElement() - element.library_item_info_template_element = template_element - element.library_item_info = self - element.flush() - self.elements.append( element ) - return element - else: - return None - -class LibraryItemInfoElement( object ): - pass - class ValidationError( object ): def __init__( self, message=None, err_type=None, attributes=None ): self.message = message @@ -1102,8 +998,7 @@ raise # Return filename inside hashed directory return os.path.abspath( os.path.join( path, "metadata_%d.dat" % self.id ) ) - - + class FormDefinition( object ): def __init__(self, name=None, desc=None, fields=[], current_form=None): self.name = name diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/mapping.py --- a/lib/galaxy/model/mapping.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/mapping.py Thu Aug 13 13:44:04 2009 -0400 @@ -216,22 +216,6 @@ Column( "library_dataset_dataset_association_id", Integer, ForeignKey( "library_dataset_dataset_association.id" ), nullable=True, index=True ), Column( "role_id", Integer, ForeignKey( "role.id" ), index=True ) ) -LibraryItemInfoPermissions.table = Table( "library_item_info_permissions", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "action", TEXT ), - Column( "library_item_info_id", Integer, ForeignKey( "library_item_info.id" ), nullable=True, index=True ), - Column( "role_id", Integer, ForeignKey( "role.id" ), index=True ) ) - -LibraryItemInfoTemplatePermissions.table = Table( "library_item_info_template_permissions", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "action", TEXT ), - Column( "library_item_info_template_id", Integer, ForeignKey( "library_item_info_template.id" ), nullable=True, index=True ), - Column( "role_id", Integer, ForeignKey( "role.id" ), index=True ) ) - DefaultUserPermissions.table = Table( "default_user_permissions", metadata, Column( "id", Integer, primary_key=True ), Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ), @@ -299,105 +283,23 @@ Column( "purged", Boolean, index=True, default=False ), Column( "genome_build", TrimmedString( 40 ) ) ) -LibraryItemInfoTemplateElement.table = Table( "library_item_info_template_element", metadata, +LibraryInfoAssociation.table = Table( 'library_info_association', metadata, Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "optional", Boolean, index=True, default=True ), - Column( "deleted", Boolean, index=True, default=False ), - Column( "name", TEXT ), - Column( "description", TEXT ), - Column( "type", TEXT, default='string' ), - Column( "order_id", Integer ), - Column( "options", JSONType() ), - Column( "library_item_info_template_id", Integer, ForeignKey( "library_item_info_template.id" ), index=True ) ) - -LibraryItemInfoTemplate.table = Table( "library_item_info_template", metadata, + Column( "library_id", Integer, ForeignKey( "library.id" ), index=True ), + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ) ) + +LibraryFolderInfoAssociation.table = Table( 'library_folder_info_association', metadata, Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "optional", Boolean, index=True, default=True ), - Column( "deleted", Boolean, index=True, default=False ), - Column( "name", TEXT ), - Column( "description", TEXT ), - Column( "item_count", Integer, default=0 ) ) + Column( "library_folder_id", Integer, ForeignKey( "library_folder.id" ), nullable=True, index=True ), + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ) ) -LibraryInfoTemplateAssociation.table = Table( "library_info_template_association", metadata, +LibraryDatasetDatasetInfoAssociation.table = Table( 'library_dataset_dataset_info_association', metadata, Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "library_id", Integer, ForeignKey( "library.id" ), nullable=True, index=True ), - Column( "library_item_info_template_id", Integer, ForeignKey( "library_item_info_template.id" ), index=True ) ) - -LibraryFolderInfoTemplateAssociation.table = Table( "library_folder_info_template_association", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "library_folder_id", Integer, ForeignKey( "library_folder.id" ), nullable=True, index=True ), - Column( "library_item_info_template_id", Integer, ForeignKey( "library_item_info_template.id" ), index=True ) ) - -LibraryDatasetInfoTemplateAssociation.table = Table( "library_dataset_info_template_association", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "library_dataset_id", Integer, ForeignKey( "library_dataset.id" ), nullable=True, index=True ), - Column( "library_item_info_template_id", Integer, ForeignKey( "library_item_info_template.id" ), index=True ) ) - -LibraryDatasetDatasetInfoTemplateAssociation.table = Table( "library_dataset_dataset_info_template_association", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), Column( "library_dataset_dataset_association_id", Integer, ForeignKey( "library_dataset_dataset_association.id" ), nullable=True, index=True ), - Column( "library_item_info_template_id", Integer, ForeignKey( "library_item_info_template.id" ), index=True ) ) - -LibraryItemInfoElement.table = Table( "library_item_info_element", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "contents", JSONType() ), - Column( "library_item_info_id", Integer, ForeignKey( "library_item_info.id" ), index=True ), - Column( "library_item_info_template_element_id", Integer, ForeignKey( "library_item_info_template_element.id" ), index=True ) ) - -LibraryItemInfo.table = Table( "library_item_info", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "deleted", Boolean, index=True, default=False ), - Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), nullable=True, index=True ), - Column( "library_item_info_template_id", Integer, ForeignKey( "library_item_info_template.id" ), nullable=True, index=True ) - ) - -LibraryInfoAssociation.table = Table( "library_info_association", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "library_id", Integer, ForeignKey( "library.id" ), nullable=True, index=True ), - Column( "library_item_info_id", Integer, ForeignKey( "library_item_info.id" ), index=True ), - Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), nullable=True, index=True ) ) - -LibraryFolderInfoAssociation.table = Table( "library_folder_info_association", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "library_folder_id", Integer, ForeignKey( "library_folder.id" ), nullable=True, index=True ), - Column( "library_item_info_id", Integer, ForeignKey( "library_item_info.id" ), index=True ), - Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), nullable=True, index=True ) ) - -LibraryDatasetInfoAssociation.table = Table( "library_dataset_info_association", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "library_dataset_id", Integer, ForeignKey( "library_dataset.id" ), nullable=True, index=True ), - Column( "library_item_info_id", Integer, ForeignKey( "library_item_info.id" ), index=True ), - Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), nullable=True, index=True ) ) - -LibraryDatasetDatasetInfoAssociation.table = Table( "library_dataset_dataset_info_association", metadata, - Column( "id", Integer, primary_key=True ), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "library_dataset_dataset_association_id", Integer, ForeignKey( "library_dataset_dataset_association.id" ), nullable=True, index=True ), - Column( "library_item_info_id", Integer, ForeignKey( "library_item_info.id" ), index=True ), - Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), nullable=True, index=True ) ) + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ) ) Job.table = Table( "job", metadata, Column( "id", Integer, primary_key=True ), @@ -545,7 +447,6 @@ Column( "deleted", Boolean, index=True, default=False ), Column( "purged", Boolean, index=True, default=False ) ) - FormDefinitionCurrent.table = Table('form_definition_current', metadata, Column( "id", Integer, primary_key=True), Column( "create_time", DateTime, default=now ), @@ -553,20 +454,17 @@ Column( "latest_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ), Column( "deleted", Boolean, index=True, default=False )) -# new table to store all the forms which is created by the admin FormDefinition.table = Table('form_definition', metadata, Column( "id", Integer, primary_key=True), Column( "create_time", DateTime, default=now ), Column( "update_time", DateTime, default=now, onupdate=now ), Column( "name", TrimmedString( 255 ), nullable=False ), Column( "desc", TEXT ), - Column( "form_definition_current_id", + Column( "form_definition_current_id", Integer, - ForeignKey( "form_definition_current.id", - name='for_def_form_def_current_id_fk', - use_alter=True), + ForeignKey( "form_definition_current.id", name='for_def_form_def_current_id_fk', use_alter=True ), index=True ), - Column( "fields", JSONType())) + Column( "fields", JSONType() ) ) RequestType.table = Table('request_type', metadata, Column( "id", Integer, primary_key=True), @@ -598,15 +496,8 @@ Column( "state", TrimmedString( 255 ), index=True ), Column( "deleted", Boolean, index=True, default=False ) ) -RequestState_table = Table('request_state', metadata, - Column( "id", Integer, primary_key=True), - Column( "create_time", DateTime, default=now ), - Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "name", TrimmedString( 255 ), nullable=False ), - Column( "desc", TEXT )) - Sample.table = Table('sample', metadata, - Column( "id", Integer, primary_key=True), + Column( "id", Integer, primary_key=True ), Column( "create_time", DateTime, default=now ), Column( "update_time", DateTime, default=now, onupdate=now ), Column( "name", TrimmedString( 255 ), nullable=False ), @@ -616,10 +507,8 @@ Column( "bar_code", TrimmedString( 255 ), index=True ), Column( "deleted", Boolean, index=True, default=False ) ) -# new table to store all the possible sample states and the sample type it -# belongs to SampleState.table = Table('sample_state', metadata, - Column( "id", Integer, primary_key=True), + Column( "id", Integer, primary_key=True ), Column( "create_time", DateTime, default=now ), Column( "update_time", DateTime, default=now, onupdate=now ), Column( "name", TrimmedString( 255 ), nullable=False ), @@ -627,14 +516,12 @@ Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ) ) SampleEvent.table = Table('sample_event', metadata, - Column( "id", Integer, primary_key=True), + Column( "id", Integer, primary_key=True ), Column( "create_time", DateTime, default=now ), Column( "update_time", DateTime, default=now, onupdate=now ), Column( "sample_id", Integer, ForeignKey( "sample.id" ), index=True ), Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ), Column( "comment", TEXT ) ) - - # With the tables defined we can define the mappers and setup the # relationships between the model objects. @@ -652,7 +539,8 @@ assign_mapper( context, FormValues, FormValues.table, properties=dict( form_definition=relation( FormDefinition, primaryjoin=( FormValues.table.c.form_definition_id == FormDefinition.table.c.id ) ) - ) ) + ) +) assign_mapper( context, Request, Request.table, properties=dict( values=relation( FormValues, @@ -863,25 +751,20 @@ ) ) -assign_mapper( context, LibraryItemInfoPermissions, LibraryItemInfoPermissions.table, +assign_mapper( context, Library, Library.table, properties=dict( - library_item_info = relation( LibraryItemInfo, backref="actions" ), - role=relation( Role, backref="library_item_info_actions" ) - ) + root_folder=relation( LibraryFolder, backref=backref( "library_root" ) ) + ) ) -assign_mapper( context, LibraryItemInfoTemplatePermissions, LibraryItemInfoTemplatePermissions.table, - properties=dict( - library_item_info_template = relation( LibraryItemInfoTemplate, backref="actions" ), - role=relation( Role, backref="library_item_info_template_actions" ) - ) -) - -assign_mapper( context, Library, Library.table, - properties=dict( - root_folder=relation( LibraryFolder, - backref=backref( "library_root" ) ) - ) ) +assign_mapper( context, LibraryInfoAssociation, LibraryInfoAssociation.table, + properties=dict( library=relation( Library, + primaryjoin=( LibraryInfoAssociation.table.c.library_id == Library.table.c.id ), backref="info_association" ), + template=relation( FormDefinition, + primaryjoin=( LibraryInfoAssociation.table.c.form_definition_id == FormDefinition.table.c.id ) ), + info=relation( FormValues, + primaryjoin=( LibraryInfoAssociation.table.c.form_values_id == FormValues.table.c.id ) ) + ) ) assign_mapper( context, LibraryFolder, LibraryFolder.table, properties=dict( @@ -900,6 +783,15 @@ lazy=False, viewonly=True ) ) ) + +assign_mapper( context, LibraryFolderInfoAssociation, LibraryFolderInfoAssociation.table, + properties=dict( folder=relation( LibraryFolder, + primaryjoin=( LibraryFolderInfoAssociation.table.c.library_folder_id == LibraryFolder.table.c.id ), backref="info_association" ), + template=relation( FormDefinition, + primaryjoin=( LibraryFolderInfoAssociation.table.c.form_definition_id == FormDefinition.table.c.id ) ), + info=relation( FormValues, + primaryjoin=( LibraryFolderInfoAssociation.table.c.form_values_id == FormValues.table.c.id ) ) + ) ) assign_mapper( context, LibraryDataset, LibraryDataset.table, properties=dict( @@ -931,65 +823,14 @@ primaryjoin=( ( LibraryDatasetDatasetAssociation.table.c.parent_id == LibraryDatasetDatasetAssociation.table.c.id ) & ( LibraryDatasetDatasetAssociation.table.c.visible == True ) ) ) ) ) -assign_mapper( context, LibraryItemInfoTemplateElement, LibraryItemInfoTemplateElement.table, - properties=dict( library_item_info_template=relation( LibraryItemInfoTemplate, backref="elements" ), - ) ) - -assign_mapper( context, LibraryItemInfoTemplate, LibraryItemInfoTemplate.table ) - -assign_mapper( context, LibraryInfoTemplateAssociation, LibraryInfoTemplateAssociation.table, - properties=dict( library=relation( Library, backref="library_info_template_associations" ), - library_item_info_template = relation( LibraryItemInfoTemplate, backref="library_info_template_associations" ), - ) ) - -assign_mapper( context, LibraryFolderInfoTemplateAssociation, LibraryFolderInfoTemplateAssociation.table, - properties=dict( folder=relation( LibraryFolder, backref="library_folder_info_template_associations" ), - library_item_info_template = relation( LibraryItemInfoTemplate, backref="library_folder_info_template_associations" ), - ) ) - -assign_mapper( context, LibraryDatasetInfoTemplateAssociation, LibraryDatasetInfoTemplateAssociation.table, - properties=dict( library_dataset=relation( LibraryDataset, backref="library_dataset_info_template_associations" ), - library_item_info_template = relation( LibraryItemInfoTemplate, backref="library_dataset_info_template_associations" ), - ) ) - -assign_mapper( context, LibraryDatasetDatasetInfoTemplateAssociation, LibraryDatasetDatasetInfoTemplateAssociation.table, - properties=dict( library_dataset_dataset_association = relation( LibraryDatasetDatasetAssociation, backref="library_dataset_dataset_info_template_associations" ), - library_item_info_template = relation( LibraryItemInfoTemplate, backref="library_dataset_dataset_info_template_associations" ), - ) ) - -assign_mapper( context, LibraryItemInfoElement, LibraryItemInfoElement.table, - properties=dict( library_item_info=relation( LibraryItemInfo, backref="elements" ), - library_item_info_template_element=relation( LibraryItemInfoTemplateElement ) - ) ) - -assign_mapper( context, LibraryItemInfo, LibraryItemInfo.table, - properties=dict( library_item_info_template=relation( LibraryItemInfoTemplate, backref="library_item_infos" ), - user=relation( User.mapper ) - ) ) - -assign_mapper( context, LibraryInfoAssociation, LibraryInfoAssociation.table, - properties=dict( library=relation( Library, backref="library_info_associations" ), - library_item_info = relation( LibraryItemInfo, backref="library_info_associations" ), - user=relation( User.mapper ) - ) ) - -assign_mapper( context, LibraryFolderInfoAssociation, LibraryFolderInfoAssociation.table, - properties=dict( folder=relation( LibraryFolder, backref="library_folder_info_associations" ), - library_item_info = relation( LibraryItemInfo, backref="library_folder_info_associations" ), - user=relation( User.mapper ) - ) ) - -assign_mapper( context, LibraryDatasetInfoAssociation, LibraryDatasetInfoAssociation.table, - properties=dict( library_dataset=relation( LibraryDataset, backref="library_dataset_info_associations" ), - library_item_info = relation( LibraryItemInfo, backref="library_dataset_info_associations" ), - user=relation( User.mapper ) - ) ) - assign_mapper( context, LibraryDatasetDatasetInfoAssociation, LibraryDatasetDatasetInfoAssociation.table, - properties=dict( library_dataset_dataset_association = relation( LibraryDatasetDatasetAssociation, backref="library_dataset_dataset_info_associations" ), - library_item_info = relation( LibraryItemInfo, backref="library_dataset_dataset_info_associations" ), - user=relation( User.mapper ) - ) ) + properties=dict( library_dataset_dataset_association=relation( LibraryDatasetDatasetAssociation, + primaryjoin=( LibraryDatasetDatasetInfoAssociation.table.c.library_dataset_dataset_association_id == LibraryDatasetDatasetAssociation.table.c.id ), backref="info_association" ), + template=relation( FormDefinition, + primaryjoin=( LibraryDatasetDatasetInfoAssociation.table.c.form_definition_id == FormDefinition.table.c.id ) ), + info=relation( FormValues, + primaryjoin=( LibraryDatasetDatasetInfoAssociation.table.c.form_values_id == FormValues.table.c.id ) ) + ) ) assign_mapper( context, JobToInputDatasetAssociation, JobToInputDatasetAssociation.table, properties=dict( job=relation( Job ), dataset=relation( HistoryDatasetAssociation, lazy=False ) ) ) diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0006_change_qual_datatype.py --- a/lib/galaxy/model/migrate/versions/0006_change_qual_datatype.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0006_change_qual_datatype.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,3 +1,7 @@ +""" +This migration script changes certain values in the history_dataset_association.extension +column, specifically 'qual' is chaged to be 'qual454'. +""" from sqlalchemy import * from sqlalchemy.orm import * from migrate import * @@ -13,9 +17,17 @@ metadata = MetaData( migrate_engine ) db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, transactional=False ) ) + +def display_migration_details(): + print "========================================" + print "This migration script changes certain values in the history_dataset_association.extension" + print "column, specifically 'qual' is chaged to be 'qual454'." + print "========================================" + HistoryDatasetAssociation_table = Table( "history_dataset_association", metadata, autoload=True ) - + def upgrade(): + display_migration_details() # Load existing tables metadata.reflect() # Add 2 indexes to the galaxy_user table @@ -42,6 +54,5 @@ except Exception, e: log.debug( "Dropping index 'ix_hda_extension' to history_dataset_association table failed: %s" % ( str( e ) ) ) - def downgrade(): pass diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0007_sharing_histories.py --- a/lib/galaxy/model/migrate/versions/0007_sharing_histories.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0007_sharing_histories.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,3 +1,8 @@ +""" +This migration script creates the new history_user_share_association table, and adds +a new boolean type column to the history table. This provides support for sharing +histories in the same way that workflows are shared. +""" from sqlalchemy import * from sqlalchemy.orm import * from migrate import * @@ -14,6 +19,13 @@ metadata = MetaData( migrate_engine ) +def display_migration_details(): + print "========================================" + print "This migration script creates the new history_user_share_association table, and adds" + print "a new boolean type column to the history table. This provides support for sharing" + print "histories in the same way that workflows are shared." + print "========================================" + HistoryUserShareAssociation_table = Table( "history_user_share_association", metadata, Column( "id", Integer, primary_key=True ), Column( "history_id", Integer, ForeignKey( "history.id" ), index=True ), @@ -21,6 +33,7 @@ ) def upgrade(): + display_migration_details() # Load existing tables metadata.reflect() # Create the history_user_share_association table diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0008_galaxy_forms.py --- a/lib/galaxy/model/migrate/versions/0008_galaxy_forms.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0008_galaxy_forms.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,3 +1,14 @@ +""" +This migration script adds the following new tables for supporting Galaxy forms: +1) form_definition_current +2) form_definition +3) form_values +4) request_type +5) request +6) sample +7) sample_state +8) sample_event +""" from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.exceptions import * @@ -22,15 +33,26 @@ metadata = MetaData( migrate_engine ) db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, transactional=False ) ) +def display_migration_details(): + print "========================================" + print "This migration script adds the following new tables for supporting Galaxy forms:" + print "1) form_definition_current" + print "2) form_definition" + print "3) form_values" + print "4) request_type" + print "5) request" + print "6) sample" + print "7) sample_state" + print "8) sample_event" + print "========================================" FormDefinitionCurrent_table = Table('form_definition_current', metadata, Column( "id", Integer, primary_key=True), Column( "create_time", DateTime, default=now ), Column( "update_time", DateTime, default=now, onupdate=now ), - Column( "latest_form_id", Integer, - #ForeignKey( "form_definition.id", use_alter=True, name='form_definition_current_latest_form_id_fk'), - index=True ), + Column( "latest_form_id", Integer, index=True ), Column( "deleted", Boolean, index=True, default=False )) + FormDefinition_table = Table('form_definition', metadata, Column( "id", Integer, primary_key=True), Column( "create_time", DateTime, default=now ), @@ -55,7 +77,7 @@ Column( "desc", TEXT ), Column( "request_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ), Column( "sample_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ) ) -# request table + Request_table = Table('request', metadata, Column( "id", Integer, primary_key=True), Column( "create_time", DateTime, default=now ), @@ -94,13 +116,10 @@ Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ), Column( "comment", TEXT ) ) - - - def upgrade(): + display_migration_details() # Load existing tables metadata.reflect() - # Add all of the new tables above # metadata.create_all() try: @@ -145,8 +164,6 @@ SampleEvent_table.create() except Exception, e: log.debug( "Creating sample_event table failed: %s" % str( e ) ) - - def downgrade(): # Load existing tables @@ -183,7 +200,3 @@ SampleEvent_table.drop() except Exception, e: log.debug( "Dropping sample_event table failed: %s" % str( e ) ) - - - - diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0009_request_table.py --- a/lib/galaxy/model/migrate/versions/0009_request_table.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0009_request_table.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,3 +1,8 @@ +""" +This migration script adds a new column to 2 tables: +1) a new boolean type column named 'submitted' to the 'request' table +2) a new string type column named 'bar_code' to the 'sample' table +""" from sqlalchemy import * from sqlalchemy.orm import * from migrate import * @@ -15,11 +20,17 @@ metadata = MetaData( migrate_engine ) +def display_migration_details(): + print "========================================" + print "This migration script adds a new column to 2 tables:" + print "1) a new boolean type column named 'submitted' to the 'request' table" + print "2) a new string type column named 'bar_code' to the 'sample' table" + print "========================================" def upgrade(): + display_migration_details() # Load existing tables metadata.reflect() - # Add 1 column to the request table try: Request_table = Table( "request", metadata, autoload=True ) @@ -33,7 +44,6 @@ assert col is Request_table.c.submitted except Exception, e: log.debug( "Adding column 'submitted' to request table failed: %s" % ( str( e ) ) ) - # Add 1 column to the sample table try: Sample_table = Table( "sample", metadata, autoload=True ) @@ -49,4 +59,4 @@ log.debug( "Adding column 'bar_code' to sample table failed: %s" % ( str( e ) ) ) def downgrade(): - pass \ No newline at end of file + pass diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0010_hda_display_at_authz_table.py --- a/lib/galaxy/model/migrate/versions/0010_hda_display_at_authz_table.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0010_hda_display_at_authz_table.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,3 +1,13 @@ +""" +This migration script adds the history_dataset_association_display_at_authorization table, +which allows 'private' datasets to be displayed at external sites without making them public. +If using mysql, this script will display the following error, which is corrected in the next +migration script: + +history_dataset_association_display_at_authorization table failed: (OperationalError) +(1059, "Identifier name 'ix_history_dataset_association_display_at_authorization_update_time' +is too long +""" from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.exceptions import * @@ -22,6 +32,17 @@ metadata = MetaData( migrate_engine ) db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, transactional=False ) ) +def display_migration_details(): + print "========================================" + print "This migration script adds the history_dataset_association_display_at_authorization table, which" + print "allows 'private' datasets to be displayed at external sites without making them public." + print "" + print "If using mysql, this script will display the following error, which is corrected in the next migration" + print "script: history_dataset_association_display_at_authorization table failed: (OperationalError)" + print "(1059, 'Identifier name 'ix_history_dataset_association_display_at_authorization_update_time'" + print "is too long." + print "========================================" + HistoryDatasetAssociationDisplayAtAuthorization_table = Table( "history_dataset_association_display_at_authorization", metadata, Column( "id", Integer, primary_key=True ), Column( "create_time", DateTime, default=now ), @@ -31,13 +52,14 @@ Column( "site", TrimmedString( 255 ) ) ) def upgrade(): + display_migration_details() # Load existing tables metadata.reflect() try: HistoryDatasetAssociationDisplayAtAuthorization_table.create() except Exception, e: log.debug( "Creating history_dataset_association_display_at_authorization table failed: %s" % str( e ) ) - + def downgrade(): # Load existing tables metadata.reflect() diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0011_v0010_mysql_index_fix.py --- a/lib/galaxy/model/migrate/versions/0011_v0010_mysql_index_fix.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0011_v0010_mysql_index_fix.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,3 +1,8 @@ +""" +This script fixes a problem introduced in 0010_hda_display_at_atuhz_table.py. MySQL has a +name length limit and thus the index "ix_hdadaa_history_dataset_association_id" has to be +manually created. +""" from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.exceptions import * @@ -22,6 +27,13 @@ metadata = MetaData( migrate_engine ) db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, transactional=False ) ) +def display_migration_details(): + print "========================================" + print "This script fixes a problem introduced in the previous migration script ( 9->10 ). MySQL" + print "has a name length limit and thus the index 'ix_hdadaa_history_dataset_association_id' has" + print "to be manually created." + print "========================================" + HistoryDatasetAssociationDisplayAtAuthorization_table = Table( "history_dataset_association_display_at_authorization", metadata, Column( "id", Integer, primary_key=True ), Column( "create_time", DateTime, default=now ), @@ -31,6 +43,7 @@ Column( "site", TrimmedString( 255 ) ) ) def upgrade(): + display_migration_details() if migrate_engine.name == 'mysql': # Load existing tables metadata.reflect() @@ -39,7 +52,7 @@ i.create() except Exception, e: log.debug( "Adding index 'ix_hdadaa_history_dataset_association_id' to table 'history_dataset_association_display_at_authorization' table failed: %s" % str( e ) ) - + def downgrade(): if migrate_engine.name == 'mysql': # Load existing tables diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0012_user_address.py --- a/lib/galaxy/model/migrate/versions/0012_user_address.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0012_user_address.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,13 +1,20 @@ +""" +This script adds a new user_address table that is currently only used with sample requests, where +a user can select from a list of his addresses to associate with the request. This script also +drops the request.submitted column which was boolean and replaces it with a request.state column +which is a string, allowing for more flexibility with request states. +""" from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.exceptions import * from migrate import * from migrate.changeset import * - import datetime now = datetime.datetime.utcnow +import sys, logging +# Need our custom types, but don't import anything else from model +from galaxy.model.custom_types import * -import sys, logging log = logging.getLogger( __name__ ) log.setLevel(logging.DEBUG) handler = logging.StreamHandler( sys.stdout ) @@ -16,12 +23,16 @@ handler.setFormatter( formatter ) log.addHandler( handler ) -# Need our custom types, but don't import anything else from model -from galaxy.model.custom_types import * - metadata = MetaData( migrate_engine ) db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, transactional=False ) ) +def display_migration_details(): + print "========================================" + print "This script adds a new user_address table that is currently only used with sample requests, where" + print "a user can select from a list of his addresses to associate with the request. This script also" + print "drops the request.submitted column which was boolean and replaces it with a request.state column" + print "which is a string, allowing for more flexibility with request states." + print "========================================" UserAddress_table = Table( "user_address", metadata, Column( "id", Integer, primary_key=True), @@ -40,27 +51,15 @@ Column( "deleted", Boolean, index=True, default=False ), Column( "purged", Boolean, index=True, default=False ) ) -#RequestState_table = Table('request_state', metadata, -# Column( "id", Integer, primary_key=True), -# Column( "create_time", DateTime, default=now ), -# Column( "update_time", DateTime, default=now, onupdate=now ), -# Column( "name", TrimmedString( 255 ), nullable=False ), -# Column( "desc", TEXT )) - def upgrade(): + display_migration_details() # Load existing tables metadata.reflect() - # Add all of the new tables above try: UserAddress_table.create() except Exception, e: log.debug( "Creating user_address table failed: %s" % str( e ) ) -# try: -# RequestState_table.create() -# except Exception, e: -# log.debug( "Creating request_state table failed: %s" % str( e ) ) - # Add 1 column to the request_type table try: RequestType_table = Table( "request_type", metadata, autoload=True ) @@ -74,7 +73,6 @@ assert col is RequestType_table.c.deleted except Exception, e: log.debug( "Adding column 'deleted' to request_type table failed: %s" % ( str( e ) ) ) - # Delete the submitted column try: Request_table = Table( "request", metadata, autoload=True ) @@ -92,27 +90,6 @@ assert col is Request_table.c.state except Exception, e: log.debug( "Adding column 'state' to request table failed: %s" % ( str( e ) ) ) -# -# # new column which points to the current state in the request_state table -# try: -# col = Column( "request_state_id", Integer, index=True ) -# col.create( Request_table ) -# assert col is Request_table.c.request_state_id -# except Exception, e: -# log.debug( "Adding column 'request_state_id' to request table failed: %s" % ( str( e ) ) ) -# # Add 1 foreign key constraint to the form_definition_current table -# if RequestState_table and Request_table: -# try: -# cons = ForeignKeyConstraint( [Request_table.c.request_state_id], -# [RequestState_table.c.id], -# name='request_request_state_id_fk' ) -# # Create the constraint -# cons.create() -# except Exception, e: -# log.debug( "Adding foreign key constraint 'request_request_state_id_fk' to table 'request' failed: %s" % ( str( e ) ) ) - def downgrade(): pass - - diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/model/migrate/versions/0013_change_lib_item_templates_to_forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/model/migrate/versions/0013_change_lib_item_templates_to_forms.py Thu Aug 13 13:44:04 2009 -0400 @@ -0,0 +1,255 @@ +""" +This migration script eliminates all of the tables that were used for the 1st version of the +library templates where template fields and contents were each stored as a separate table row +in various library item tables. All of these tables are dropped in this script, eliminating all +existing template data. A total of 14 existing tables are dropped. + +We're now basing library templates on forms, so field contents are +stored as a jsonified list in the form_values table. This script introduces the following 3 +new association tables: +1) library_info_association +2) library_folder_info_association +3) library_dataset_dataset_info_association + +If using mysql, this script will throw an (OperationalError) exception due to a long index name on +the library_dataset_dataset_info_association table, which is OK because the script creates an index +with a shortened name. +""" +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.exceptions import * +from migrate import * +from migrate.changeset import * +import sys, logging + +log = logging.getLogger( __name__ ) +log.setLevel(logging.DEBUG) +handler = logging.StreamHandler( sys.stdout ) +format = "%(name)s %(levelname)s %(asctime)s %(message)s" +formatter = logging.Formatter( format ) +handler.setFormatter( formatter ) +log.addHandler( handler ) + +metadata = MetaData( migrate_engine ) + +def display_migration_details(): + print "========================================" + print "This migration script eliminates all of the tables that were used for the 1st version of the" + print "library templates where template fields and contents were each stored as a separate table row" + print "in various library item tables. All of these tables are dropped in this script, eliminating all" + print "existing template data. A total of 14 existing tables are dropped." + print "" + print "We're now basing library templates on Galaxy forms, so field contents are stored as a jsonified" + print "list in the form_values table. This script introduces the following 3 new association tables:" + print "1) library_info_association" + print "2) library_folder_info_association" + print "3) library_dataset_dataset_info_association" + print "" + print "If using mysql, this script will throw an (OperationalError) exception due to a long index name" + print "on the library_dataset_dataset_info_association table, which is OK because the script creates" + print "an index with a shortened name." + print "========================================" + +if migrate_engine.name == 'postgres': + # http://blog.pythonisito.com/2008/01/cascading-drop-table-with-sqlalchemy.htm... + from sqlalchemy.databases import postgres + class PGCascadeSchemaDropper(postgres.PGSchemaDropper): + def visit_table(self, table): + for column in table.columns: + if column.default is not None: + self.traverse_single(column.default) + self.append("\nDROP TABLE " + + self.preparer.format_table(table) + + " CASCADE") + self.execute() + postgres.dialect.schemadropper = PGCascadeSchemaDropper + +LibraryInfoAssociation_table = Table( 'library_info_association', metadata, + Column( "id", Integer, primary_key=True), + Column( "library_id", Integer, ForeignKey( "library.id" ), index=True ), + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ) ) + +LibraryFolderInfoAssociation_table = Table( 'library_folder_info_association', metadata, + Column( "id", Integer, primary_key=True), + Column( "library_folder_id", Integer, ForeignKey( "library_folder.id" ), nullable=True, index=True ), + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ) ) + +LibraryDatasetDatasetInfoAssociation_table = Table( 'library_dataset_dataset_info_association', metadata, + Column( "id", Integer, primary_key=True), + Column( "library_dataset_dataset_association_id", Integer, ForeignKey( "library_dataset_dataset_association.id" ), nullable=True, index=True ), + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ) ) + +def upgrade(): + display_migration_details() + # Load existing tables + metadata.reflect() + # Drop all of the original library_item_info tables + # NOTE: all existing library item into template data is eliminated here via table drops + try: + LibraryItemInfoPermissions_table = Table( "library_item_info_permissions", metadata, autoload=True ) + except NoSuchTableError: + LibraryItemInfoPermissions_table = None + log.debug( "Failed loading table library_item_info_permissions" ) + try: + LibraryItemInfoPermissions_table.drop() + except Exception, e: + log.debug( "Dropping library_item_info_permissions table failed: %s" % str( e ) ) + + try: + LibraryItemInfoTemplatePermissions_table = Table( "library_item_info_template_permissions", metadata, autoload=True ) + except NoSuchTableError: + LibraryItemInfoTemplatePermissions_table = None + log.debug( "Failed loading table library_item_info_template_permissions" ) + try: + LibraryItemInfoTemplatePermissions_table.drop() + except Exception, e: + log.debug( "Dropping library_item_info_template_permissions table failed: %s" % str( e ) ) + + try: + LibraryItemInfoElement_table = Table( "library_item_info_element", metadata, autoload=True ) + except NoSuchTableError: + LibraryItemInfoElement_table = None + log.debug( "Failed loading table library_item_info_element" ) + try: + LibraryItemInfoElement_table.drop() + except Exception, e: + log.debug( "Dropping library_item_info_element table failed: %s" % str( e ) ) + + try: + LibraryItemInfoTemplateElement_table = Table( "library_item_info_template_element", metadata, autoload=True ) + except NoSuchTableError: + LibraryItemInfoTemplateElement_table = None + log.debug( "Failed loading table library_item_info_template_element" ) + try: + LibraryItemInfoTemplateElement_table.drop() + except Exception, e: + log.debug( "Dropping library_item_info_template_element table failed: %s" % str( e ) ) + + try: + LibraryInfoTemplateAssociation_table = Table( "library_info_template_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryInfoTemplateAssociation_table = None + log.debug( "Failed loading table library_info_template_association" ) + try: + LibraryInfoTemplateAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_info_template_association table failed: %s" % str( e ) ) + + try: + LibraryFolderInfoTemplateAssociation_table = Table( "library_folder_info_template_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryFolderInfoTemplateAssociation_table = None + log.debug( "Failed loading table library_folder_info_template_association" ) + try: + LibraryFolderInfoTemplateAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_folder_info_template_association table failed: %s" % str( e ) ) + + try: + LibraryDatasetInfoTemplateAssociation_table = Table( "library_dataset_info_template_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryDatasetInfoTemplateAssociation_table = None + log.debug( "Failed loading table library_dataset_info_template_association" ) + try: + LibraryDatasetInfoTemplateAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_dataset_info_template_association table failed: %s" % str( e ) ) + + try: + LibraryDatasetDatasetInfoTemplateAssociation_table = Table( "library_dataset_dataset_info_template_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryDatasetDatasetInfoTemplateAssociation_table = None + log.debug( "Failed loading table library_dataset_dataset_info_template_association" ) + try: + LibraryDatasetDatasetInfoTemplateAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_dataset_dataset_info_template_association table failed: %s" % str( e ) ) + + try: + LibraryInfoAssociation_table = Table( "library_info_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryInfoAssociation_table = None + log.debug( "Failed loading table library_info_association" ) + try: + LibraryInfoAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_info_association table failed: %s" % str( e ) ) + + try: + LibraryFolderInfoAssociation_table = Table( "library_folder_info_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryFolderInfoAssociation_table = None + log.debug( "Failed loading table library_folder_info_association" ) + try: + LibraryFolderInfoAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_folder_info_association table failed: %s" % str( e ) ) + + try: + LibraryDatasetInfoAssociation_table = Table( "library_dataset_info_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryDatasetInfoAssociation_table = None + log.debug( "Failed loading table library_dataset_info_association" ) + try: + LibraryDatasetInfoAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_dataset_info_association table failed: %s" % str( e ) ) + + try: + LibraryDatasetDatasetInfoAssociation_table = Table( "library_dataset_dataset_info_association", metadata, autoload=True ) + except NoSuchTableError: + LibraryDatasetDatasetInfoAssociation_table = None + log.debug( "Failed loading table library_dataset_dataset_info_association" ) + try: + LibraryDatasetDatasetInfoAssociation_table.drop() + except Exception, e: + log.debug( "Dropping library_dataset_dataset_info_association table failed: %s" % str( e ) ) + + try: + LibraryItemInfo_table = Table( "library_item_info", metadata, autoload=True ) + except NoSuchTableError: + LibraryItemInfo_table = None + log.debug( "Failed loading table library_item_info" ) + try: + LibraryItemInfo_table.drop() + except Exception, e: + log.debug( "Dropping library_item_info table failed: %s" % str( e ) ) + + try: + LibraryItemInfoTemplate_table = Table( "library_item_info_template", metadata, autoload=True ) + except NoSuchTableError: + LibraryItemInfoTemplate_table = None + log.debug( "Failed loading table library_item_info_template" ) + try: + LibraryItemInfoTemplate_table.drop() + except Exception, e: + log.debug( "Dropping library_item_info_template table failed: %s" % str( e ) ) + + # Create all new tables above + try: + LibraryInfoAssociation_table.create() + except Exception, e: + log.debug( "Creating library_info_association table failed: %s" % str( e ) ) + try: + LibraryFolderInfoAssociation_table.create() + except Exception, e: + log.debug( "Creating library_folder_info_association table failed: %s" % str( e ) ) + try: + LibraryDatasetDatasetInfoAssociation_table.create() + except Exception, e: + log.debug( "Creating library_dataset_dataset_info_association table failed: %s" % str( e ) ) + # Fix index on LibraryDatasetDatasetInfoAssociation_table for mysql + if migrate_engine.name == 'mysql': + # Load existing tables + metadata.reflect() + i = Index( "ix_lddaia_ldda_id", LibraryDatasetDatasetInfoAssociation_table.c.library_dataset_dataset_association_id ) + try: + i.create() + except Exception, e: + log.debug( "Adding index 'ix_lddaia_ldda_id' to table 'library_dataset_dataset_info_association' table failed: %s" % str( e ) ) + +def downgrade(): + log.debug( "Downgrade is not possible." ) diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/security/__init__.py --- a/lib/galaxy/security/__init__.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/security/__init__.py Thu Aug 13 13:44:04 2009 -0400 @@ -75,12 +75,10 @@ self.permitted_actions = permitted_actions # List of "library_item" objects and their associated permissions and info template objects self.library_item_assocs = ( - ( self.model.Library, self.model.LibraryPermissions, self.model.LibraryInfoAssociation ), - ( self.model.LibraryFolder, self.model.LibraryFolderPermissions, self.model.LibraryFolderInfoAssociation ), - ( self.model.LibraryDataset, self.model.LibraryDatasetPermissions, self.model.LibraryDatasetInfoAssociation ), - ( self.model.LibraryDatasetDatasetAssociation, self.model.LibraryDatasetDatasetAssociationPermissions, self.model.LibraryDatasetDatasetInfoAssociation ), - ( self.model.LibraryItemInfo, self.model.LibraryItemInfoPermissions, None ), - ( self.model.LibraryItemInfoTemplate, self.model.LibraryItemInfoTemplatePermissions, None ) ) + ( self.model.Library, self.model.LibraryPermissions ), + ( self.model.LibraryFolder, self.model.LibraryFolderPermissions ), + ( self.model.LibraryDataset, self.model.LibraryDatasetPermissions ), + ( self.model.LibraryDatasetDatasetAssociation, self.model.LibraryDatasetDatasetAssociationPermissions ) ) def allow_action( self, user, action, **kwd ): if 'dataset' in kwd: return self.allow_dataset_action( user, action, kwd[ 'dataset' ] ) @@ -117,7 +115,7 @@ user_role_ids = [ r.id for r in user.all_roles() ] # Check to see if user has access to any of the roles allowed_role_assocs = [] - for item_class, permission_class, info_association_class in self.library_item_assocs: + for item_class, permission_class in self.library_item_assocs: if isinstance( library_item, item_class ): if permission_class == self.model.LibraryPermissions: allowed_role_assocs = permission_class.filter_by( action=action.action, library_id=library_item.id ).all() @@ -127,10 +125,6 @@ allowed_role_assocs = permission_class.filter_by( action=action.action, library_dataset_id=library_item.id ).all() elif permission_class == self.model.LibraryDatasetDatasetAssociationPermissions: allowed_role_assocs = permission_class.filter_by( action=action.action, library_dataset_dataset_association_id=library_item.id ).all() - elif permission_class == self.model.LibraryItemInfoPermissions: - allowed_role_assocs = permission_class.filter_by( action=action.action, library_item_info_id=library_item.id ).all() - elif permission_class == self.model.LibraryItemInfoTemplatePermissions: - allowed_role_assocs = permission_class.filter_by( action=action.action, library_item_info_template_id=library_item.id ).all() for allowed_role_assoc in allowed_role_assocs: if allowed_role_assoc.role_id in user_role_ids: return True @@ -366,7 +360,7 @@ role_assoc.delete() role_assoc.flush() # Add the new permissions on library_item - for item_class, permission_class, info_association_class in self.library_item_assocs: + for item_class, permission_class in self.library_item_assocs: if isinstance( library_item, item_class ): for action, roles in permissions.items(): if isinstance( action, Action ): @@ -396,12 +390,12 @@ permissions[role_assoc.action] = [ role_assoc.role ] self.set_all_library_permissions( target_library_item, permissions ) if user: - # The user passed will be the current Galaxy user. Make sure user's private role is included item_class = None - for item_class, permission_class, info_association_class in self.library_item_assocs: + for item_class, permission_class in self.library_item_assocs: if isinstance( target_library_item, item_class ): break if item_class: + # Make sure user's private role is included private_role = self.model.security_agent.get_private_user_role( user ) for name, action in self.permitted_actions.items(): if not permission_class.filter_by( role_id = private_role.id, action = action.action ).first(): diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/tools/__init__.py Thu Aug 13 13:44:04 2009 -0400 @@ -128,7 +128,7 @@ tree = util.parse_xml( config_file ) root = tree.getroot() # Allow specifying a different tool subclass to instantiate - if root.find( "type" ): + if root.find( "type" ) is not None: type_elem = root.find( "type" ) module = type_elem.get( 'module', 'galaxy.tools' ) cls = type_elem.get( 'class' ) @@ -1468,7 +1468,7 @@ out_data[ name ] = data return out_data - def exec_after_process( self, app, inp_data, out_data, param_dict ): + def exec_after_process( self, app, inp_data, out_data, param_dict, job = None ): if self.tool_type == 'data_source': name, data = out_data.items()[0] data.set_size() @@ -1572,6 +1572,18 @@ dataset.history.add( new_data ) new_data.flush() return primary_datasets + +class SetMetadataTool( Tool ): + def exec_after_process( self, app, inp_data, out_data, param_dict, job = None ): + for name, dataset in inp_data.iteritems(): + external_metadata = galaxy.datatypes.metadata.JobExternalOutputMetadataWrapper( job ) + if external_metadata.external_metadata_set_successfully( dataset ): + dataset.metadata.from_JSON_dict( external_metadata.get_output_filenames_by_dataset( dataset ).filename_out ) + # If setting external metadata has failed, how can we inform the user? + # For now, we'll leave the default metadata and set the state back to its original. + dataset.datatype.after_edit( dataset ) + dataset.state = param_dict.get( '__ORIGINAL_DATASET_STATE__' ) + dataset.flush() # ---- Utility classes to be factored out ----------------------------------- diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/tools/actions/metadata.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/tools/actions/metadata.py Thu Aug 13 13:44:04 2009 -0400 @@ -0,0 +1,48 @@ +from . import ToolAction +from galaxy.datatypes.metadata import JobExternalOutputMetadataWrapper + +import logging +log = logging.getLogger( __name__ ) + +class SetMetadataToolAction( ToolAction ): + """Tool action used for setting external metadata on an existing dataset""" + + def execute( self, tool, trans, incoming = {}, set_output_hid = False ): + for name, value in incoming.iteritems(): + if isinstance( value, trans.app.model.HistoryDatasetAssociation ): + dataset = value + dataset_name = name + break + else: + raise Exception( 'The dataset to set metadata on could not be determined.' ) + + # Create the job object + job = trans.app.model.Job() + job.session_id = trans.get_galaxy_session().id + job.history_id = trans.history.id + job.tool_id = tool.id + try: + # For backward compatibility, some tools may not have versions yet. + job.tool_version = tool.version + except: + job.tool_version = "1.0.0" + job.flush() #ensure job.id is available + + #add parameters to job_parameter table + incoming[ '__ORIGINAL_DATASET_STATE__' ] = dataset.state #store original dataset state, so we can restore it. A seperate table might be better (no chance of 'loosing' the original state)? + external_metadata_wrapper = JobExternalOutputMetadataWrapper( job ) + cmd_line = external_metadata_wrapper.setup_external_metadata( dataset, exec_dir = None, tmp_dir = trans.app.config.new_file_path, dataset_files_path = trans.app.model.Dataset.file_path, output_fnames = None, config_root = None, datatypes_config = None, kwds = { 'overwrite' : True } ) + incoming[ '__SET_EXTERNAL_METADATA_COMMAND_LINE__' ] = cmd_line + for name, value in tool.params_to_strings( incoming, trans.app ).iteritems(): + job.add_parameter( name, value ) + #add the dataset to job_to_input_dataset table + job.add_input_dataset( dataset_name, dataset ) + #Need a special state here to show that metadata is being set and also allow the job to run + # i.e. if state was set to 'running' the set metadata job would never run, as it would wait for input (the dataset to set metadata on) to be in a ready state + dataset.state = dataset.states.SETTING_METADATA + trans.app.model.flush() + + # Queue the job for execution + trans.app.job_queue.put( job.id, tool ) + trans.log_event( "Added set external metadata job to the job queue, id: %s" % str(job.id), tool_id=job.tool_id ) + return [] diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/tools/actions/upload.py --- a/lib/galaxy/tools/actions/upload.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/tools/actions/upload.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,4 +1,5 @@ import os, shutil, urllib, StringIO, re, gzip, tempfile, shutil, zipfile +from . import ToolAction from galaxy import datatypes, jobs from galaxy.datatypes import sniff from galaxy import model, util @@ -8,7 +9,7 @@ import logging log = logging.getLogger( __name__ ) -class UploadToolAction( object ): +class UploadToolAction( ToolAction ): # Action for uploading files def __init__( self ): self.empty = False diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/web/controllers/admin.py --- a/lib/galaxy/web/controllers/admin.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/web/controllers/admin.py Thu Aug 13 13:44:04 2009 -0400 @@ -1,9 +1,9 @@ -import shutil, StringIO, operator, urllib, gzip, tempfile, sets, string +import shutil, StringIO, operator, urllib, gzip, tempfile, sets, string, sys from datetime import datetime, timedelta from galaxy import util, datatypes from galaxy.web.base.controller import * from galaxy.model.orm import * -import sys +from galaxy.web.controllers.forms import get_all_forms, get_form_widgets import logging log = logging.getLogger( __name__ ) @@ -710,6 +710,7 @@ library=trans.app.model.Library.get( id ), deleted=deleted, created_ldda_ids=created_ldda_ids, + forms=get_all_forms( trans, filter=dict(deleted=False) ), msg=msg, messagetype=messagetype, show_deleted=show_deleted ) @@ -751,6 +752,22 @@ messagetype='done' ) ) return trans.fill_template( '/admin/library/new_library.mako', msg=msg, messagetype=messagetype ) elif action == 'information': + # See if we have any associated templates + info_association = library.get_info_association() + if info_association: + template = info_association.template + # See if we have any field contents + info = info_association.info + if info: + field_contents = {} + for index, value in enumerate( info.content ): + key = 'field_%i' % index + field_contents[ key ] = value + widgets = get_form_widgets( trans, template, field_contents ) + else: + widgets = get_form_widgets( trans, template ) + else: + widgets = [] if params.get( 'rename_library_button', False ): old_name = library.name new_name = util.restore_text( params.name ) @@ -759,8 +776,7 @@ msg = 'Enter a valid name' return trans.fill_template( '/admin/library/library_info.mako', library=library, - restrict=params.get( 'restrict', False ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype='error' ) else: @@ -780,12 +796,10 @@ messagetype='done' ) ) return trans.fill_template( '/admin/library/library_info.mako', library=library, - restrict=params.get( 'restrict', False ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) elif action == 'delete': - # TODO: need to revamp the way we delete libraries, folders and contained LibraryDatasets. def delete_folder( library_folder ): library_folder.refresh() for folder in library_folder.folders: @@ -939,6 +953,22 @@ msg=msg, messagetype=messagetype ) elif action == 'information': + # See if we have any associated templates + info_association = folder.get_info_association() + if info_association: + template = info_association.template + # See if we have any field contents + info = info_association.info + if info: + field_contents = {} + for index, value in enumerate( info.content ): + key = 'field_%i' % index + field_contents[ key ] = value + widgets = get_form_widgets( trans, template, field_contents ) + else: + widgets = get_form_widgets( trans, template ) + else: + widgets = [] if params.get( 'rename_folder_button', False ): old_name = folder.name new_name = util.restore_text( params.name ) @@ -948,8 +978,7 @@ return trans.fill_template( '/admin/library/folder_info.mako', folder=folder, library_id=library_id, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype='error' ) else: @@ -967,12 +996,10 @@ return trans.fill_template( '/admin/library/folder_info.mako', folder=folder, library_id=library_id, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) elif action == 'delete': - # TODO: need to revamp the way we delete folders and contained LibraryDatasets def delete_folder( folder ): folder.refresh() for subfolder in folder.active_folders: @@ -1045,8 +1072,6 @@ return trans.fill_template( '/admin/library/library_dataset_info.mako', library_dataset=library_dataset, library_id=library_id, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), msg=msg, messagetype=messagetype ) elif action == 'permissions': @@ -1101,7 +1126,7 @@ created_ldda_ids = trans.webapp.controllers[ 'library_dataset' ].upload_dataset( trans, controller='admin', library_id=library_id, - folder_id=folder_id, + folder_id=folder_id, replace_dataset=replace_dataset, **kwd ) if created_ldda_ids: @@ -1126,6 +1151,13 @@ msg=util.sanitize_text( msg ), messagetype=messagetype ) ) elif not id or replace_dataset: + # See if we have any associated templates + info_association = folder.get_info_association() + if info_association: + template = info_association.template + widgets = get_form_widgets( trans, template ) + else: + widgets = [] upload_option = params.get( 'upload_option', 'upload_file' ) # No dataset(s) specified, so display the upload form. Send list of data formats to the form # so the "extension" select list can be populated dynamically @@ -1150,6 +1182,7 @@ last_used_build=last_used_build, roles=roles, history=history, + widgets=widgets, msg=msg, messagetype=messagetype, replace_dataset=replace_dataset ) @@ -1175,6 +1208,22 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) + # See if we have any associated templates + info_association = ldda.get_info_association() + if info_association: + template = info_association.template + # See if we have any field contents + info = info_association.info + if info: + field_contents = {} + for index, value in enumerate( info.content ): + key = 'field_%i' % index + field_contents[ key ] = value + widgets = get_form_widgets( trans, template, field_contents ) + else: + widgets = get_form_widgets( trans, template ) + else: + widgets = [] if action == 'permissions': if params.get( 'update_roles_button', False ): permissions = {} @@ -1242,6 +1291,7 @@ library_id=library_id, deleted=deleted, show_deleted=show_deleted, + widgets=widgets, msg=msg, messagetype=messagetype ) elif action == 'edit_info': @@ -1255,8 +1305,7 @@ ldda=ldda, library_id=library_id, datatypes=ldatatypes, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) else: @@ -1293,8 +1342,7 @@ ldda=ldda, library_id=library_id, datatypes=ldatatypes, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) elif params.get( 'detect', False ): @@ -1312,8 +1360,7 @@ ldda=ldda, library_id=library_id, datatypes=ldatatypes, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) elif params.get( 'delete', False ): @@ -1324,8 +1371,7 @@ ldda=ldda, library_id=library_id, datatypes=ldatatypes, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) ldda.datatype.before_edit( ldda ) @@ -1340,8 +1386,7 @@ ldda=ldda, library_id=library_id, datatypes=ldatatypes, - restrict=params.get( 'restrict', True ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) elif ids: @@ -1553,26 +1598,17 @@ last_used_build=last_used_build, roles=roles, history=history, + widgets=widgets, msg=msg, messagetype=messagetype ) @web.expose @web.require_admin - def info_template( self, trans, library_id, id=None, num_fields=0, folder_id=None, ldda_id=None, library_dataset_id=None, **kwd ): + def info_template( self, trans, library_id, id=None, folder_id=None, ldda_id=None, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - if not num_fields: - num_fields = 0 - else: - num_fields = int( num_fields ) - if params.get( 'new_template', False ): - action = 'new_template' - elif params.get( 'permissions', False ): - action = 'permissions' - else: - action = 'edit_template' if id: - library_item = trans.app.model.LibraryItemInfoTemplate.get( int( id ) ) + library_item = trans.app.model.FormDefinition.get( int( id ) ) library_item_desc = 'information template' response_action = 'info_template' response_id = id @@ -1586,174 +1622,51 @@ library_item_desc = 'library dataset' response_action = 'library_dataset_dataset_association' response_id = ldda_id - elif library_dataset_id: - library_item = trans.app.model.LibraryDataset.get( int( library_dataset_id ) ) - library_item_desc = 'dataset' - response_action = 'library_dataset_dataset_association' - response_id = library_item.library_dataset_dataset_association.id else: library_item = trans.app.model.Library.get( int( library_id ) ) library_item_desc = 'library' response_action = 'browse_library' response_id = library_id - if action == 'new_template': - if params.get( 'create_info_template_button', False ): - return trans.fill_template( '/admin/library/new_info_template.mako', - library_item_name=library_item.name, - library_item_desc=library_item_desc, - num_fields=num_fields, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - library_dataset_id=library_dataset_id, - msg=msg, - messagetype=messagetype ) - elif params.get( 'new_info_template_button', False ): - # Make sure at least 1 template field is filled in - # TODO: Eventually we'll enhance templates to allow for required and optional fields. - proceed = False - for i in range( int( params.get( 'set_num_fields', 0 ) ) ): - elem_name = params.get( 'new_element_name_%i' % i, None ) - elem_description = params.get( 'new_element_description_%i' % i, None ) - if elem_name or elem_description: - proceed = True - break - if not proceed: - msg = "At least 1 of the fields must be completed." - return trans.fill_template( '/admin/library/new_info_template.mako', - library_item_name=library_item.name, - library_item_desc=library_item_desc, - num_fields=num_fields, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - library_dataset_id=library_dataset_id, - msg=msg, - messagetype=messagetype ) - # Create template - liit = trans.app.model.LibraryItemInfoTemplate() - liit.name = util.restore_text( params.get( 'name', '' ) ) - liit.description = util.restore_text( params.get( 'description', '' ) ) - liit.flush() - # Inherit the template's permissions from the library_item - trans.app.security_agent.copy_library_permissions( library_item, liit ) - # Create template association + forms = get_all_forms( trans, filter=dict(deleted=False) ) + if not forms: + msg = "There are no forms on which to base the template, so create a form and " + msg += "try again to add the information template to the %s." % library_item_desc + trans.response.send_redirect( web.url_for( controller='forms', + action='new', + new=True, + msg=msg, + messagetype='done' ) ) + if params.get( 'add', False ): + if params.get( 'add_info_template_button', False ): + form = trans.app.model.FormDefinition.get( int( kwd[ 'form_id' ] ) ) + #fields = list( copy.deepcopy( form.fields ) ) + form_values = trans.app.model.FormValues( form, [] ) + form_values.flush() if folder_id: - liit_assoc = trans.app.model.LibraryFolderInfoTemplateAssociation() - liit_assoc.folder = trans.app.model.LibraryFolder.get( folder_id ) + assoc = trans.app.model.LibraryFolderInfoAssociation( library_item, form, form_values ) elif ldda_id: - liit_assoc = trans.app.model.LibraryDatasetDatasetInfoTemplateAssociation() - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id ) - liit_assoc.library_dataset_dataset_association = ldda - # This response_action method requires a folder_id - folder_id = ldda.library_dataset.folder.id - elif library_dataset_id: - liit_assoc = trans.app.model.LibraryDatasetInfoTemplateAssociation() - library_dataset = trans.app.model.LibraryDataset.get( library_dataset_id ) - liit_assoc.library_dataset = library_dataset - # This response_action method requires a folder_id - folder_id = library_dataset.folder.id + assoc = trans.app.model.LibraryDatasetDatasetInfoAssociation( library_item, form, form_values ) else: - # We'll always be sent a library_id - liit_assoc = trans.app.model.LibraryInfoTemplateAssociation() - liit_assoc.library = trans.app.model.Library.get( library_id ) - liit_assoc.library_item_info_template = liit - liit_assoc.flush() - # Create and add elements - for i in range( int( params.get( 'set_num_fields', 0 ) ) ): - elem_name = params.get( 'new_element_name_%i' % i, None ) - elem_description = params.get( 'new_element_description_%i' % i, None ) - if elem_description and not elem_name: - # If we have a description but no name, the description will be both - # ( a name cannot be empty, but a description can ) - elem_name = elem_description - if elem_name: - # Skip any elements that have a missing name - liit.add_element( name=elem_name, description=elem_description ) - msg = "The new information template has been created." - return trans.response.send_redirect( web.url_for( controller='admin', - action=response_action, - id=response_id, - library_id=library_id, - folder_id=folder_id, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - return trans.fill_template( '/admin/library/create_info_template.mako', - library_item=library_item, - library_id=library_id, - msg=msg, - messagetype=messagetype ) - elif action == 'edit_template': - define_or_save = 'define' - edit_info_template_button = params.get( 'edit_info_template_button', False ) - if edit_info_template_button: - if edit_info_template_button == 'Define fields': - define_or_save = 'save' - else: - define_or_save = 'define' - # Save changes to existing attributes, only set name if nonempty/nonNone is passed, but always set description - name = params.get( 'name', None ) - if name: - library_item.name = name - library_item.description = params.get( 'description', '' ) - library_item.flush() - # Save changes to exisiting elements - for elem_id in util.listify( params.get( 'element_ids', [] ) ): - liit_element = trans.app.model.LibraryItemInfoTemplateElement.get( elem_id ) - name = params.get( 'element_name_%s' % elem_id, None ) - if name: - liit_element.name = name - liit_element.description = params.get( 'element_description_%s' % elem_id, None ) - liit_element.flush() - # Add new elements - for i in range( int( params.get( 'set_num_fields', 0 ) ) ): - elem_name = params.get( 'new_element_name_%i' % i, None ) - elem_description = params.get( 'new_element_description_%i' % i, None ) - # Skip any elements that have a missing name and description - if not elem_name: - # If we have a description but no name, the description will be both - # ( a name cannot be empty, but a description can ) - elem_name = elem_description - if elem_name: - library_item.add_element( name=elem_name, description=elem_description ) - library_item.refresh() - msg = "Information template '%s' has been updated" % library_item.name - return trans.fill_template( "/admin/library/edit_info_template.mako", - liit=library_item, - num_fields=num_fields, - library_id=library_id, - library_dataset_id=library_dataset_id, - ldda_id=ldda_id, - folder_id=folder_id, + assoc = trans.app.model.LibraryInfoAssociation( library_item, form, form_values ) + assoc.flush() + msg = 'An information template based on the form "%s" has been added to this %s.' % ( form.name, library_item_desc ) + trans.response.send_redirect( web.url_for( controller='admin', + action=response_action, + id=response_id, + msg=msg, + message_type='done' ) ) + return trans.fill_template( '/admin/library/select_info_template.mako', library_item_name=library_item.name, library_item_desc=library_item_desc, - define_or_save=define_or_save, - msg=msg, - messagetype=messagetype ) - elif action == 'permissions': - if params.get( 'update_roles_button', False ): - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - trans.app.security_agent.set_all_library_permissions( library_item, permissions ) - library_item.refresh() - msg = "Permissions updated for information template '%s'" % library_item.name - return trans.response.send_redirect( web.url_for( controller='admin', - action='info_template', - library_id=library_id, - id=id, - permissions=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - return trans.fill_template( '/admin/library/info_template_permissions.mako', - liit=library_item, library_id=library_id, + folder_id=folder_id, + ldda_id=ldda_id, + forms=forms, msg=msg, messagetype=messagetype ) @web.expose @web.require_admin - def library_item_info( self, trans, library_id, id=None, library_item_id=None, library_item_type=None, **kwd ): + def edit_template_info( self, trans, library_id, num_widgets, library_item_id=None, library_item_type=None, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) @@ -1768,8 +1681,6 @@ library_item = trans.app.model.LibraryDatasetDatasetAssociation.get( library_item_id ) # This response_action method requires a folder_id folder_id = library_item.library_dataset.folder.id - elif library_item_type == 'library_item_info_elememt': - library_item = trans.app.model.LibraryItemInfoElement.get( library_item_id ) else: msg = "Invalid library item type ( %s ) specified, id ( %s )" % ( str( library_item_type ), str( library_item_id ) ) return trans.response.send_redirect( web.url_for( controller='admin', @@ -1777,107 +1688,47 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - if params.get( 'new_info', False ): - if library_item: - if params.get( 'create_new_info_button', False ): - library_item_info_template_id = params.get( 'library_item_info_template_id', None ) - library_item_info_template = trans.app.model.LibraryItemInfoTemplate.get( int( library_item_info_template_id ) ) - # Make sure at least 1 template field is filled in - # TODO: Eventually we'll enhance templates to allow for required and optional fields. - proceed = False - for template_element in library_item_info_template.elements: - if params.get( "info_element_%s_%s" % ( library_item_info_template.id, template_element.id ), None ): - proceed = True - break - if not proceed: - msg = "At least 1 of the fields must be completed." - return trans.response.send_redirect( web.url_for( controller='admin', - action=library_item_type, - id=library_item.id, - library_id=library_id, - folder_id=folder_id, - edit_info=True, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - user = trans.get_user() - library_item_info = trans.app.model.LibraryItemInfo( user=user ) - library_item_info.library_item_info_template = library_item_info_template - library_item_info.flush() - trans.app.security_agent.copy_library_permissions( library_item_info_template, library_item_info ) - for template_element in library_item_info_template.elements: - info_element_value = params.get( "info_element_%s_%s" % ( library_item_info_template.id, template_element.id ), None ) - info_element = trans.app.model.LibraryItemInfoElement() - info_element.contents = info_element_value - info_element.library_item_info_template_element = template_element - info_element.library_item_info = library_item_info - info_element.flush() - info_association_class = None - for item_class, permission_class, info_association_class in trans.app.security_agent.library_item_assocs: - if isinstance( library_item, item_class ): - break - if info_association_class: - library_item_info_association = info_association_class( user=user ) - library_item_info_association.set_library_item( library_item ) - library_item_info_association.library_item_info = library_item_info - library_item_info_association.flush() - else: - raise 'Invalid class (%s) specified for library_item (%s)' % ( library_item.__class__, library_item.__class__.__name__ ) - msg = 'The information has been saved' - return trans.response.send_redirect( web.url_for( controller='admin', - action=library_item_type, - id=library_item.id, - library_id=library_id, - folder_id=folder_id, - edit_info=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - return trans.fill_template( "/admin/library/new_info.mako", - library_id=library_id, - library_item=library_item, - library_item_type=library_item_type, - msg=msg, - messagetype=messagetype ) - elif params.get( 'edit_info', False ): - if params.get( 'edit_info_button', False ): - ids = util.listify( id ) - for id in ids: - library_item_info_element = trans.app.model.LibraryItemInfoElement.get( int( id ) ) - new_contents = util.restore_text( params.get( ( 'info_element_%s' % id ), '' ) ) - library_item_info_element.contents = new_contents - library_item_info_element.flush() - msg = 'The information has been updated.' - return trans.response.send_redirect( web.url_for( controller='admin', - action=library_item_type, - id=library_item.id, - library_id=library_id, - folder_id=folder_id, - edit_info=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - elif params.get( 'permissions', False ): - if params.get( 'update_roles_button', False ): - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - trans.app.security_agent.set_all_library_permissions( library_item.library_item_info, permissions ) - library_item.library_item_info.refresh() - library_item.refresh() - msg = "Permissions updated for field '%s'" % library_item.library_item_info_template_element.name - return trans.response.send_redirect( web.url_for( controller='admin', - action='library_item_info', - library_id=library_id, - id=id, - library_item_id=library_item_id, - library_item_type=library_item_type, - permissions=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - return trans.fill_template( '/admin/library/info_permissions.mako', - library_item_info_element=library_item, - library_id=library_id, - msg=msg, - messagetype=messagetype ) + # Save updated template field contents + field_contents = [] + for index in range( int( num_widgets ) ): + field_contents.append( util.restore_text( params.get( 'field_%i' % ( index ), '' ) ) ) + if field_contents: + # Since information templates are inherited, the template fields can be displayed on the information + # page for a folder or library dataset when it has no info_association object. If the user has added + # field contents on an inherited template via a parent's info_association, we'll need to create a new + # form_values and info_association for the current object. + info_association = library_item.get_info_association( restrict=True ) + if info_association: + template = info_association.template + info = info_association.info + form_values = trans.app.model.FormValues.get( info.id ) + # Update existing content only if it has changed + if form_values.content != field_contents: + form_values.content = field_contents + form_values.flush() + else: + # Inherit the next available info_association so we can get the template + info_association = library_item.get_info_association() + template = info_association.template + # Create a new FormValues object + form_values = trans.app.model.FormValues( template, field_contents ) + form_values.flush() + # Create a new info_association between the current library item and form_values + if library_item_type == 'folder': + info_association = trans.app.model.LibraryFolderInfoAssociation( library_item, template, form_values ) + info_association.flush() + elif library_item_type == 'library_dataset_dataset_association': + info_association = trans.app.model.LibraryDatasetDatasetInfoAssociation( library_item, template, form_values ) + info_association.flush() + msg = 'The information has been updated.' + return trans.response.send_redirect( web.url_for( controller='admin', + action=library_item_type, + id=library_item.id, + library_id=library_id, + folder_id=folder_id, + edit_info=True, + msg=util.sanitize_text( msg ), + messagetype='done' ) ) @web.expose @web.require_admin def download_dataset_from_folder(self, trans, id, library_id=None, **kwd): @@ -2101,19 +1952,6 @@ else: last_updated[job.id] = '%s minutes' % int( delta.seconds / 60 ) return trans.fill_template( '/admin/jobs.mako', jobs = jobs, last_updated = last_updated, cutoff = cutoff, msg = msg, messagetype = messagetype ) - - def _get_all_forms(self, trans, all_versions=False): - ''' - This method returns all the latest forms from the - form_definition_current table if all_versions is set to True. Otherwise - this method return all the versions of all the forms from form_definition - table - ''' - if all_versions: - return trans.app.model.FormDefinition.query().all() - else: - fdc_list = trans.app.model.FormDefinitionCurrent.query().all() - return [fdc.latest_form for fdc in fdc_list] @web.expose @web.require_admin def manage_request_types( self, trans, **kwd ): @@ -2121,7 +1959,7 @@ msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) show_filter = util.restore_text( params.get( 'show_filter', 'Active' ) ) - forms = self._get_all_forms(trans, all_versions=True) + forms = get_all_forms(trans, all_versions=True) request_types_list = trans.app.model.RequestType.query().all() if show_filter == 'All': request_types = request_types_list @@ -2141,37 +1979,38 @@ params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - if params.get('create', False) == 'True': + if params.get( 'create', False ): return trans.fill_template( '/admin/requests/create_request_type.mako', - forms=self._get_all_forms(trans, all_versions=False), + forms=get_all_forms( trans, + filter=dict(deleted=False) ), msg=msg, messagetype=messagetype) - elif params.get('add_states', False) == 'True': + elif params.get( 'define_states_button', False ): return trans.fill_template( '/admin/requests/add_states.mako', - sample_type_name=util.restore_text( params.name ), + request_type_name=util.restore_text( params.name ), desc=util.restore_text( params.description ), num_states=int(util.restore_text( params.num_states )), request_form_id=int(util.restore_text( params.request_form_id )), sample_form_id=int(util.restore_text( params.sample_form_id )), msg=msg, messagetype=messagetype) - elif params.get('save_new', False) == 'True': + elif params.get( 'save_request_type', False ): st, msg = self._save_request_type(trans, **kwd) if not st: return trans.fill_template( '/admin/requests/create_request_type.mako', - forms=self._get_all_forms(trans, all_versions=False), + forms=get_all_forms( trans ), msg=msg, messagetype='error') return trans.response.send_redirect( web.url_for( controller='admin', action='manage_request_types', msg='Request type <b>%s</b> has been created' % st.name, messagetype='done') ) - elif params.get('edit', False) == 'True': + elif params.get('view', False): rt = trans.app.model.RequestType.get(int(util.restore_text( params.id ))) ss_list = trans.app.model.SampleState.filter(trans.app.model.SampleState.table.c.request_type_id == rt.id).all() return trans.fill_template( '/admin/requests/view_request_type.mako', request_type=rt, - forms=self._get_all_forms(trans, all_versions=False), + forms=get_all_forms( trans ), states_list=ss_list, deleted=False, show_deleted=False, @@ -2200,9 +2039,6 @@ for ss in ss_list: ss.delete() ss.flush() - # unsubmitted state - #ss = trans.app.model.SampleState('Unsubmitted', 'Sample not yet submitted', rt) - ##ss.flush() for i in range( num_states ): name = util.restore_text( params.get( 'new_element_name_%i' % i, None )) desc = util.restore_text( params.get( 'new_element_description_%i' % i, None )) @@ -2236,5 +2072,5 @@ rt.flush() return trans.response.send_redirect( web.url_for( controller='admin', action='manage_request_types', - msg='Request type <b>%s</b> has been deleted' % rt.name, + msg='Request type <b>%s</b> has been undeleted' % rt.name, messagetype='done') ) diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/web/controllers/forms.py --- a/lib/galaxy/web/controllers/forms.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/web/controllers/forms.py Thu Aug 13 13:44:04 2009 -0400 @@ -10,7 +10,6 @@ import copy log = logging.getLogger( __name__ ) - class Forms( BaseController ): @web.expose @@ -44,45 +43,30 @@ show_filter=show_filter, msg=msg, messagetype=messagetype ) - def _get_all_forms(self, trans, all_versions=False): - ''' - This method returns all the latest forms from the - form_definition_current table if all_versions is set to True. Otherwise - this method return all the versions of all the forms from form_definition - table - ''' - if all_versions: - return trans.app.model.FormDefinition.query().all() - else: - fdc_list = trans.app.model.FormDefinitionCurrent.query().all() - return [fdc.latest_form for fdc in fdc_list] @web.expose @web.require_admin def new( self, trans, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) - messagetype = params.get( 'messagetype', 'done' ) - if params.get('new', False) and not params.get('create_form', False): - self.current_form = {} - self.current_form['name'] = 'New Form' - self.current_form['desc'] = '' - self.current_form['fields'] = [] - inputs = [ ( 'Name', TextField('name', 40,self.current_form['name'] ) ), - ( 'Description', TextField('description', 40, self.current_form['desc']) ), - ( 'Import from csv file (Optional)', TextField('csv_file', 40, '') ) ] - return trans.fill_template( '/admin/forms/create_form.mako', - inputs=inputs, - msg=msg, - messagetype=messagetype ) - elif params.get('create_form', False) == 'True': - if 'submitted' in params.new: - self.num_add_fields = 0 - fd, msg = self.__save_form(trans, fdc_id=None, **kwd) - self.__get_saved_form(fd) - return trans.response.send_redirect( web.url_for( controller='forms', - action='edit', - form_id=fd.id, - show_form=True) ) + messagetype = params.get( 'messagetype', 'done' ) + if params.get( 'create_form_button', False ): + fd, msg = self.__save_form( trans, fdc_id=None, **kwd ) + self.__get_saved_form( fd ) + return trans.response.send_redirect( web.url_for( controller='forms', + action='edit', + form_id=fd.id, + show_form=True ) ) + self.current_form = {} + self.current_form[ 'name' ] = 'New Form' + self.current_form[ 'desc' ] = '' + self.current_form[ 'fields' ] = [] + inputs = [ ( 'Name', TextField( 'name', 40, self.current_form[ 'name' ] ) ), + ( 'Description', TextField( 'description', 40, self.current_form[ 'desc' ] ) ), + ( 'Import from csv file (Optional)', FileField( 'file_data', 40, '' ) ) ] + return trans.fill_template( '/admin/forms/create_form.mako', + inputs=inputs, + msg=msg, + messagetype=messagetype ) @web.expose @web.require_admin def delete( self, trans, **kwd ): @@ -111,73 +95,75 @@ @web.require_admin def edit( self, trans, **kwd ): ''' - This callback method is for handling all the editing functions like: - remaning fields, adding/deleting fields, changing fields attributes + This callback method is for handling all the editing functions like + renaming fields, adding/deleting fields, changing fields attributes. ''' params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - fd = trans.app.model.FormDefinition.get(int(util.restore_text( params.form_id ))) - # SHOW THE FORM FOR EDITING. - if params.get('show_form', False) == 'True': - self.__get_saved_form(fd) - # the following two dicts store the unsaved select box options + form_id = params.get( 'form_id', None ) + if not form_id: + msg = 'Invalid form id %s' % str( form_id ) + trans.response.send_redirect( web.url_for( controller='forms', + action='manage', + msg=msg, + messagetype='error' ) ) + fd = trans.app.model.FormDefinition.get( int( params.form_id ) ) + # Show the form for editing + if params.get( 'show_form', False ): + self.__get_saved_form( fd ) + # The following two dicts store the unsaved select box options self.del_options = {} self.add_options = {} - return self.__show(trans=trans, form=fd, msg=msg, - messagetype=messagetype, **kwd) - # DELETE FIELD - elif params.get('remove_button', False): - self.__update_current_form(**kwd) - index = int(params.get('remove_button', None).split(' ')[2])-1 - self.__remove_field(index) - return self.__show(trans=trans, form=fd, msg=msg, - messagetype=messagetype, **kwd) - # SAVE CHANGES - elif params.get('save_changes_button', False) == 'Save': - self.__update_current_form(**kwd) - fd_new, msg = self.__save_form(trans, fd.form_definition_current.id, **kwd) + if fd.fields: + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, **kwd ) + else: + # If the form is empty, we'll simulate a click on the add_field_button so the + # form will be displayed with the field choice, saving a mouse click. + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, empty_form=True, **kwd ) + # Delete a field + elif params.get( 'remove_button', False ): + self.__update_current_form( trans, **kwd ) + index = int( kwd[ 'remove_button' ].split( ' ' )[2] ) - 1 + self.__remove_field( index ) + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, **kwd ) + # Save changes + elif params.get( 'save_changes_button', False ): + self.__update_current_form( trans, **kwd ) + fd_new, msg = self.__save_form( trans, fd.form_definition_current.id, **kwd ) if not fd_new: - return self.__show(trans=trans, form=fd, msg=msg, - messagetype='error', **kwd) + return self.__show( trans=trans, form=fd, msg=msg, messagetype='error', **kwd ) else: fd = fd_new msg = "The form '%s' has been updated with the changes." % fd.name - return self.__show(trans=trans, form=fd, msg=msg, - messagetype=messagetype, **kwd) - #ADD A FIELD - elif params.get('add_field_button', False) == 'Add field': - self.__update_current_form(**kwd) + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, **kwd ) + #Add a field + elif params.get( 'add_field_button', False ): + self.__update_current_form( trans, **kwd ) self.__add_field() # show the form again with one empty field - return self.__show(trans=trans, form=fd, msg=msg, - messagetype=messagetype, **kwd) - # SHOW FORM READ ONLY - elif params.get('read_only', False): + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, **kwd ) + # Show form read-only + elif params.get( 'read_only', False ): return trans.fill_template( '/admin/forms/show_form_read_only.mako', form=fd, msg=msg, messagetype=messagetype ) - # REFRESH PAGE, SelectField is selected/deselected as the type of a field - elif params.get('refresh', False) == 'true': - self.__update_current_form(**kwd) - return self.__show(trans=trans, form=fd, msg=msg, - messagetype=messagetype, **kwd) - # REMOVE SelectField OPTION - elif params.get('select_box_options', False) == 'remove': - #self.__update_current_form(**kwd) - index = int(params.get( 'field_index', None )) - option = int(params.get( 'option_index', None )) - del self.current_form['fields'][index]['selectlist'][option] - return self.__show(trans=trans, form=fd, msg=msg, - messagetype=messagetype, **kwd) - # ADD SelectField OPTION - elif params.get('select_box_options', False) == 'add': - #self.__update_current_form(**kwd) - index = int(params.get( 'field_index', None )) - self.current_form['fields'][index]['selectlist'].append('') - return self.__show(trans=trans, form=fd, msg=msg, - messagetype=messagetype, **kwd) + # Refresh page, SelectField is selected/deselected as the type of a field + elif params.get( 'refresh', False ): + self.__update_current_form( trans, **kwd ) + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, **kwd ) + # Remove SelectField option + elif params.get( 'select_box_options', False ) == 'remove': + index = int( kwd[ 'field_index' ] ) + option = int( kwd[ 'option_index' ] ) + del self.current_form[ 'fields' ][ index ][ 'selectlist' ][ option ] + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, **kwd ) + # Add SelectField option + elif params.get( 'select_box_options', False ) == 'add': + index = int( kwd[ 'field_index' ] ) + self.current_form[ 'fields' ][ index ][ 'selectlist' ].append( '' ) + return self.__show( trans=trans, form=fd, msg=msg, messagetype=messagetype, **kwd ) def __remove_field(self, index): del self.current_form['fields'][index] def __add_field(self): @@ -193,6 +179,10 @@ self.current_form['fields'].append(empty_field) def __get_field(self, index, **kwd): params = util.Params( kwd ) + #TODO: RC this needs to be handled so that it does not throw an exception. + # To reproduce, create a new form, click the "add field" button, click the + # browser back arrow, then click the "add field" button again. + # You should never attempt to "restore_text()" on a None object... name = util.restore_text( params.get( 'field_name_%i' % index, None ) ) helptext = util.restore_text( params.get( 'field_helptext_%i' % index, None ) ) required = params.get( 'field_required_%i' % index, False ) @@ -245,29 +235,28 @@ if not util.restore_text(params.get( 'field_name_%i' % i, None )): return None, "All the field label(s) must be completed." return True, '' - def __get_form(self, **kwd): + def __get_form(self, trans, **kwd): params = util.Params( kwd ) name = util.restore_text( params.name ) desc = util.restore_text( params.description ) or "" - if params.get( 'csv_file', None ): - csv_file = util.restore_text( params.get( 'csv_file', '' ) ) - if csv_file: - fields = self.__import_fields(csv_file) - else: + csv_file = params.get( 'file_data', '' ) + if csv_file == '': # set form fields fields = [] for i in range( len(self.current_form['fields']) ): fields.append(self.__get_field(i, **kwd)) fields = fields + else: + fields = self.__import_fields(trans, csv_file) return name, desc, fields - def __update_current_form(self, **kwd): - name, desc, fields = self.__get_form(**kwd) + def __update_current_form(self, trans, **kwd): + name, desc, fields = self.__get_form(trans, **kwd) self.current_form = {} self.current_form['name'] = name self.current_form['desc'] = desc self.current_form['fields'] = fields - def __import_fields(self, csv_file): + def __import_fields(self, trans, csv_file): ''' "company","name of the company", "True", "required", "TextField",, "due date","turnaround time", "True", "optional", "SelectField","24 hours, 1 week, 1 month" @@ -275,7 +264,7 @@ import csv fields = [] try: - reader = csv.reader(open(csv_file)) + reader = csv.reader(csv_file.file) for row in reader: options = row[5].split(',') fields.append({'label': row[0], @@ -301,7 +290,7 @@ if not flag: return None, msg fd = trans.app.model.FormDefinition() - fd.name, fd.desc, fd.fields = self.__get_form(**kwd) + fd.name, fd.desc, fd.fields = self.__get_form(trans, **kwd) if fdc_id: # save changes to the existing form # change the pointer in the form_definition_current table to point # to this new record @@ -314,9 +303,6 @@ trans.sa_session.save_or_update( fdc ) trans.sa_session.flush() msg = "The new form named '%s' has been created. " % (fd.name) - request_types = trans.app.model.RequestType.query().all() - if not request_types: - msg = msg + "Now you can create requests to associate with this form." return fd, msg class FieldUI(object): @@ -381,18 +367,31 @@ def label(self): return str(self.index)+'.'+self.label - def __show(self, trans, form, msg=None, messagetype='done', **kwd): + def __show( self, trans, form, msg='', messagetype='done', empty_form=False, **kwd ): ''' - This method displays the form and any of the changes made to it + This method displays the form and any of the changes made to it, + The empty_form param allows for this method to simulate clicking + the "add_field_button" on the edit_form.mako page so that the page + is displayed with the first field to be added, saving a mouse click. ''' + if empty_form: + # Send params that will simulate a button click on the add_field_button + # button on edit_form.mako. + param_dict = { 'form_id' : str( form.id ), + 'num_fields' : '0', + 'refresh' : 'true', + 'name' : form.name, + 'description' : form.desc, + 'add_field_button' : 'Add field' } + self.edit( trans, **param_dict ) params = util.Params( kwd ) # name & description - form_details = [ ( 'Name', TextField('name', 40, self.current_form['name']) ), - ( 'Description', TextField('description', 40, self.current_form['desc']) ) ] + form_details = [ ( 'Name', TextField( 'name', 40, self.current_form[ 'name' ] ) ), + ( 'Description', TextField( 'description', 40, self.current_form[ 'desc' ] ) ) ] # fields field_details = [] - for index, field in enumerate(self.current_form['fields']): - field_ui = self.FieldUI(index, field) + for index, field in enumerate( self.current_form[ 'fields' ] ): + field_ui = self.FieldUI( index, field ) field_details.append( field_ui.get() ) return trans.fill_template( '/admin/forms/edit_form.mako', form_details=form_details, @@ -401,3 +400,61 @@ field_types=BaseField.form_field_types(), msg=msg, messagetype=messagetype ) + +# Common methods for all components that use forms +def get_all_forms( trans, all_versions=False, filter=None ): + ''' + Return all the latest forms from the form_definition_current table + if all_versions is set to True. Otherwise return all the versions + of all the forms from the form_definition table. + + TODO: when we add the concept of a form_definition_type ( e.g., + 'request_header', 'request_sample', 'library_template' ), filter + the query if received filter is not None. + ''' + if all_versions: + return trans.app.model.FormDefinition.query().all() + if filter: + fdc_list = trans.app.model.FormDefinitionCurrent.query().filter_by(**filter) + else: + fdc_list = trans.app.model.FormDefinitionCurrent.query().all() + return [ fdc.latest_form for fdc in fdc_list ] +def get_form_widgets( trans, form, contents={} ): + ''' + Return the list of widgets that comprise a form definition, + including field contents if any. + ''' + widgets = [] + for index, field in enumerate( form.fields ): + field_name = 'field_%i' % index + if field_name in contents: + value = contents[ field_name ] + elif field[ 'type' ] == 'CheckboxField': + # Since we do not have contents, set checkbox value to False + value = False + else: + # Set other field types to empty string + value = '' + field_widget = eval( field[ 'type' ] )( field_name ) + if field[ 'type' ] == 'TextField': + field_widget.set_size( 40 ) + field_widget.value = value + elif field[ 'type' ] == 'TextArea': + field_widget.set_size( 3, 40 ) + field_widget.value = value + elif field[ 'type' ] == 'SelectField': + for option in field[ 'selectlist' ]: + if option == value: + field_widget.add_option( option, option, selected=True ) + else: + field_widget.add_option( option, option ) + elif field[ 'type' ] == 'CheckboxField': + field_widget.checked = value + if field[ 'required' ] == 'required': + req = 'Required' + else: + req = 'Optional' + widgets.append( dict( label=field[ 'label' ], + widget=field_widget, + helptext='%s (%s)' % ( field[ 'helptext' ], req ) ) ) + return widgets diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/web/controllers/history.py Thu Aug 13 13:44:04 2009 -0400 @@ -12,7 +12,6 @@ # States for passing messages SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error" - class HistoryListGrid( grids.Grid ): # Custom column types @@ -70,8 +69,43 @@ def apply_default_filter( self, trans, query ): return query.filter_by( user=trans.user, purged=False ) +class SharedHistoryListGrid( grids.Grid ): + # Custom column types + class DatasetsByStateColumn( grids.GridColumn ): + def get_value( self, trans, grid, history ): + rval = [] + for state in ( 'ok', 'running', 'queued', 'error' ): + total = sum( 1 for d in history.active_datasets if d.state == state ) + if total: + rval.append( '<div class="count-box state-color-%s">%s</div>' % ( state, total ) ) + else: + rval.append( '' ) + return rval + class SharedByColumn( grids.GridColumn ): + def get_value( self, trans, grid, history ): + return history.user.email + # Grid definition + title = "Histories shared with you by others" + model_class = model.History + default_sort_key = "-update_time" + columns = [ + grids.GridColumn( "Name", key="name" ), + DatasetsByStateColumn( "Datasets (by state)", ncells=4 ), + grids.GridColumn( "Created", key="create_time", format=time_ago ), + grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), + SharedByColumn( "Shared by", key="user_id" ) + ] + operations = [ + grids.GridOperation( "Clone" ), + grids.GridOperation( "Unshare" ) + ] + standard_filters = [] + def build_initial_query( self, session ): + return session.query( self.model_class ).join( 'users_shared_with' ) + def apply_default_filter( self, trans, query ): + return query.filter( model.HistoryUserShareAssociation.user == trans.user ) + class HistoryController( BaseController ): - @web.expose def index( self, trans ): return "" @@ -80,7 +114,8 @@ """XML history list for functional tests""" return trans.fill_template( "/history/list_as_xml.mako" ) - list_grid = HistoryListGrid() + stored_list_grid = HistoryListGrid() + shared_list_grid = SharedHistoryListGrid() @web.expose @web.require_login( "work with multiple histories" ) @@ -91,7 +126,6 @@ if 'operation' in kwargs: history_ids = util.listify( kwargs.get( 'id', [] ) ) histories = [] - shared_by_others = [] operation = kwargs['operation'].lower() if operation == "share": return self.share( trans, **kwargs ) @@ -127,7 +161,7 @@ status, message = self._list_undelete( trans, histories ) trans.sa_session.flush() # Render the list view - return self.list_grid( trans, status=status, message=message, template='/history/grid.mako', **kwargs ) + return self.stored_list_grid( trans, status=status, message=message, template='/history/stored_grid.mako', **kwargs ) def _list_delete( self, trans, histories ): """Delete histories""" n_deleted = 0 @@ -195,18 +229,38 @@ # No message return None, None @web.expose - def list_shared( self, trans, **kwd ): + def list_shared( self, trans, **kwargs ): """List histories shared with current user by others""" - params = util.Params( kwd ) - msg = util.restore_text( params.get( 'msg', '' ) ) - shared_by_others = trans.sa_session \ - .query( model.HistoryUserShareAssociation ) \ - .filter_by( user=trans.user ) \ - .join( 'history' ) \ - .filter( model.History.deleted == False ) \ - .order_by( desc( model.History.update_time ) ) \ - .all() - return trans.fill_template( "/history/list_shared.mako", shared_by_others=shared_by_others, msg=msg, messagetype='done' ) + msg = util.restore_text( kwargs.get( 'msg', '' ) ) + status = message = None + if 'operation' in kwargs: + id = kwargs.get( 'id', None ) + operation = kwargs['operation'].lower() + if operation == "clone": + if not id: + message = "Select a history to clone" + return self.shared_list_grid( trans, status='error', message=message, template='/history/shared_grid.mako', **kwargs ) + # When cloning shared histories, only copy active datasets + new_kwargs = { 'clone_choice' : 'active' } + return self.clone( trans, id, **new_kwargs ) + elif operation == 'unshare': + if not id: + message = "Select a history to unshare" + return self.shared_list_grid( trans, status='error', message=message, template='/history/shared_grid.mako', **kwargs ) + ids = util.listify( id ) + histories = [] + for history_id in ids: + history = get_history( trans, history_id, check_ownership=False ) + histories.append( history ) + for history in histories: + # Current user is the user with which the histories were shared + association = trans.app.model.HistoryUserShareAssociation.filter_by( user=trans.user, history=history ).one() + association.delete() + association.flush() + message = "Unshared %d shared histories" % len( ids ) + status = 'done' + # Render the list view + return self.shared_list_grid( trans, status=status, message=message, template='/history/shared_grid.mako', **kwargs ) @web.expose def delete_current( self, trans ): """Delete just the active history -- this does not require a logged in user.""" @@ -323,6 +377,9 @@ can_change, cannot_change, no_change_needed, unique_no_change_needed, send_to_err = \ self._populate_restricted( trans, user, histories, send_to_users, None, send_to_err, unique=True ) send_to_err += err_msg + if cannot_change and not no_change_needed and not can_change: + send_to_err = "The histories you are sharing do not contain any datasets that can be accessed by the users with which you are sharing." + return trans.fill_template( "/history/share.mako", histories=histories, email=email, send_to_err=send_to_err ) if can_change or cannot_change: return trans.fill_template( "/history/share.mako", histories=histories, @@ -350,8 +407,6 @@ email=email, err_msg=err_msg, share_button=True ) ) - if action == "no_share": - trans.response.send_redirect( url_for( controller='root', action='history_options' ) ) user = trans.get_user() histories, send_to_users, send_to_err = self._get_histories_and_users( trans, user, id, email ) send_to_err = '' @@ -629,29 +684,38 @@ @web.expose @web.require_login( "clone shared Galaxy history" ) def clone( self, trans, id, **kwd ): - history = get_history( trans, id, check_ownership=False ) + """Clone a list of histories""" params = util.Params( kwd ) + ids = util.listify( id ) + histories = [] + for history_id in ids: + history = get_history( trans, history_id, check_ownership=False ) + histories.append( history ) clone_choice = params.get( 'clone_choice', None ) if not clone_choice: return trans.fill_template( "/history/clone.mako", history=history ) user = trans.get_user() - if history.user == user: - owner = True + for history in histories: + if history.user == user: + owner = True + else: + if trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ) \ + .filter_by( user=user, history=history ).count() == 0: + return trans.show_error_message( "The history you are attempting to clone is not owned by you or shared with you. " ) + owner = False + name = "Clone of '%s'" % history.name + if not owner: + name += " shared by '%s'" % history.user.email + if clone_choice == 'activatable': + new_history = history.copy( name=name, target_user=user, activatable=True ) + elif clone_choice == 'active': + name += " (active items only)" + new_history = history.copy( name=name, target_user=user ) + if len( histories ) == 1: + msg = 'Clone with name "%s" is now included in your previously stored histories.' % new_history.name else: - if trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ) \ - .filter_by( user=user, history=history ).count() == 0: - return trans.show_error_message( "The history you are attempting to clone is not owned by you or shared with you. " ) - owner = False - name = "Clone of '%s'" % history.name - if not owner: - name += " shared by '%s'" % history.user.email - if clone_choice == 'activatable': - new_history = history.copy( name=name, target_user=user, activatable=True ) - elif clone_choice == 'active': - name += " (active items only)" - new_history = history.copy( name=name, target_user=user ) - # Render the list view - return trans.show_ok_message( 'Clone with name "%s" is now included in your list of stored histories.' % new_history.name ) + msg = '%d cloned histories are now included in your previously stored histories.' % len( histories ) + return trans.show_ok_message( msg ) ## ---- Utility methods ------------------------------------------------------- diff -r f1f2d1de5f3e -r 5b6146705e80 lib/galaxy/web/controllers/library.py --- a/lib/galaxy/web/controllers/library.py Thu Aug 13 13:43:25 2009 -0400 +++ b/lib/galaxy/web/controllers/library.py Thu Aug 13 13:44:04 2009 -0400 @@ -2,6 +2,7 @@ from galaxy.model.orm import * from galaxy.datatypes import sniff from galaxy import util +from galaxy.web.controllers.forms import get_all_forms, get_form_widgets from galaxy.util.streamball import StreamBall import logging, tempfile, zipfile, tarfile, os, sys @@ -130,6 +131,21 @@ msg=util.sanitize_text( msg ), messagetype='error' ) ) if action == 'information': + # See if we have any associated templates + if library.info_association: + template = library.info_association[0].template + # See if we have any field contents + info = library.info_association[0].info + if info: + field_contents = {} + for index, value in enumerate( info.content ): + key = 'field_%i' % index + field_contents[ key ] = value + widgets = get_form_widgets( trans, template, field_contents ) + else: + widgets = get_form_widgets( trans, template ) + else: + widgets = [] if params.get( 'rename_library_button', False ): old_name = library.name new_name = util.restore_text( params.name ) @@ -138,8 +154,7 @@ msg = 'Enter a valid name' return trans.fill_template( '/library/library_info.mako', library=library, - restrict=params.get( 'restrict', False ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype='error' ) else: @@ -159,8 +174,7 @@ messagetype='done' ) ) return trans.fill_template( '/library/library_info.mako', library=library, - restrict=params.get( 'restrict', False ), - render_templates=params.get( 'render_templates', False ), + widgets=widgets, msg=msg, messagetype=messagetype ) elif action == 'permissions': @@ -377,8 +391,6 @@ return trans.fill_template( '/library/library_dataset_info.mako', library_dataset=library_dataset, library_id=library_id, - restrict=params.get( 'restrict', True ),
participants (1)
-
Greg Von Kuster