def testLoadErrors(self): f = factory.Factory(plugin_dirs=('./plugins', )) self.assertEqual(f.status(), 0) with mock.patch('importlib.import_module') as loader: loader.side_effect = Exception() with self.assertLogs(level='CRITICAL') as log: f.load() self.assertEqual(f.status(), 1) for out in log.output: self.assertIn("Failed to load module", out) with mock.patch('os.path.isdir', return_value=False): with self.assertLogs(level='ERROR') as log: f.load() self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("'plugin_dirs' parameter is not a directory", log.output[0]) with mock.patch('os.path.isfile', return_value=False): with self.assertLogs(level='ERROR') as log: f.load() self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("'plugin_dirs' parameter is not a python package", log.output[0])
def testCreate(self): f = factory.Factory(plugin_dirs=('./plugins', )) f.load() self.assertEqual(f.status(), 0) obj = f.create('CustomObject', name='Andrew') self.assertEqual(obj.name(), 'Andrew') self.assertEqual(f.status(), 0) obj = f.create('CustomCustomObject', name='Andrew') self.assertEqual(obj.name(), 'Andrew') self.assertEqual(f.status(), 0) with self.assertLogs(level='CRITICAL') as log: f.create('TestObjectBadInit', name='Andrew') self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("Failed to create 'TestObjectBadInit'", log.output[0]) with self.assertLogs(level='ERROR') as log: f.create('Unknown') self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("The supplied name 'Unknown' is not associated", log.output[0])
def testRegister(self): f = factory.Factory() f.load() self.assertEqual(f.status(), 0) plugins2 = os.path.join('plugins2', 'CustomObject2.py') spec = importlib.util.spec_from_file_location('CustomObject2', plugins2) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) otype = module.CustomObject2 f.register('CO2', otype) self.assertEqual(f.status(), 0) obj = f.create('CO2', name='Andrew') self.assertEqual(f.status(), 0) self.assertIsInstance(obj, otype) self.assertEqual(obj.name(), 'Andrew') with self.assertLogs(level='ERROR') as log: f.register('CO2', otype) self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("The 'CO2' name is already", log.output[0])
def testPrint(self): f = factory.Factory(plugin_dirs=('./plugins', )) f.load() f._registered_types.pop('TestObjectBadParams') # avoid error out = str(f) self.assertIn('CustomObject', out) self.assertIn('CustomCustomObject', out)
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 testPackageError(self): f = factory.Factory(plugin_dirs=(self._tmpdir, )) with self.assertLogs(level='ERROR') as log: f.load() self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("the 'plugin_dirs' parameter is not a python package", log.output[0])
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 testParams(self): f = factory.Factory(plugin_dirs=('./plugins', )) f.load() self.assertEqual(f.status(), 0) params = f.params('TestObject') self.assertEqual(f.status(), 0) self.assertIn('par', params) with self.assertLogs(level='CRITICAL') as log: f.params('TestObjectBadParams') self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn('Failed to evaluate validParams', log.output[0]) with self.assertLogs(level='ERROR') as log: f.params('Unknown') self.assertEqual(f.status(), 1) self.assertEqual(len(log.output), 1) self.assertIn("The supplied name 'Unknown' is not associated", log.output[0])
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 testLoad(self): f = factory.Factory(plugin_dirs=('./plugins', )) f.load() self.assertIn('CustomObject', f._registered_types)
def testInit(self): f = factory.Factory() self.assertEqual(f.status(), 0) f.load() self.assertEqual(f.status(), 0)
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])