Пример #1
0
 def test_serialization(self):
     """Test serialization of workflow templates."""
     template = TemplateHandle(
         identifier='ABC',
         base_dir='XYZ',
         workflow_spec=dict(),
         parameters=[
             TemplateParameter(pd.parameter_declaration('A')),
             TemplateParameter(
                 pd.parameter_declaration('B', data_type=pd.DT_LIST)),
             TemplateParameter(pd.parameter_declaration('C', parent='B'))
         ])
     doc = DefaultTemplateLoader().to_dict(template)
     parameters = DefaultTemplateLoader().from_dict(doc).parameters
     assert len(parameters) == 3
     assert 'A' in parameters
     assert 'B' in parameters
     assert len(parameters['B'].children) == 1
     template = DefaultTemplateLoader().from_dict(doc)
     assert template.identifier == 'ABC'
     # The base directory is not materialized
     assert template.base_dir is None
     # Invalid resource descriptor serializations
     with pytest.raises(err.InvalidTemplateError):
         ResourceDescriptor.from_dict(dict())
     with pytest.raises(err.InvalidTemplateError):
         ResourceDescriptor.from_dict({LABEL_ID: 'A', 'noname': 'B'})
 def test_invalid_identifier(self):
     """Assert that an error is raised if a package declaration with an
     invalid identifier is given.
     """
     # Ensure that it works with a valid identifier
     pd.parameter_declaration(identifier='ABC', data_type=pd.DT_BOOL)
     # Error is raised if identifier is None
     with pytest.raises(err.InvalidParameterError):
         pd.parameter_declaration(identifier=None, data_type=pd.DT_BOOL)
 def test_validate_error(self):
     """Assert that errors are raised if an invalid parameter declaration is
     given to the validate_parameter function.
     """
     p = pd.parameter_declaration(identifier='ABC')
     # Ensure that creating a dictionary from a valid parameter declaration
     # is still valid
     pd.validate_parameter(dict(p))
     # Invalid data type for parameter identifier
     p_invalid = dict(p)
     p_invalid[pd.LABEL_ID] = 123
     with pytest.raises(err.InvalidParameterError):
         pd.validate_parameter(p_invalid)
     # Invalid data type for parameter name
     p_invalid = dict(p)
     p_invalid[pd.LABEL_NAME] = 123
     with pytest.raises(err.InvalidParameterError):
         pd.validate_parameter(p_invalid)
     # Invalid data type for parameter data type
     p_invalid = dict(p)
     p_invalid[pd.LABEL_DATATYPE] = 12.3
     with pytest.raises(err.InvalidParameterError):
         pd.validate_parameter(p_invalid)
     # Invalid data type for parameter index
     p_invalid = dict(p)
     p_invalid[pd.LABEL_INDEX] = '12'
     with pytest.raises(err.InvalidParameterError):
         pd.validate_parameter(p_invalid)
     # Invalid data type for parameter required
     p_invalid = dict(p)
     p_invalid[pd.LABEL_REQUIRED] = '12'
     with pytest.raises(err.InvalidParameterError):
         pd.validate_parameter(p_invalid)
Пример #4
0
 def test_validate(self):
     """Test error cases for argument validation."""
     para_list = TemplateParameter(
         pd.parameter_declaration('E', data_type=pd.DT_LIST))
     with pytest.raises(ValueError):
         values.TemplateArgument(parameter=para_list, value=1)
     para_record = TemplateParameter(
         pd.parameter_declaration('E', data_type=pd.DT_RECORD))
     with pytest.raises(ValueError):
         values.TemplateArgument(parameter=para_record, value=list())
     arg = values.TemplateArgument(parameter=TemplateParameter(
         pd.parameter_declaration('E', data_type=pd.DT_INTEGER)),
                                   value=1,
                                   validate=True)
     arg.data_type = 'unknown'
     with pytest.raises(ValueError):
         arg.validate()
 def test_invalid_datatype(self):
     """Assert that an error is raised if a package declaration with an
     invalid data type is given.
     """
     # Ensure that it works with a valid data type
     p = pd.parameter_declaration(identifier='ABC', data_type=pd.DT_RECORD)
     with pytest.raises(err.InvalidParameterError):
         p = pd.parameter_declaration(identifier='ABC', data_type='XYZ')
     # Specifying a non-string value should also raise an error
     with pytest.raises(err.InvalidParameterError):
         pd.parameter_declaration(identifier='ABC', data_type=123)
     # Ensure that validation fails if data type is manipulated
     p = pd.parameter_declaration(identifier='ABC', data_type=pd.DT_RECORD)
     pd.validate_parameter(p)
     p[pd.LABEL_DATATYPE] = 'Something unknown'
     with pytest.raises(err.InvalidParameterError):
         pd.validate_parameter(p)
