def test_importer(self): from libcellml import Importer, Parser, Printer parser = Parser() i = Importer() m = parser.parseModel(file_contents('importer/diamond.cellml')) printer = Printer() i.resolveImports(m, resource_path('importer/')) self.assertFalse(m.hasUnresolvedImports()) # Library should contain left, right, and one instance (not two) of the point. self.assertEqual(3, i.libraryCount()) self.assertEqual(resource_path('importer/diamond_left.cellml'), i.key(0)) self.assertEqual(resource_path('importer/diamond_point.cellml'), i.key(1)) self.assertEqual(resource_path('importer/diamond_right.cellml'), i.key(2)) # Access library items by their URL. left = i.library(resource_path('importer/diamond_left.cellml')) self.assertEqual(file_contents('importer/diamond_left.cellml'), printer.printModel(left))
# Iterate through the items in the library (Importer.libraryCount() will give you # the total), and print its keys to the terminal. The keys can be retrieved as a # string from the Importer.key(index) function. At this stage we expect only one model in the library. print('The importer has {} models in the library.'.format(importer.libraryCount())) for i in range(0, importer.libraryCount()): print(' library({}) = {}'.format(i, importer.key(i))) print() # 10.e # We can simply use a clone of the imported components to define dummy variables in the # destination component. # Create dummy components from the resolved imported components. You can get these from the # library or from the import source's model (or one of each, to prove to yourself that it works # either way!). dummy_gate = imported_gate.importSource().model().component(imported_gate.importReference()).clone() dummy_controller = importer.library('PotassiumChannelController.cellml').component(controller.importReference()).clone() # GOTCHA: Note that when an item is added to a new parent, it is automatically removed from # its original parent. Iterating through a set of children is best done in descending # index order or using a while loop so that child items are not skipped as the indices change. # 10.f # Iterate through the variables in each dummy component, and add a clone of each variable # to the destination component. while(dummy_gate.variableCount()): imported_gate.addVariable(dummy_gate.variable(0)) while(dummy_controller.variableCount()): controller.addVariable(dummy_controller.variable(0)) # More connections are needed. These should include: # - (n_gate equations component : imported gate component)
print('The importer has {} models in the library.'.format( importer.libraryCount())) for i in range(0, importer.libraryCount()): print(' library({}) = {}'.format(i, importer.key(i))) print() # 10.e # We can simply use a clone of the imported components to define dummy variables in the # destination component. # Create dummy components from the resolved imported components. You can get these from the # library or from the import source's model (or one of each, to prove to yourself that it works # either way!). dummy_gate = imported_gate.importSource().model().component( imported_gate.importReference()).clone() dummy_controller = importer.library( os.path.join(import_path, 'PotassiumChannelController.cellml')).component( controller.importReference()).clone() # GOTCHA: Note that when an item is added to a new parent, it is automatically removed from # its original parent. Iterating through a set of children is best done in descending # index order or using a while loop so that child items are not skipped as the indices change. # 10.f # Iterate through the variables in each dummy component, and add a clone of each variable # to the destination component. while (dummy_gate.variableCount()): imported_gate.addVariable(dummy_gate.variable(0)) while (dummy_controller.variableCount()): controller.addVariable(dummy_controller.variable(0)) # More connections are needed. These should include:
print('----------------------------------------------------------') # At this stage we've validated the local model, and we've used the Importer class # to retrieve all of its import dependencies. These dependencies are stored in # the importer's library, and have not yet been validated or analysed. # Useful functions: # - Importer.libraryCount() returns the number of stored models # - Importer.library(index) returns the model at the given index # - Importer.key(index) returns a key string that could be used to retrieve the model too # - Importer.library(keystring) returns the model at the given key. # 5.a # Use a simple loop to validate each of the models stored in the importer's library. for i in range(0, importer.libraryCount()): print('Imported model at key: {}'.format(importer.key(i))) validator.validateModel(importer.library(i)) print_issues(validator) # end 5.a # Note that the two files creating the circular import in 4.a are still in the # library. # To limit ourselves to only those models which are still relevant as the import # dependencies of our repaired model, we can iterate through our model's ImportSource # items instead. As soon as the model's imports have been resolved, all these will # point to instantiated models within the importer. # Useful functions: # - Model.importSourceCount() # - Model.importSource(size_t index) and # - ImportSource.model()
print('--------------------------------------------') # At this stage we've validated the local model, and we've used the Importer class # to retrieve all of its import dependencies. These dependencies are stored in # the importer's library, and have not yet been validated or analysed. # Useful functions: # - Importer.libraryCount() returns the number of stored models # - Importer.library(index) returns the model at the given index # - Importer.key(index) returns a key string that could be used to retrieve the model too # - Importer.library(keystring) returns the model at the given key. # 5.a # Use a simple loop to validate each of the models stored in the importer's library. for i in range(0, importer.libraryCount()): print('Imported model at key: {}'.format(importer.key(i))) validator.validateModel(importer.library(i)) print_issues(validator) # end 5.a # Note that the two files creating the circular import in 4.a are still in the # library. # To limit ourselves to only those models which are still relevant as the import # dependencies of our repaired model, we can iterate through our model's ImportSource # items instead. As soon as the model's imports have been resolved, all these will # point to instantiated models within the importer. # Useful functions: # - Model.importSourceCount() # - Model.importSource(size_t index) and # - ImportSource.model()
print(' - {}'.format(analyser.issue(i).description())) print() # STEP 4 # The Validator and Analyser classes process only the contents of concrete items (ie: not the contents of # imported items) of a model. # After successfully resolving a model's imports using an importer, the importer will store instances # of all of the dependencies of the resolved model. These are accessible through the "library" function. # We can ascertain that all of import dependencies meet the diagnostic checks of the Validator and the # Analyser individually by iterating through the importer's library. # Loop through the importer library and call the validator for each model. for m in range(0, importer.libraryCount()): # Retrieve the library model by index, m. validator.validateModel(importer.library(m)) # Retrieve the key under which it's stored: this will be the URL at which the imported model was found. print("The validator found {} issues in {}.".format(validator.issueCount(),importer.key(m))) for i in range(0, validator.issueCount()): print(" - {}".format(validator.issue(i).description())) print() # STEP 5 # Fix the validation errors in the imported files. # According to the printout above, we need to add units to the "iNeedUnits" # variable, to be found inside the "importExample3.cellml" file. # To fix this, we need to fix the model inside the "importExample3.cellml" file. # When the original_model's imports were resolved, this model was added to the # library in the Importer. We can retrieve the model from there for repair.