def _create_runners(root_dir, filename, spec_file_blocks, obj_factory): """ Return the `Runner` objects, with attached `Differ` objects, as defined in HIT file given in *filename*. The *root_dir* is the starting location provided to the `discover` function. Objects are only extracted from the HIT blocks in *spec_file_blocks*. The *obj_factory* is used to by the HIT parser to create the desired object type. TODO: This should return a list of lists and allow for each `Runner` to optionally, have a separate entry in the outer list. This will allow handling of intra-file dependencies if needed or the ability to run without any dependencies. For example, the `Runner` could have a `depends_on`, that defaults to the previously defined runner. Supply `None` would put it in its own entry in the outer list. """ root = pyhit.load(filename) wh = MooseTestWarehouse(root_dir=root_dir, specfile=filename) parser = factory.Parser(obj_factory, wh) for node in moosetree.findall(root, func=lambda n: n.name in spec_file_blocks): parser.parse( filename, node, ) return wh.objects, max(parser.status(), wh.status())
def make_formatter(filename, root, plugin_dirs): """ Create the `Formatter` object from the [Formatter] block of the `pyhit.Node` of *root*. By default, a `BasicFormatter` is created. Refer to `make_controllers` function for information on the supplied input arguments. """ # Locate/create the [Formatter] node f_node = moosetree.find(root, func=lambda n: n.fullpath == '/Formatter') if f_node is None: f_node = root.append('Formatter', type='BasicFormatter') # Factory for building Formatter objects f_factory = factory.Factory(plugin_dirs=plugin_dirs, plugin_types=(Formatter, )) f_factory.load() if f_factory.status() > 0: msg = "An error occurred registering the Formatter type, see console message(s) for details." raise RuntimeError(msg) # Create the Formatter object by parsing the input file formatters = list() f_parser = factory.Parser(f_factory, formatters) with mooseutils.CurrentWorkingDirectory(os.path.dirname(filename)): f_parser._parseNode(filename, f_node) if f_parser.status() > 0: msg = "An error occurred during parsing of the root level parameters for creation of the Formatter object, see console message(s) for details." raise RuntimeError(msg) return formatters[0]
def testTypes(self): f = factory.Factory() f.load() w = factory.Warehouse() p = factory.Parser(f, w) p.parse('test1.hit') self.assertEqual(len(w.objects), 4) self.assertEqual(w.objects[0].name(), 'scalar') self.assertEqual(w.objects[0].getParam('par_int'), 1980) self.assertEqual(w.objects[0].getParam('par_float'), 1.2345) self.assertEqual(w.objects[0].getParam('par_str'), "string with space") self.assertEqual(w.objects[0].getParam('par_bool'), True) self.assertEqual(w.objects[1].name(), 'vector') self.assertEqual(w.objects[1].getParam('vec_int'), (1949, 1954, 1977, 1980)) self.assertEqual(w.objects[1].getParam('vec_float'), (1.1, 1.2, 1.3)) self.assertEqual(w.objects[1].getParam('vec_str'), ("s0", "s1", "s2")) self.assertEqual(w.objects[1].getParam('vec_bool'), (True, False, True, False, True, False)) self.assertEqual(w.objects[2].name(), 'any') self.assertEqual(w.objects[2].getParam('par'), "this is something") self.assertEqual(w.objects[3].name(), 'scalar_with_quote') self.assertEqual(w.objects[3].getParam('par_int'), 1980) self.assertEqual(w.objects[3].getParam('par_float'), 1.2345) self.assertEqual(w.objects[3].getParam('par_str'), "string with 'quote'") self.assertEqual(w.objects[3].getParam('par_bool'), True)
def testSimple(self): f = factory.Factory() f.load() w = factory.Warehouse() p = factory.Parser(f, w) p.parse('test0.hit') self.assertEqual(len(w.objects), 2) self.assertEqual(w.objects[0].name(), 'object0') self.assertEqual(w.objects[1].name(), 'object1')
def make_controllers(filename, root, plugin_dirs): """ Create the `Controller` object from the [Controllers] block of the `pyhit.Node` of *root*. The *filename* is provided for error reporting and setting the current working directory for creating object defined in the configuration file. It should be the file used for generating the tree structure in *root*. The *plugin_dirs* should contain a list of absolute paths to include when registering Controller objects with the factory. By default, regardless of the contents of *root*, all registered Controller objects are created. """ # Locate/create the [Controllers] node c_node = moosetree.find(root, func=lambda n: n.fullpath == '/Controllers') if c_node is None: c_node = root.append('Controllers') # Factory for building Controller objects c_factory = factory.Factory(plugin_dirs=plugin_dirs, plugin_types=(Controller, )) c_factory.load() if c_factory.status() > 0: msg = "An error occurred registering the Controller type, see console message(s) for details." raise RuntimeError(msg) # All Controller object type found by the Factory are automatically included with the default # configuration. This adds them to the configuration tree so they will be built by the factory c_types = set(child['type'] for child in c_node) for name in [ key for key, value in c_factory._registered_types.items() if value.AUTO_BUILD ]: if name not in c_types: c_node.append(f"_moosetools_{name}", type=name) # Use the Parser to create the Controller objects controllers = list() c_parser = factory.Parser(c_factory, controllers) with mooseutils.CurrentWorkingDirectory(os.path.dirname(filename)): c_parser.parse(filename, c_node) if c_parser.status() > 0: msg = "An error occurred during parsing of the Controller block, see console message(s) for details." raise RuntimeError(msg) return tuple(controllers)
def make_harness(filename, root, cli_args): """ Create the `TestHarness` object from top-level parameters in the `pyhit.Node` of *root*. The *filename* is provided for error reporting and should be the file used for generating the tree structure in *root*. The *cli_args* input is passed to the created `TestHarness` object via the `applyCommandLineArguments` method. It is expected that the file that produced *root* has top-level parameters, which are used to create a `TestHarness` object. """ # Top-level parameters are used to build the TestHarness object. Creating custom `TestHarness` # objects is not-supported, so don't allow "type" to be set. if 'type' in root: msg = "The 'type' parameter must NOT be defined in the top-level of the configuration." raise RuntimeError(msg) root['type'] = 'TestHarness' # Build a factory capable of creating the TestHarness object f = factory.Factory() f.register('TestHarness', TestHarness) if f.status() > 0: msg = "An error occurred during registration of the TestHarness type, see console message(s) for details." raise RuntimeError(msg) # Setup the environment variables setup_environment(filename, root) # Use the Parser is used to correctly convert HIT to InputParameters w = list() p = factory.Parser(f, w) with mooseutils.CurrentWorkingDirectory(os.path.dirname(filename)): p._parseNode(filename, root) if p.status() > 0: msg = "An error occurred during parsing of the root level parameters for creation of the TestHarness object, see console message(s) for details." raise RuntimeError(msg) # Apply the command line arguments to update TestHarness object parameters harness = w[0] harness.applyCommandLineArguments(cli_args) if harness.status() > 0: msg = "An error occurred applying the command line arguments to the TestHarness object, see console message(s) for details." raise RuntimeError(msg) return harness
def testSubBlocks(self): root = pyhit.Node(None, 'Tests') root.append('obj0', type='TestObject') root.append('obj1', type='TestObject') sub = root.append('sub') sub.append('obj2', type='TestObject') sub.append('obj3', type='TestObject') f = factory.Factory() f.load() w = factory.Warehouse() p = factory.Parser(f, w) with mock.patch('moosetools.pyhit.load') as load: load.return_value = root p.parse('test0.hit') self.assertEqual(len(w.objects), 4) self.assertEqual(w.objects[0].name(), 'obj0') self.assertEqual(w.objects[1].name(), 'obj1') self.assertEqual(w.objects[2].name(), 'obj2') self.assertEqual(w.objects[3].name(), 'obj3')
def testErrors(self): f = factory.Factory() f.load() w = factory.Warehouse() p = factory.Parser(f, w) # INVALID FILENAME with self.assertLogs(level='ERROR') as log: p.parse('wrong') self.assertEqual(len(log.output), 1) self.assertIn("The filename 'wrong' does not exist.", log.output[0]) # MISSING TYPE root = pyhit.Node(None, 'Tests') root.append('obj0') with self.assertLogs(level='ERROR') as log: p._parseNode('test0.hit', root) self.assertEqual(p.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("Missing 'type' in block", log.output[0]) # FAIL PYHIT.LOAD with mock.patch('moosetools.pyhit.load') as load: load.side_effect = Exception() with self.assertLogs(level='ERROR') as log: p.parse('test0.hit') self.assertEqual(p.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("Failed to load filename with pyhit: test0.hit", log.output[0]) # OBJECT FAILS VALIDPARAMS root = pyhit.Node(None, 'Tests') root.append('obj0', type='TestObjectBadParams') with mock.patch('moosetools.pyhit.load') as load: load.return_value = root with self.assertLogs(level='ERROR') as log: p.parse('test0.hit') self.assertEqual(p.status(), 1) self.assertEqual(len(log.output), 2) self.assertIn("Failed to evaluate validParams function of 'TestObjectBadParams'", log.output[0]) self.assertIn("Failed to extract parameters from 'TestObjectBadParams'", log.output[1]) # PARAM NO EXISTY root = pyhit.Node(None, 'Tests') root.append('obj0', type='TestObject', nope='1') with mock.patch('moosetools.pyhit.load') as load: load.return_value = root with self.assertLogs(level='ERROR') as log: p.parse('test0.hit') self.assertEqual(p.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("he parameter 'nope' does not exist", log.output[0]) # PARAM WRONG TYPE root = pyhit.Node(None, 'Tests') root.append('obj0', type='TestObject', par_int='abc') with mock.patch('moosetools.pyhit.load') as load: load.return_value = root with self.assertLogs(level='ERROR') as log: p.parse('test0.hit') self.assertEqual(p.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn( "Failed to convert 'None' to the correct type(s) of '(<class 'int'>,)' for 'par_int' parameter", log.output[0]) # OBJECT FAILS __INIT__ root = pyhit.Node(None, 'Tests') root.append('obj0', type='TestObjectBadInit') with mock.patch('moosetools.pyhit.load') as load: load.return_value = root with self.assertLogs(level='ERROR') as log: p.parse('test0.hit') self.assertEqual(p.status(), 1) self.assertEqual(len(log.output), 2) self.assertIn("Failed to create 'TestObjectBadInit' object.", log.output[0]) self.assertIn( "Failed to create object of type 'TestObjectBadInit' in block 'Tests/obj0'", log.output[1]) # DUPLICATE BLOCKS/PARAMS root = pyhit.Node(None, 'Tests') root.append('obj0', type='TestObject') root.append('obj0', type='TestObject') with mock.patch('moosetools.pyhit.load') as load: load.return_value = root with self.assertLogs(level='ERROR') as log: p.parse('test0.hit') self.assertEqual(p.status(), 1) self.assertEqual(len(log.output), 2) self.assertIn("Duplicate section 'Tests/obj0'", log.output[0]) self.assertIn("Duplicate parameter 'Tests/obj0/type'", log.output[1])