Пример #6
0
 def test_init(self):
     """Test initialization of attribuets and error cases when creating
     template instances.
     """
     th = TemplateHandle(
         workflow_spec=dict(),
         parameters=[
             TemplateParameter(pd.parameter_declaration('A')),
             TemplateParameter(pd.parameter_declaration('B'))
         ])
     assert not th.identifier is None
     assert th.base_dir is None
     th = TemplateHandle(
         identifier='ABC',
         base_dir='XYZ',
         workflow_spec=dict(),
         parameters=[
             TemplateParameter(pd.parameter_declaration('A')),
             TemplateParameter(pd.parameter_declaration('B'))
         ])
     assert th.identifier == 'ABC'
     assert th.base_dir == 'XYZ'
     with pytest.raises(err.InvalidTemplateError):
         TemplateHandle(
             workflow_spec=dict(),
             parameters=[
                 TemplateParameter(pd.parameter_declaration('A')),
                 TemplateParameter(pd.parameter_declaration('B')),
                 TemplateParameter(pd.parameter_declaration('A'))
             ])
Пример #7
0
 def test_duplicate_id(self):
     """Ensure that exception is raised if parameter identifier are not
     unique.
     """
     with pytest.raises(err.InvalidTemplateError):
         DefaultTemplateLoader().from_dict(
             {
                 loader.LABEL_WORKFLOW:
                 dict(),
                 loader.LABEL_PARAMETERS: [
                     pd.parameter_declaration('A', index=1),
                     pd.parameter_declaration('B'),
                     pd.parameter_declaration('C'),
                     pd.parameter_declaration('A', index=2),
                     pd.parameter_declaration('E', index=1)
                 ]
             },
             validate=True)
Пример #8
0
 def test_read_with_record(self):
     """Read argument for a template that contains a parameter of data type
     DT_RECORD.
     """
     template = TemplateHandle(
         workflow_spec=dict(),
         parameters=[
             TemplateParameter(
                 pd.parameter_declaration(identifier='codeFile',
                                          data_type=pd.DT_FILE,
                                          index=0,
                                          default_value=None,
                                          as_const=AS_INPUT)),
             TemplateParameter(
                 pd.parameter_declaration(identifier='dataFile',
                                          data_type=pd.DT_FILE,
                                          index=1,
                                          default_value='data/names.txt')),
             TemplateParameter(
                 pd.parameter_declaration(identifier='resultFile',
                                          data_type=pd.DT_FILE,
                                          index=2,
                                          default_value=None)),
             TemplateParameter(
                 pd.parameter_declaration(identifier='sleeptime',
                                          data_type=pd.DT_INTEGER,
                                          index=3,
                                          default_value=10)),
             TemplateParameter(
                 pd.parameter_declaration(identifier='verbose',
                                          data_type=pd.DT_BOOL,
                                          index=4,
                                          default_value=False)),
             TemplateParameter(
                 pd.parameter_declaration(identifier='frac',
                                          data_type=pd.DT_DECIMAL,
                                          index=6)),
             TemplateParameter(
                 pd.parameter_declaration(identifier='outputType',
                                          index=5)),
         ])
     sc = Scanner(reader=ListReader([
         'ABC.txt', 'code/abc.py', '', 'result/output.txt', 3, True, 'XYZ',
         0.123
     ]))
     arguments = tmpl.read(template.list_parameters(), scanner=sc)
     assert arguments['codeFile'].name == 'ABC.txt'
     assert arguments['codeFile'].target_path == 'code/abc.py'
     assert arguments['dataFile'].name == 'names.txt'
     assert arguments['dataFile'].target_path is None
     assert arguments['resultFile'].name == 'output.txt'
     assert arguments['resultFile'].target_path is None
     assert arguments['sleeptime'] == 3
     assert arguments['verbose']
     assert arguments['outputType'] == 'XYZ'
     assert arguments['frac'] == 0.123
