details: http://www.bx.psu.edu/hg/galaxy/rev/c69e55c91036 changeset: 2445:c69e55c91036 user: Greg Von Kuster <greg@bx.psu.edu> date: Thu Jun 11 12:06:29 2009 -0400 description: Restrict the target history list to the users active hisstories when copying datasets between histories, clean up the relavent templates ( fixes ticket # 41 ), and add functional tests for copying history items between histories. 5 file(s) affected in this change: lib/galaxy/web/controllers/dataset.py templates/dataset/copy_view.mako templates/dataset/edit_attributes.mako test/base/twilltestcase.py test/functional/test_history_functions.py diffs (369 lines): diff -r 004cd81cff72 -r c69e55c91036 lib/galaxy/web/controllers/dataset.py --- a/lib/galaxy/web/controllers/dataset.py Wed Jun 10 15:46:26 2009 -0400 +++ b/lib/galaxy/web/controllers/dataset.py Thu Jun 11 12:06:29 2009 -0400 @@ -159,7 +159,8 @@ raise "Error undeleting" @web.expose - def copy_datasets( self, trans, source_dataset_ids = "", target_history_ids = "", new_history_name="", do_copy = False ): + def copy_datasets( self, trans, source_dataset_ids="", target_history_ids="", new_history_name="", do_copy=False, **kwd ): + params = util.Params( kwd ) user = trans.get_user() history = trans.get_history() create_new_history = False @@ -202,7 +203,7 @@ error_msg = error_msg + "You do not have permission to add datasets to %i requested histories. " % ( len( target_history_ids ) - len( target_histories ) ) for data in map( trans.app.model.HistoryDatasetAssociation.get, source_dataset_ids ): if data is None: - error_msg = error_msg + "You tried to copy a non-existant dataset. " + error_msg = error_msg + "You tried to copy a dataset that does not exist. " invalid_datasets += 1 elif data.history != history: error_msg = error_msg + "You tried to copy a dataset which is not in your current history. " @@ -220,8 +221,7 @@ source_datasets = history.active_datasets target_histories = [history] if user: - target_histories = user.histories - + target_histories = user.active_histories return trans.fill_template( "/dataset/copy_view.mako", source_dataset_ids = source_dataset_ids, target_history_ids = target_history_ids, diff -r 004cd81cff72 -r c69e55c91036 templates/dataset/copy_view.mako --- a/templates/dataset/copy_view.mako Wed Jun 10 15:46:26 2009 -0400 +++ b/templates/dataset/copy_view.mako Thu Jun 11 12:06:29 2009 -0400 @@ -5,65 +5,67 @@ ${javascripts()} %if error_msg: -<p> -<div class="errormessage">${error_msg}</div> -<div style="clear: both"></div> -</p> + <p> + <div class="errormessage">${error_msg}</div> + <div style="clear: both"></div> + </p> %endif %if done_msg: -<p> -<div class="donemessage">${done_msg}</div> -<div style="clear: both"></div> -</p> + <p> + <div class="donemessage">${done_msg}</div> + <div style="clear: both"></div> + </p> %endif <p> -<div class="toolForm"> - <form> - <div style="float: left; width: 50%; padding: 0px 0px 0px 0px;"> - <div class="toolFormTitle">Source History Items</div> - <div class="toolFormBody"> - %for data in source_datasets: - <% - checked = "" - if data.id in source_dataset_ids: - checked = " checked" - %> - <div class="form-row"><input type="checkbox" name="source_dataset_ids" value="${data.id}"${checked}/> ${data.hid}: ${data.name}</div> - %endfor - </div> - </div> - <div style="float: right; width: 50%; padding: 0px 0px 0px 0px;"> - <div class="toolFormTitle">Target Histories</div> - <div class="toolFormBody"> - %for i, hist in enumerate( target_histories ): - <% - checked = "" - if hist.id in target_history_ids: - checked = " checked" - cur_history_text = "" - if hist == trans.get_history(): - cur_history_text = " <strong>(current history)</strong>" - %> - <div class="form-row"><input type="checkbox" name="target_history_ids" value="${hist.id}"${checked}/> ${i + 1}${cur_history_text}: ${hist.name}</div> - %endfor - %if trans.get_user(): - <% - checked = "" - if "create_new_history" in target_history_ids: - checked = " checked" - %> - <br> - <div class="form-row"><input type="checkbox" name="target_history_ids" value="create_new_history"${checked}/>New history named: <input type="textbox" name="new_history_name" value="${new_history_name}"/></div> - %endif - </div> - </div> - <div style="clear: both"></div> - <div class="form-row" align="center"><input type="submit" class="primary-button" name="do_copy" value="Copy History Items"/></div> - </form> -</div> + <div class="toolForm"> + <form> + <div style="float: left; width: 50%; padding: 0px 0px 0px 0px;"> + <div class="toolFormTitle">Source History Items</div> + <div class="toolFormBody"> + %for data in source_datasets: + <% + checked = "" + if data.id in source_dataset_ids: + checked = " checked" + %> + <div class="form-row"><input type="checkbox" name="source_dataset_ids" value="${data.id}"${checked}/> ${data.hid}: ${data.name}</div> + %endfor + </div> + </div> + <div style="float: right; width: 50%; padding: 0px 0px 0px 0px;"> + <div class="toolFormTitle">Target Histories</div> + <div class="toolFormBody"> + %for i, hist in enumerate( target_histories ): + <% + checked = "" + if hist.id in target_history_ids: + checked = " checked" + cur_history_text = "" + if hist == trans.get_history(): + cur_history_text = " <strong>(current history)</strong>" + %> + <div class="form-row"><input type="checkbox" name="target_history_ids" value="${hist.id}"${checked}/> ${i + 1}${cur_history_text}: ${hist.name}</div> + %endfor + %if trans.get_user(): + <% + checked = "" + if "create_new_history" in target_history_ids: + checked = " checked" + %> + <br/> + <div class="form-row"><input type="checkbox" name="target_history_ids" value="create_new_history"${checked}/>New history named: <input type="textbox" name="new_history_name" value="${new_history_name}"/></div> + %endif + </div> + </div> + <div style="clear: both"></div> + <div class="form-row" align="center"> + <input type="submit" class="primary-button" name="do_copy" value="Copy History Items"/> + </div> + </form> + </div> </p> <div style="clear: both"></div> <p> -<div class="infomessage">Select any number of source history items and any number of target histories and click on "Copy History Items" to add a copy of each selected dataset to each selected history.</div> -<div style="clear: both"></div> + <div class="infomessage">Select any number of source history items and any number of target histories and click "Copy History Items" to add a copy of each selected history item to each selected target history.</div> + <div style="clear: both"></div> </p> diff -r 004cd81cff72 -r c69e55c91036 templates/dataset/edit_attributes.mako --- a/templates/dataset/edit_attributes.mako Wed Jun 10 15:46:26 2009 -0400 +++ b/templates/dataset/edit_attributes.mako Thu Jun 11 12:06:29 2009 -0400 @@ -157,8 +157,16 @@ %endif <p/> <div class="toolForm"> -<div class="toolFormTitle">Copy History Item</div> -<div class="toolFormBody"> - Click <a href="${h.url_for( controller='dataset', action='copy_datasets', source_dataset_ids=data.id, target_history_ids=data.history_id )}" target="galaxy_main">here</a> to make a copy of this history item. + <div class="toolFormTitle">Copy History Item</div> + <div class="toolFormBody"> + <form name="copy_hda" action="${h.url_for( controller='dataset', action='copy_datasets', source_dataset_ids=data.id, target_history_ids=data.history_id )}" method="post"> + <div class="form-row"> + <input type="submit" name="change" value="Copy history item"/> + </div> + <div class="toolParamHelp" style="clear: both;"> + Make a copy of this history item in your current history or any of your active histories. + </div> + </form> + </div> + </div> </div> -</div> diff -r 004cd81cff72 -r c69e55c91036 test/base/twilltestcase.py --- a/test/base/twilltestcase.py Wed Jun 10 15:46:26 2009 -0400 +++ b/test/base/twilltestcase.py Thu Jun 11 12:06:29 2009 -0400 @@ -181,8 +181,9 @@ self.home() def new_history( self, name=None ): """Creates a new, empty history""" + self.home() if name: - self.visit_url( "%s/history_new?name=%s" % ( self.url, str( name ) ) ) + self.visit_url( "%s/history_new?name=%s" % ( self.url, name ) ) else: self.visit_url( "%s/history_new" % self.url ) self.check_history_for_string('Your history is empty') @@ -191,7 +192,7 @@ """Rename an existing history""" self.home() self.visit_page( "history/rename?id=%s&name=%s" %( id, new_name ) ) - check_str = 'History: %s renamed to: %s' % ( old_name, new_name ) + check_str = 'History: %s renamed to: %s' % ( old_name, urllib.unquote( new_name ) ) self.check_page_for_string( check_str ) self.home() def set_history( self ): @@ -330,7 +331,7 @@ self.check_page_for_string( 'Attributes updated' ) self.home() def convert_format( self, hda_id, target_type ): - """Auto-detect history_dataset_association metadata""" + """Convert format of history_dataset_association""" self.home() self.visit_url( "%s/root/edit?id=%s" % ( self.url, hda_id ) ) self.check_page_for_string( 'This will inspect the dataset and attempt' ) @@ -339,13 +340,36 @@ self.check_page_for_string( 'The file conversion of Convert BED to GFF on data' ) self.home() def change_datatype( self, hda_id, datatype ): - """Auto-detect history_dataset_association metadata""" + """Change format of history_dataset_association""" self.home() self.visit_url( "%s/root/edit?id=%s" % ( self.url, hda_id ) ) self.check_page_for_string( 'This will change the datatype of the existing dataset but' ) tc.fv( 'change_datatype', 'datatype', datatype ) tc.submit( 'change' ) self.check_page_for_string( 'Edit Attributes' ) + self.home() + def copy_history_item( self, source_dataset_ids='', target_history_ids=[], all_target_history_ids=[], deleted_history_ids=[] ): + """Copy 1 or more history_dataset_associations to 1 or more histories""" + self.home() + self.visit_url( "%s/dataset/copy_datasets?source_dataset_ids=%s" % ( self.url, source_dataset_ids ) ) + self.check_page_for_string( 'Source History Items' ) + # Make sure all of users active histories are displayed + for id in all_target_history_ids: + self.check_page_for_string( id ) + # Make sure only active histories are displayed + for id in deleted_history_ids: + try: + self.check_page_for_string( id ) + raise AssertionError, "deleted history id %d displayed in list of target histories" % id + except: + pass + # Check each history to which we want to copy the item + for id in target_history_ids: + tc.fv( '1', 'target_history_ids', id ) + tc.submit( 'do_copy' ) + no_source_ids = len( source_dataset_ids.split( ',' ) ) + check_str = '%d datasets copied to %d histories.' % ( no_source_ids, len( target_history_ids ) ) + self.check_page_for_string( check_str ) self.home() def get_dataset_ids_in_history( self ): """Returns the ids of datasets in a history""" diff -r 004cd81cff72 -r c69e55c91036 test/functional/test_history_functions.py --- a/test/functional/test_history_functions.py Wed Jun 10 15:46:26 2009 -0400 +++ b/test/functional/test_history_functions.py Thu Jun 11 12:06:29 2009 -0400 @@ -1,3 +1,4 @@ +import urllib import galaxy.model from galaxy.model.orm import * from base.twilltestcase import * @@ -55,7 +56,7 @@ history1 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first() assert history1 is not None, "Problem retrieving history1 from database" self.upload_file( '1.bed', dbkey='hg18' ) - self.new_history( name='history2' ) + self.new_history( name=urllib.quote( 'history2' ) ) global history2 history2 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first() assert history2 is not None, "Problem retrieving history2 from database" @@ -96,7 +97,7 @@ assert history3 is not None, "Problem retrieving history3 from database" if history3.deleted: raise AssertionError, "History id %d deleted when it should not be" % latest_history.id - self.rename_history( str( history3.id ), history3.name, new_name='history3' ) + self.rename_history( str( history3.id ), history3.name, new_name=urllib.quote( 'history 3' ) ) def test_020_history_list( self ): """Testing viewing previously stored histories""" self.view_stored_active_histories() @@ -131,7 +132,7 @@ global history4 history4 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first() assert history4 is not None, "Problem retrieving history4 from database" - self.rename_history( str( history4.id ), history4.name, new_name='history4' ) + self.rename_history( str( history4.id ), history4.name, new_name=urllib.quote( 'history 4' ) ) history4.refresh() self.upload_file( '2.bed', dbkey='hg18' ) id = '%s,%s' % ( str( history3.id ), str( history4.id ) ) @@ -195,7 +196,7 @@ global history5 history5 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first() assert history5 is not None, "Problem retrieving history5 from database" - self.rename_history( str( history5.id ), history5.name, new_name='history5' ) + self.rename_history( str( history5.id ), history5.name, new_name=urllib.quote( 'history5' ) ) history5.refresh() # Due to the limitations of twill ( not functional with the permissions forms ), we're forced # to do this manually. At this point, we just want to restrict the access permission on history5 @@ -377,7 +378,7 @@ action='no_share' ) def test_055_history_show_and_hide_deleted_datasets( self ): """Testing displaying deleted history items""" - self.new_history( name='temp_history1' ) + self.new_history( name=urllib.quote( 'show hide deleted datasets' ) ) self.upload_file('1.bed', dbkey='hg18') latest_hda = galaxy.model.HistoryDatasetAssociation.query() \ .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first() @@ -393,7 +394,7 @@ self.check_page_for_string( 'Your history is empty' ) def test_060_deleting_and_undeleting_history_items( self ): """Testing deleting and un-deleting history items""" - self.new_history( name='temp_history2' ) + self.new_history( name=urllib.quote( 'delete undelete history items' ) ) # Add a new history item self.upload_file( '1.bed', dbkey='hg15' ) self.home() @@ -416,8 +417,54 @@ self.visit_url( "%s/history/?show_deleted=False" % self.url ) self.check_page_for_string( '1.bed' ) self.check_page_for_string( 'hg15' ) - def test_065_reset_data_for_later_test_runs( self ): + def test_065_copying_history_items_between_histories( self ): + """Testing copying history items between histories""" + self.new_history( name=urllib.quote( 'copy history items' ) ) + global history6 + history6 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first() + assert history6 is not None, "Problem retrieving history6 from database" + self.upload_file( '1.bed', dbkey='hg18' ) + hda1 = galaxy.model.HistoryDatasetAssociation.query() \ + .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first() + assert hda1 is not None, "Problem retrieving hda1 from database" + # We'll just test copying 1 hda + source_dataset_ids=str( hda1.id ) + # The valid list of target histories is only the user's active histories + all_target_history_ids = [ str( hda.id ) for hda in admin_user.active_histories ] + # Since history1 and history2 have been deleted, they should not be displayed in the list of target histories + # on the copy_view.mako form + deleted_history_ids = [ str( history1.id ), str( history2.id ) ] + # Test copying to the current history + target_history_ids=[ str( history6.id ) ] + self.copy_history_item( source_dataset_ids=source_dataset_ids, + target_history_ids=target_history_ids, + all_target_history_ids=all_target_history_ids, + deleted_history_ids=deleted_history_ids ) + history6.refresh() + if len( history6.datasets ) != 2: + raise AssertionError, "Copying hda1 to the current history failed" + # Test copying 1 hda to another history + self.new_history( name=urllib.quote( 'copy history items - 2' ) ) + global history7 + history7 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first() + assert history7 is not None, "Problem retrieving history7 from database" + # Switch back to our history from which we want to copy + self.switch_history( id=str( history6.id ), name=history6.name ) + target_history_ids=[ str( history7.id ) ] + all_target_history_ids = [ str( hda.id ) for hda in admin_user.active_histories ] + # Test copying to the a history that is not the current history + target_history_ids=[ str( history7.id ) ] + self.copy_history_item( source_dataset_ids=source_dataset_ids, + target_history_ids=target_history_ids, + all_target_history_ids=all_target_history_ids, + deleted_history_ids=deleted_history_ids ) + # Switch to the history to which we copied + self.switch_history( id=str( history7.id ), name=history7.name ) + self.check_history_for_string( hda1.name ) + def test_070_reset_data_for_later_test_runs( self ): """Reseting data to enable later test runs to pass""" self.delete_history( id=str( history3.id ) ) self.delete_history( id=str( history4.id ) ) self.delete_history( id=str( history5.id ) ) + self.delete_history( id=str( history6.id ) ) + self.delete_history( id=str( history7.id ) )