5 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/40d2e69e89a3/ Changeset: 40d2e69e89a3 User: jmchilton Date: 2013-11-18 07:51:54 Summary: Redo fix from 8b65e61 so it works when no Twill clicking at all occurs (e.g. all default params used). Affected #: 1 file diff -r 64cb656e95b2f40ac5f6f1f26fc484ce88a11ad1 -r 40d2e69e89a3210d1760851ea8563e1e344a0c3f test/base/twilltestcase.py --- a/test/base/twilltestcase.py +++ b/test/base/twilltestcase.py @@ -1356,11 +1356,11 @@ tool_id = tool_id.replace(" ", "+") """Runs the tool 'tool_id' and passes it the key/values from the *kwd""" self.visit_url( "%s/tool_runner/index?tool_id=%s" % (self.url, tool_id) ) + # Must click somewhere in tool_form, to disambiguate what form + # is being targetted. + tc.browser.clicked( tc.browser.get_form( 'tool_form' ), None ) if repeat_name is not None: repeat_button = '%s_add' % repeat_name - # Must click somewhere in tool_form, to disambiguate what form - # is being targetted. - tc.browser.clicked( tc.browser.get_form( 'tool_form' ), None ) # Submit the "repeat" form button to add an input) tc.submit( repeat_button ) tc.find( 'runtool_btn' ) https://bitbucket.org/galaxy/galaxy-central/commits/59a0ca3d48c0/ Changeset: 59a0ca3d48c0 User: jmchilton Date: 2013-11-18 07:51:54 Summary: PEP-8 fixes related to tool test parsing. Affected #: 2 files diff -r 40d2e69e89a3210d1760851ea8563e1e344a0c3f -r 59a0ca3d48c019c017d85fc780239837b2e5453d lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -1574,7 +1574,7 @@ # history, but we'll keep it unique per set of tests composite_data_names_counter = 0 for i, test_elem in enumerate( tests_elem.findall( 'test' ) ): - name = test_elem.get( 'name', 'Test-%d' % (i+1) ) + name = test_elem.get( 'name', 'Test-%d' % (i + 1) ) maxseconds = int( test_elem.get( 'maxseconds', '120' ) ) test = ToolTestBuilder( self, name, maxseconds ) try: @@ -1625,6 +1625,7 @@ raise Exception( "Test output does not have a 'name'" ) assert_elem = output_elem.find("assert_contents") assert_list = None + # Trying to keep testing patch as localized as # possible, this function should be relocated # somewhere more conventional. @@ -1636,7 +1637,7 @@ converted_children = [] for child_elem in child_elems: converted_children.append( convert_elem(child_elem) ) - return {"tag" : tag, "attributes" : attributes, "children" : converted_children} + return {"tag": tag, "attributes": attributes, "children": converted_children} if assert_elem is not None: assert_list = [] for assert_child in list(assert_elem): @@ -1677,6 +1678,7 @@ test.error = True test.exception = e self.tests.append( test ) + def parse_input_page( self, input_elem, enctypes ): """ Parse a page of inputs. This basically just calls 'parse_input_elem', diff -r 40d2e69e89a3210d1760851ea8563e1e344a0c3f -r 59a0ca3d48c019c017d85fc780239837b2e5453d lib/galaxy/tools/test.py --- a/lib/galaxy/tools/test.py +++ b/lib/galaxy/tools/test.py @@ -1,20 +1,18 @@ -import new, sys import os.path -import galaxy.util -import parameters from parameters import basic from parameters import grouping -from elementtree.ElementTree import XML import logging log = logging.getLogger( __name__ ) + class ToolTestBuilder( object ): """ Encapsulates information about a tool test, and allows creation of a dynamic TestCase class (the unittest framework is very class oriented, doing dynamic tests in this way allows better integration) """ + def __init__( self, tool, name, maxseconds ): self.tool = tool self.name = name @@ -24,6 +22,7 @@ self.outputs = [] self.error = False self.exception = None + def add_param( self, name, value, extra ): try: if name not in self.tool.inputs: @@ -43,8 +42,10 @@ except Exception, e: log.debug( "Error for tool %s: could not add test parameter %s. %s" % ( self.tool.id, name, e ) ) self.inputs.append( ( name, value, extra ) ) + def add_output( self, name, file, extra ): self.outputs.append( ( name, file, extra ) ) + def __expand_grouping_for_data_input( self, name, value, extra, grouping_name, grouping_value ): # Currently handles grouping.Conditional and grouping.Repeat if isinstance( grouping_value, grouping.Conditional ): @@ -93,20 +94,21 @@ if found_parameter: return True, new_value return False, value + def __add_uploaded_dataset( self, name, value, extra, input_parameter ): if value is None: assert input_parameter.optional, '%s is not optional. You must provide a valid filename.' % name return value if ( value, extra ) not in self.required_files: - self.required_files.append( ( value, extra ) ) #these files will be uploaded + self.required_files.append( ( value, extra ) ) # these files will be uploaded name_change = [ att for att in extra.get( 'edit_attributes', [] ) if att.get( 'type' ) == 'name' ] if name_change: - name_change = name_change[-1].get( 'value' ) #only the last name change really matters - value = name_change #change value for select to renamed uploaded file for e.g. composite dataset + name_change = name_change[-1].get( 'value' ) # only the last name change really matters + value = name_change # change value for select to renamed uploaded file for e.g. composite dataset else: for end in [ '.zip', '.gz' ]: if value.endswith( end ): value = value[ :-len( end ) ] break - value = os.path.basename( value ) #if uploading a file in a path other than root of test-data + value = os.path.basename( value ) # if uploading a file in a path other than root of test-data return value https://bitbucket.org/galaxy/galaxy-central/commits/d9482b09663e/ Changeset: d9482b09663e User: jmchilton Date: 2013-11-18 07:51:54 Summary: Refactor tool test parsing logic out of Tool and into ToolTestBuilder. Affected #: 2 files diff -r 59a0ca3d48c019c017d85fc780239837b2e5453d -r d9482b09663e0cb7cc74adc284267fee1dc498eb lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -1570,113 +1570,8 @@ store in `self.tests`. """ self.tests = [] - # Composite datasets need a unique name: each test occurs in a fresh - # history, but we'll keep it unique per set of tests - composite_data_names_counter = 0 for i, test_elem in enumerate( tests_elem.findall( 'test' ) ): - name = test_elem.get( 'name', 'Test-%d' % (i + 1) ) - maxseconds = int( test_elem.get( 'maxseconds', '120' ) ) - test = ToolTestBuilder( self, name, maxseconds ) - try: - for param_elem in test_elem.findall( "param" ): - attrib = dict( param_elem.attrib ) - if 'values' in attrib: - value = attrib[ 'values' ].split( ',' ) - elif 'value' in attrib: - value = attrib['value'] - else: - value = None - attrib['children'] = list( param_elem.getchildren() ) - if attrib['children']: - # At this time, we can assume having children only - # occurs on DataToolParameter test items but this could - # change and would cause the below parsing to change - # based upon differences in children items - attrib['metadata'] = [] - attrib['composite_data'] = [] - attrib['edit_attributes'] = [] - # Composite datasets need to be renamed uniquely - composite_data_name = None - for child in attrib['children']: - if child.tag == 'composite_data': - attrib['composite_data'].append( child ) - if composite_data_name is None: - # Generate a unique name; each test uses a - # fresh history - composite_data_name = '_COMPOSITE_RENAMED_%i_' \ - % ( composite_data_names_counter ) - composite_data_names_counter += 1 - elif child.tag == 'metadata': - attrib['metadata'].append( child ) - elif child.tag == 'metadata': - attrib['metadata'].append( child ) - elif child.tag == 'edit_attributes': - attrib['edit_attributes'].append( child ) - if composite_data_name: - # Composite datasets need implicit renaming; - # inserted at front of list so explicit declarations - # take precedence - attrib['edit_attributes'].insert( 0, { 'type': 'name', 'value': composite_data_name } ) - test.add_param( attrib.pop( 'name' ), value, attrib ) - for output_elem in test_elem.findall( "output" ): - attrib = dict( output_elem.attrib ) - name = attrib.pop( 'name', None ) - if name is None: - raise Exception( "Test output does not have a 'name'" ) - assert_elem = output_elem.find("assert_contents") - assert_list = None - - # Trying to keep testing patch as localized as - # possible, this function should be relocated - # somewhere more conventional. - def convert_elem(elem): - """ Converts and XML element to a dictionary format, used by assertion checking code. """ - tag = elem.tag - attributes = dict( elem.attrib ) - child_elems = list( elem.getchildren() ) - converted_children = [] - for child_elem in child_elems: - converted_children.append( convert_elem(child_elem) ) - return {"tag": tag, "attributes": attributes, "children": converted_children} - if assert_elem is not None: - assert_list = [] - for assert_child in list(assert_elem): - assert_list.append(convert_elem(assert_child)) - file = attrib.pop( 'file', None ) - # File no longer required if an list of assertions was present. - if assert_list is None and file is None: - raise Exception( "Test output does not have a 'file'") - attributes = {} - # Method of comparison - attributes['compare'] = attrib.pop( 'compare', 'diff' ).lower() - # Number of lines to allow to vary in logs (for dates, etc) - attributes['lines_diff'] = int( attrib.pop( 'lines_diff', '0' ) ) - # Allow a file size to vary if sim_size compare - attributes['delta'] = int( attrib.pop( 'delta', '10000' ) ) - attributes['sort'] = string_as_bool( attrib.pop( 'sort', False ) ) - attributes['extra_files'] = [] - attributes['assert_list'] = assert_list - if 'ftype' in attrib: - attributes['ftype'] = attrib['ftype'] - for extra in output_elem.findall( 'extra_files' ): - # File or directory, when directory, compare basename - # by basename - extra_type = extra.get( 'type', 'file' ) - extra_name = extra.get( 'name', None ) - assert extra_type == 'directory' or extra_name is not None, \ - 'extra_files type (%s) requires a name attribute' % extra_type - extra_value = extra.get( 'value', None ) - assert extra_value is not None, 'extra_files requires a value attribute' - extra_attributes = {} - extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower() - extra_attributes['delta'] = extra.get( 'delta', '0' ) - extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) ) - extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) ) - attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) ) - test.add_output( name, file, attributes ) - except Exception, e: - test.error = True - test.exception = e + test = ToolTestBuilder( self, test_elem, i ) self.tests.append( test ) def parse_input_page( self, input_elem, enctypes ): diff -r 59a0ca3d48c019c017d85fc780239837b2e5453d -r d9482b09663e0cb7cc74adc284267fee1dc498eb lib/galaxy/tools/test.py --- a/lib/galaxy/tools/test.py +++ b/lib/galaxy/tools/test.py @@ -1,6 +1,7 @@ import os.path from parameters import basic from parameters import grouping +from galaxy.util import string_as_bool import logging log = logging.getLogger( __name__ ) @@ -13,7 +14,10 @@ doing dynamic tests in this way allows better integration) """ - def __init__( self, tool, name, maxseconds ): + def __init__( self, tool, test_elem, i ): + name = test_elem.get( 'name', 'Test-%d' % (i + 1) ) + maxseconds = int( test_elem.get( 'maxseconds', '120' ) ) + self.tool = tool self.name = name self.maxseconds = maxseconds @@ -23,6 +27,114 @@ self.error = False self.exception = None + self.__parse_elem( test_elem, i ) + + def __parse_elem( self, test_elem, i ): + # Composite datasets need a unique name: each test occurs in a fresh + # history, but we'll keep it unique per set of tests - use i (test #) + # and composite_data_names_counter (instance per test #) + composite_data_names_counter = 0 + try: + for param_elem in test_elem.findall( "param" ): + attrib = dict( param_elem.attrib ) + if 'values' in attrib: + value = attrib[ 'values' ].split( ',' ) + elif 'value' in attrib: + value = attrib['value'] + else: + value = None + attrib['children'] = list( param_elem.getchildren() ) + if attrib['children']: + # At this time, we can assume having children only + # occurs on DataToolParameter test items but this could + # change and would cause the below parsing to change + # based upon differences in children items + attrib['metadata'] = [] + attrib['composite_data'] = [] + attrib['edit_attributes'] = [] + # Composite datasets need to be renamed uniquely + composite_data_name = None + for child in attrib['children']: + if child.tag == 'composite_data': + attrib['composite_data'].append( child ) + if composite_data_name is None: + # Generate a unique name; each test uses a + # fresh history + composite_data_name = '_COMPOSITE_RENAMED_t%i_d%i' \ + % ( i, composite_data_names_counter ) + composite_data_names_counter += 1 + elif child.tag == 'metadata': + attrib['metadata'].append( child ) + elif child.tag == 'metadata': + attrib['metadata'].append( child ) + elif child.tag == 'edit_attributes': + attrib['edit_attributes'].append( child ) + if composite_data_name: + # Composite datasets need implicit renaming; + # inserted at front of list so explicit declarations + # take precedence + attrib['edit_attributes'].insert( 0, { 'type': 'name', 'value': composite_data_name } ) + self.add_param( attrib.pop( 'name' ), value, attrib ) + for output_elem in test_elem.findall( "output" ): + attrib = dict( output_elem.attrib ) + name = attrib.pop( 'name', None ) + if name is None: + raise Exception( "Test output does not have a 'name'" ) + assert_elem = output_elem.find("assert_contents") + assert_list = None + + # Trying to keep testing patch as localized as + # possible, this function should be relocated + # somewhere more conventional. + def convert_elem(elem): + """ Converts and XML element to a dictionary format, used by assertion checking code. """ + tag = elem.tag + attributes = dict( elem.attrib ) + child_elems = list( elem.getchildren() ) + converted_children = [] + for child_elem in child_elems: + converted_children.append( convert_elem(child_elem) ) + return {"tag": tag, "attributes": attributes, "children": converted_children} + if assert_elem is not None: + assert_list = [] + for assert_child in list(assert_elem): + assert_list.append(convert_elem(assert_child)) + file = attrib.pop( 'file', None ) + # File no longer required if an list of assertions was present. + if assert_list is None and file is None: + raise Exception( "Test output does not have a 'file'") + attributes = {} + # Method of comparison + attributes['compare'] = attrib.pop( 'compare', 'diff' ).lower() + # Number of lines to allow to vary in logs (for dates, etc) + attributes['lines_diff'] = int( attrib.pop( 'lines_diff', '0' ) ) + # Allow a file size to vary if sim_size compare + attributes['delta'] = int( attrib.pop( 'delta', '10000' ) ) + attributes['sort'] = string_as_bool( attrib.pop( 'sort', False ) ) + attributes['extra_files'] = [] + attributes['assert_list'] = assert_list + if 'ftype' in attrib: + attributes['ftype'] = attrib['ftype'] + for extra in output_elem.findall( 'extra_files' ): + # File or directory, when directory, compare basename + # by basename + extra_type = extra.get( 'type', 'file' ) + extra_name = extra.get( 'name', None ) + assert extra_type == 'directory' or extra_name is not None, \ + 'extra_files type (%s) requires a name attribute' % extra_type + extra_value = extra.get( 'value', None ) + assert extra_value is not None, 'extra_files requires a value attribute' + extra_attributes = {} + extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower() + extra_attributes['delta'] = extra.get( 'delta', '0' ) + extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) ) + extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) ) + attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) ) + self.add_output( name, file, attributes ) + except Exception, e: + self.error = True + self.exception = e + def add_param( self, name, value, extra ): try: if name not in self.tool.inputs: https://bitbucket.org/galaxy/galaxy-central/commits/b1a929a53f22/ Changeset: b1a929a53f22 User: jmchilton Date: 2013-11-18 07:51:54 Summary: Make formerly public methods in ToolTestBuilder private now that it does its own construction. Affected #: 1 file diff -r d9482b09663e0cb7cc74adc284267fee1dc498eb -r b1a929a53f22ed8e59e8ca4d75d3ab230344cd46 lib/galaxy/tools/test.py --- a/lib/galaxy/tools/test.py +++ b/lib/galaxy/tools/test.py @@ -74,7 +74,7 @@ # inserted at front of list so explicit declarations # take precedence attrib['edit_attributes'].insert( 0, { 'type': 'name', 'value': composite_data_name } ) - self.add_param( attrib.pop( 'name' ), value, attrib ) + self.__add_param( attrib.pop( 'name' ), value, attrib ) for output_elem in test_elem.findall( "output" ): attrib = dict( output_elem.attrib ) name = attrib.pop( 'name', None ) @@ -130,12 +130,12 @@ extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) ) extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) ) attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) ) - self.add_output( name, file, attributes ) + self.__add_output( name, file, attributes ) except Exception, e: self.error = True self.exception = e - def add_param( self, name, value, extra ): + def __add_param( self, name, value, extra ): try: if name not in self.tool.inputs: found_parameter = False @@ -155,7 +155,7 @@ log.debug( "Error for tool %s: could not add test parameter %s. %s" % ( self.tool.id, name, e ) ) self.inputs.append( ( name, value, extra ) ) - def add_output( self, name, file, extra ): + def __add_output( self, name, file, extra ): self.outputs.append( ( name, file, extra ) ) def __expand_grouping_for_data_input( self, name, value, extra, grouping_name, grouping_value ): https://bitbucket.org/galaxy/galaxy-central/commits/3ebc0f5c4486/ Changeset: 3ebc0f5c4486 User: jmchilton Date: 2013-11-18 07:51:54 Summary: Refactor smaller methods out of tool output test parsing. Affected #: 1 file diff -r b1a929a53f22ed8e59e8ca4d75d3ab230344cd46 -r 3ebc0f5c4486cc5c207882bcea819018d23b2bf4 lib/galaxy/tools/test.py --- a/lib/galaxy/tools/test.py +++ b/lib/galaxy/tools/test.py @@ -80,29 +80,12 @@ name = attrib.pop( 'name', None ) if name is None: raise Exception( "Test output does not have a 'name'" ) - assert_elem = output_elem.find("assert_contents") - assert_list = None - # Trying to keep testing patch as localized as - # possible, this function should be relocated - # somewhere more conventional. - def convert_elem(elem): - """ Converts and XML element to a dictionary format, used by assertion checking code. """ - tag = elem.tag - attributes = dict( elem.attrib ) - child_elems = list( elem.getchildren() ) - converted_children = [] - for child_elem in child_elems: - converted_children.append( convert_elem(child_elem) ) - return {"tag": tag, "attributes": attributes, "children": converted_children} - if assert_elem is not None: - assert_list = [] - for assert_child in list(assert_elem): - assert_list.append(convert_elem(assert_child)) + assert_list = self.__parse_assert_list( output_elem ) file = attrib.pop( 'file', None ) # File no longer required if an list of assertions was present. - if assert_list is None and file is None: - raise Exception( "Test output does not have a 'file'") + if not assert_list and file is None: + raise Exception( "Test output does not have a 'file' to compare with or list of assertions to check") attributes = {} # Method of comparison attributes['compare'] = attrib.pop( 'compare', 'diff' ).lower() @@ -116,25 +99,51 @@ if 'ftype' in attrib: attributes['ftype'] = attrib['ftype'] for extra in output_elem.findall( 'extra_files' ): - # File or directory, when directory, compare basename - # by basename - extra_type = extra.get( 'type', 'file' ) - extra_name = extra.get( 'name', None ) - assert extra_type == 'directory' or extra_name is not None, \ - 'extra_files type (%s) requires a name attribute' % extra_type - extra_value = extra.get( 'value', None ) - assert extra_value is not None, 'extra_files requires a value attribute' - extra_attributes = {} - extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower() - extra_attributes['delta'] = extra.get( 'delta', '0' ) - extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) ) - extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) ) - attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) ) + attributes['extra_files'].append( self.__parse_extra_files_elem( extra ) ) self.__add_output( name, file, attributes ) except Exception, e: self.error = True self.exception = e + def __parse_assert_list( self, output_elem ): + assert_elem = output_elem.find("assert_contents") + assert_list = None + + # Trying to keep testing patch as localized as + # possible, this function should be relocated + # somewhere more conventional. + def convert_elem(elem): + """ Converts and XML element to a dictionary format, used by assertion checking code. """ + tag = elem.tag + attributes = dict( elem.attrib ) + child_elems = list( elem.getchildren() ) + converted_children = [] + for child_elem in child_elems: + converted_children.append( convert_elem(child_elem) ) + return {"tag": tag, "attributes": attributes, "children": converted_children} + if assert_elem is not None: + assert_list = [] + for assert_child in list(assert_elem): + assert_list.append(convert_elem(assert_child)) + + return assert_list + + def __parse_extra_files_elem( self, extra ): + # File or directory, when directory, compare basename + # by basename + extra_type = extra.get( 'type', 'file' ) + extra_name = extra.get( 'name', None ) + assert extra_type == 'directory' or extra_name is not None, \ + 'extra_files type (%s) requires a name attribute' % extra_type + extra_value = extra.get( 'value', None ) + assert extra_value is not None, 'extra_files requires a value attribute' + extra_attributes = {} + extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower() + extra_attributes['delta'] = extra.get( 'delta', '0' ) + extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) ) + extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) ) + return extra_type, extra_value, extra_name, extra_attributes + def __add_param( self, name, value, extra ): try: if name not in self.tool.inputs: Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.