Пример #9
0
 def test_sort(self):
     """Test the sort functionality of the template list_parameters method.
     """
     # Create a new TemplateHandle with an empty workflow specification and
     # a list of five parameters
     template = DefaultTemplateLoader().from_dict(
         {
             loader.LABEL_WORKFLOW:
             dict(),
             loader.LABEL_PARAMETERS: [
                 pd.parameter_declaration('A', index=1),
                 pd.parameter_declaration('B'),
                 pd.parameter_declaration('C'),
                 pd.parameter_declaration('D', index=2),
                 pd.parameter_declaration('E', index=1)
             ]
         },
         validate=True)
     # Get list of sorted parameter identifier from listing
     keys = [p.identifier for p in template.list_parameters()]
     assert keys == ['B', 'C', 'A', 'E', 'D']
Пример #10
0
 def test_nested_parameters(self):
     """Test proper nesting of parameters for DT_LIST and DT_RECORD."""
     # Create a new TemplateHandle with an empty workflow specification and
     # a list of six parameters (one record and one list)
     template = DefaultTemplateLoader().from_dict(
         {
             loader.LABEL_WORKFLOW:
             dict(),
             loader.LABEL_PARAMETERS: [
                 pd.parameter_declaration('A'),
                 pd.parameter_declaration('B', data_type=pd.DT_RECORD),
                 pd.parameter_declaration('C', parent='B'),
                 pd.parameter_declaration('D', parent='B'),
                 pd.parameter_declaration('E', data_type=pd.DT_LIST),
                 pd.parameter_declaration('F', parent='E'),
             ]
         },
         validate=True)
     # Parameters 'A', 'C', 'D', and 'F' have no children
     for key in ['A', 'C', 'D', 'F']:
         assert not template.get_parameter(key).has_children()
     # Parameter 'B' has two children 'C' and 'D'
     b = template.get_parameter('B')
     assert b.has_children()
     assert len(b.children) == 2
     assert 'C' in [p.identifier for p in b.children]
     assert 'D' in [p.identifier for p in b.children]
     # Parameter 'E' has one childr 'F'
     e = template.get_parameter('E')
     assert e.has_children()
     assert len(e.children) == 1
     assert 'F' in [p.identifier for p in e.children]
Пример #11
0
 def test_propmpt(self):
     """Test generated prompts when reading parameter values from standard
     input.
     """
     # BOOL
     p = TemplateParameter(
         pd.set_defaults(
             pd.parameter_declaration(identifier='ABC',
                                      data_type=pd.DT_BOOL))).prompt()
     assert p == 'ABC (bool): '
     # FILE
     p = TemplateParameter(
         pd.set_defaults(
             pd.parameter_declaration(identifier='ABC',
                                      data_type=pd.DT_FILE))).prompt()
     assert p == 'ABC (file): '
     # FLOAT
     p = TemplateParameter(
         pd.set_defaults(
             pd.parameter_declaration(identifier='ABC',
                                      data_type=pd.DT_DECIMAL))).prompt()
     assert p == 'ABC (decimal): '
     # INTEGER
     p = TemplateParameter(
         pd.set_defaults(
             pd.parameter_declaration(identifier='ABC',
                                      data_type=pd.DT_INTEGER))).prompt()
     assert p == 'ABC (integer): '
     # STRING
     p = TemplateParameter(
         pd.set_defaults(
             pd.parameter_declaration(identifier='ABC',
                                      data_type=pd.DT_STRING))).prompt()
     assert p == 'ABC (string): '
     # Default values in prompts
     p = TemplateParameter(
         pd.set_defaults(
             pd.parameter_declaration(identifier='ABC',
                                      data_type=pd.DT_INTEGER,
                                      default_value=100))).prompt()
     assert p == 'ABC (integer) [default 100]: '
     p = TemplateParameter(
         pd.set_defaults(
             pd.parameter_declaration(identifier='ABC',
                                      data_type=pd.DT_STRING,
                                      default_value=100))).prompt()
     assert p == 'ABC (string) [default \'100\']: '
Пример #12
0
 def test_parameter_declaration(self):
     """Test methods of the parameter declaration object."""
     obj = pd.set_defaults(pd.parameter_declaration(identifier='ABC'))
     obj[pd.LABEL_AS] = 'XYZ'
     p = TemplateParameter(obj)
     # Type flags
     assert not p.is_bool()
     assert not p.is_file()
     assert not p.is_float()
     assert not p.is_int()
     assert not p.is_list()
     assert not p.is_record()
     assert p.is_string()
     # Constant values
     assert p.has_constant()
     assert p.get_constant() == 'XYZ'
     # Error for invalid data type
     with pytest.raises(err.InvalidParameterError):
         TemplateParameter({pd.LABEL_ID: 'A', pd.LABEL_DATATYPE: 'XYZ'})
Пример #13
0
 def test_minimal_declaration(self):
     """Test parameter declarations that only provide the required arguments.
     """
     # Expect to get a dictionary that contains the identifier, name (both
     # equal to 'ABC'), a data type DT_STRING, an index of 0. The required
     #  flag is True.
     p = pd.parameter_declaration(identifier='ABC')
     assert isinstance(p, dict)
     assert p.get(pd.LABEL_ID) == 'ABC'
     assert p.get(pd.LABEL_NAME) == 'ABC'
     assert p.get(pd.LABEL_DESCRIPTION) == 'ABC'
     assert p.get(pd.LABEL_DATATYPE) == pd.DT_STRING
     assert p.get(pd.LABEL_INDEX) == 0
     assert p.get(pd.LABEL_REQUIRED)
     # All other optional elements of the declaration are missing
     assert pd.LABEL_DEFAULT not in p
     assert pd.LABEL_PARENT not in p
     assert pd.LABEL_VALUES not in p
     # Ensure that the returned dictionary is valid with respect to the
     # parameter schema declaration.
     pd.validate_parameter(p)
Пример #14
0
 def test_maximal_declaration(self):
     """Test parameter declarations that provide values for all arguments.
     """
     # Set all parameter elements to values that are different from their
     # default value
     p = pd.parameter_declaration(identifier='ABC',
                                  name='XYZ',
                                  description='ABC to XYZ',
                                  data_type=pd.DT_INTEGER,
                                  index=10,
                                  required=False,
                                  values=[
                                      pd.enum_value(value=1),
                                      pd.enum_value(value=2, text='Two'),
                                      pd.enum_value(value=3,
                                                    text='THREE',
                                                    is_default=True)
                                  ],
                                  parent='DEF',
                                  default_value=5,
                                  as_const='data/names.txt')
     assert isinstance(p, dict)
     assert p.get(pd.LABEL_ID) == 'ABC'
     assert p.get(pd.LABEL_NAME) == 'XYZ'
     assert p.get(pd.LABEL_DESCRIPTION) == 'ABC to XYZ'
     assert p.get(pd.LABEL_DATATYPE) == pd.DT_INTEGER
     assert p.get(pd.LABEL_INDEX) == 10
     assert not p.get(pd.LABEL_REQUIRED)
     assert p.get(pd.LABEL_PARENT) == 'DEF'
     assert p.get(pd.LABEL_DEFAULT) == 5
     assert p.get(pd.LABEL_AS) == 'data/names.txt'
     # Valudate value enumeration
     values = p.get(pd.LABEL_VALUES, [])
     assert len(values) == 3
     self.validate_value(values[0], 1, '1', False)
     self.validate_value(values[1], 2, 'Two', False)
     self.validate_value(values[2], 3, 'THREE', True)
     # Ensure that the returned dictionary is valid with respect to the
     # parameter schema declaration.
     pd.validate_parameter(p)
Пример #15
0
 def test_flat_parse(self):
     """Test parsing arguments for a flat (un-nested) parameter declaration.
     """
     template = TemplateHandle(
         workflow_spec=dict(),
         parameters=[
             TemplateParameter(
                 pd.parameter_declaration('A', data_type=pd.DT_INTEGER)),
             TemplateParameter(
                 pd.parameter_declaration('B', data_type=pd.DT_BOOL)),
             TemplateParameter(
                 pd.parameter_declaration('C', data_type=pd.DT_DECIMAL)),
             TemplateParameter(
                 pd.parameter_declaration('D',
                                          data_type=pd.DT_FILE,
                                          required=False)),
             TemplateParameter(
                 pd.parameter_declaration('E',
                                          data_type=pd.DT_STRING,
                                          required=False))
         ])
     params = template.parameters
     fh = InputFile(f_handle=FileHandle(filepath=LOCAL_FILE))
     # Valid argument set
     args = values.parse_arguments(arguments={
         'A': 10,
         'B': True,
         'C': 12.5,
         'D': fh,
         'E': 'ABC'
     },
                                   parameters=params,
                                   validate=True)
     assert len(args) == 5
     for key in params.keys():
         assert key in args
     values.parse_arguments(arguments=args,
                            parameters=params,
                            validate=False)
     # Error cases
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': 10,
             'Z': 0
         },
                                parameters=params)
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': 10,
             'B': True
         },
                                parameters=params)
     # Validate data type
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': '10',
             'B': True,
             'C': 12.3,
             'D': fh,
             'E': 'ABC'
         },
                                parameters=params,
                                validate=True)
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': 10,
             'B': 23,
             'C': 12.3,
             'D': fh,
             'E': 'ABC'
         },
                                parameters=params,
                                validate=True)
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': 10,
             'B': True,
             'C': '12.3',
             'D': fh,
             'E': 'ABC'
         },
                                parameters=params,
                                validate=True)
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': 10,
             'B': True,
             'C': 12.3,
             'D': 'fh',
             'E': 'ABC'
         },
                                parameters=params,
                                validate=True)
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': 10,
             'B': True,
             'C': 12.3,
             'D': fh,
             'E': 12
         },
                                parameters=params,
                                validate=True)
Пример #16
0
 def test_nested_parse(self):
     """Test parsing arguments for a nested parameter declaration."""
     template = DefaultTemplateLoader().from_dict(
         {
             tmpl.LABEL_WORKFLOW:
             dict(),
             tmpl.LABEL_PARAMETERS: [
                 pd.parameter_declaration('A', data_type=pd.DT_INTEGER),
                 pd.parameter_declaration('B', data_type=pd.DT_RECORD),
                 pd.parameter_declaration(
                     'C', data_type=pd.DT_DECIMAL, parent='B'),
                 pd.parameter_declaration('D',
                                          data_type=pd.DT_STRING,
                                          parent='B',
                                          required=False),
                 pd.parameter_declaration(
                     'E', data_type=pd.DT_LIST, required=False),
                 pd.parameter_declaration(
                     'F', data_type=pd.DT_INTEGER, parent='E'),
                 pd.parameter_declaration('G',
                                          data_type=pd.DT_DECIMAL,
                                          parent='E',
                                          required=False)
             ]
         },
         validate=True)
     params = template.parameters
     # Without values for list parameters
     args = values.parse_arguments(arguments={
         'A': 10,
         'B': {
             'C': 12.3
         }
     },
                                   parameters=params,
                                   validate=True)
     assert len(args) == 2
     assert not args['B'].value.get('C') is None
     assert args['B'].value.get('D') is None
     assert len(args['B'].value) == 1
     assert args['B'].value.get('C').value == 12.3
     # With list arguments
     args = values.parse_arguments(arguments={
         'A':
         10,
         'B': {
             'C': 12.3,
             'D': 'ABC'
         },
         'E': [{
             'F': 1
         }, {
             'F': 2
         }, {
             'F': 3,
             'G': 0.9
         }]
     },
                                   parameters=params,
                                   validate=True)
     assert len(args) == 3
     assert not args['B'].value.get('C') is None
     assert not args['B'].value.get('D') is None
     assert len(args['B'].value) == 2
     assert len(args['E'].value) == 3
     for arg in args['E'].value:
         if arg.get('F').value < 3:
             assert len(arg) == 1
         else:
             assert len(arg) == 2
     # Error cases
     with pytest.raises(ValueError):
         values.parse_arguments(arguments={
             'A': 10,
             'B': [{
                 'C': 12.3
             }]
         },
                                parameters=params,
                                validate=True)