def resolveMarkupInclusions( src: Union[io.TextIOBase, pathlib.Path], typ: str = None, root: Optional[pathlib.Path] = None, ) -> io.StringIO: """ Process a YAML stream, appropriately handling ``!include`` tags." This will take the passed string or file path, and attempt to parse it as YAML. In the process, any instances of ``!include [path]`` will be replaced with the appropriate contents of the ``!include`` file. Parameters ---------- src : TextIOBase or Path If a Path is provided, read YAML from there. If is stream is provided, consume read text from the stream. If a stream is provided, ``root`` must also be provided. typ : str A valid parse type for the ruamel YAML library. Defaults to "rt" to preserve round-trip data. root : Optional Path The root directory to use for resolving relative paths in !include tags. If a stream is provided for ``src``, ``root`` must be provided. Otherwise, the directory containing the ``src`` path will be used by default. Notes ----- This does a full (albeit not Yamlize) parse of the input YAML into the appropriate data structure, resolving the textual inclusions along the way. Then, the resulting data are re-serialized to a new YAML stream. As such, this is not super efficient. We do it this way because we don't have a whole lot of control over how yamlize handles the parsing. For instance, yamlize will not honor the custom !include tag. This sort of makes sense, as yamlize and YAML tags are two distinct approaches to representing custom objects in YAML. For now, this is not handling cross-document anchors and aliases, which sucks. We may wish to resolve this, but methods to do so are rather complex and not without their own drawbacks. There is some pure gold on that topic here: https://stackoverflow.com/questions/44910886/pyyaml-include-file-and-yaml-aliases-anchors-references """ registerYamlIncludeConstructor() if isinstance(src, pathlib.Path): root = root or src.parent.absolute() else: root = root or pathlib.Path(os.getcwd()).absolute() with directoryChangers.DirectoryChanger(root): yaml = ruamel.yaml.YAML(typ=typ, pure=True) data = yaml.load(src) out = io.StringIO() yaml.dump(data, out) out.seek(0) if isinstance(src, io.TextIOBase): src.seek(0) return out
def setUpClass(cls): # prepare the input files. This is important so the unit tests run from wherever # they need to run from. cls.directoryChanger = directoryChangers.DirectoryChanger( TEST_ROOT, dumpOnException=False ) cls.directoryChanger.open()
def blueprintsHasOldXSInput(path): with directoryChangers.DirectoryChanger(inspector.cs.inputDirectory): with open(os.path.expandvars(path)) as f: for line in f: if line.startswith("cross sections:"): return True return False
def _setGeomType(self): if self.cs["geomFile"]: with directoryChangers.DirectoryChanger(self.cs.inputDirectory): geom = geometry.SystemLayoutInput() geom.readGeomFromFile(self.cs["geomFile"]) self.geomType, self.coreSymmetry = geom.geomType, geom.symmetry
def _setGeomType(self): if self.cs["geomFile"]: with directoryChangers.DirectoryChanger(self.cs.inputDirectory, dumpOnException=False): geom = systemLayoutInput.SystemLayoutInput() geom.readGeomFromFile(self.cs["geomFile"]) self.geomType, self.coreSymmetry = geom.geomType, geom.symmetry
def loadFromCs(cs): """Function to load Geoemtry based on supplied ``CaseSettings``.""" from armi.utils import directoryChangers # circular import protection with directoryChangers.DirectoryChanger(cs.inputDirectory): geom = SystemLayoutInput() geom.readGeomFromFile(cs["geomFile"]) return geom
def setUpClass(cls): cls.cs = settings.Settings() cls.directoryChanger = directoryChangers.DirectoryChanger(TEST_ROOT) cls.directoryChanger.open() y = textProcessors.resolveMarkupInclusions( pathlib.Path(os.getcwd()) / "refSmallReactor.yaml") cls.blueprints = blueprints.Blueprints.load(y) cls.blueprints._prepConstruction(cls.cs)
def setUpClass(cls): cls.cs = settings.Settings() cls.directoryChanger = directoryChangers.DirectoryChanger(TEST_ROOT) cls.directoryChanger.open() isotopicDepletion.applyDefaultBurnChain() with open("refSmallReactor.yaml", "r") as y: cls.blueprints = blueprints.Blueprints.load(y) cls.blueprints._prepConstruction("hex", cls.cs)
def loadFromCs(cls, cs): """Function to load Geoemtry based on supplied ``CaseSettings``.""" if not cs["geomFile"]: return None with directoryChangers.DirectoryChanger(cs.inputDirectory): geom = cls() geom.readGeomFromFile(cs["geomFile"]) return geom
def runTutorialNotebook(): import nbformat from nbconvert.preprocessors import ExecutePreprocessor with directoryChangers.DirectoryChanger(TUTORIAL_DIR): with open("data_model.ipynb") as f: nb = nbformat.read(f, as_version=4) ep = ExecutePreprocessor(timeout=600, kernel_name="python") ep.preprocess(nb, {})
def loadFromCs(cs): """Function to load Geoemtry based on supplied ``CaseSettings``.""" from armi.utils import directoryChangers # pylint: disable=import-outside-toplevel; circular import protection if not cs["geomFile"]: return None with directoryChangers.DirectoryChanger(cs.inputDirectory): geom = SystemLayoutInput() geom.readGeomFromFile(cs["geomFile"]) return geom
def invoke(self): """ Run the entry point """ if self.args.settings_path: path, _fname = os.path.split(self.args.settings_path) with directoryChangers.DirectoryChanger(path, dumpOnException=False): self._migrate(self.args.settings_path, self.args.database_path) else: self._migrate(self.args.settings_path, self.args.database_path)
def test_getFullFileNames(self): with directoryChangers.DirectoryChanger(THIS_DIR): baseCall = pathTools.getFullFileNames() # all variations should return the same values. self.assertEqual(pathTools.getFullFileNames(), pathTools.getFullFileNames(THIS_DIR)) self.assertEqual( pathTools.getFullFileNames(recursive=True), pathTools.getFullFileNames(THIS_DIR, recursive=True), )
def invoke(self): with directoryChangers.DirectoryChanger( self.args.suiteDir, dumpOnException=False ): suite = cases.CaseSuite(self.cs) suite.discover(patterns=self.args.patterns, ignorePatterns=self.args.ignore) if self.args.list: suite.echoConfiguration() else: suite.run()
def _setup_blueprints(self): # need this for the getAllNuclides call with directoryChangers.DirectoryChanger(TEST_ROOT): self.cs["loadingFile"] = "refSmallReactor.yaml" with open(self.cs["loadingFile"], "r") as y: y = textProcessors.resolveMarkupInclusions( y, pathlib.Path(self.cs.inputDirectory)) self.r.blueprints = blueprints.Blueprints.load(y) self.r.blueprints._prepConstruction(self.cs)
def setUpClass(cls): o, r = test_reactors.loadTestReactor() opts = executionOptions.Dif3dOptions("test-output-file") opts.fromUserSettings(o.cs) opts.resolveDerivedOptions() opts.fromReactor(r) with directoryChangers.DirectoryChanger(FIXTURE_DIR): outputReader = outputReaders.Dif3dReader(opts) outputReader.apply(r) cls.r = r
def invoke(self): srcDB = db.databaseFactory(dbName=self.args.srcDB, permission=db.Permissions.READ_ONLY_FME) tarDB = db.databaseFactory(dbName=self.args.tarDB, permission=db.Permissions.CREATE_FILE_TIE) cs = settings.Settings(fName=self.args.csPath) with directoryChangers.DirectoryChanger(cs.inputDirectory): o = armi.init(cs=cs) db.copyDatabase(o.r, srcDB, tarDB)
def setUpClass(cls): runTutorialNotebook() with directoryChangers.DirectoryChanger(TUTORIAL_DIR): reloadCs = settings.Settings(f"{CASE_TITLE}.yaml") reloadCs.caseTitle = "armiRun" reloadCs["db"] = True reloadCs["reloadDBName"] = f"{CASE_TITLE}.h5" reloadCs["runType"] = "Snapshots" reloadCs["loadStyle"] = "fromDB" reloadCs["detailAssemLocationsBOL"] = ["A1001"] o = armi.init(cs=reloadCs) cls.o = o
def invoke(self): with directoryChangers.DirectoryChanger(self.args.suiteDir, dumpOnException=False): suite = cases.CaseSuite(self.cs) suite.discover(patterns=self.args.patterns, ignorePatterns=self.args.ignore) if self.args.list: suite.echoConfiguration() else: for ci, case in enumerate(suite): runLog.important( f"Running case {ci+1}/{len(suite)}: {case}") with directoryChangers.DirectoryChanger(case.directory): settings.setMasterCs(case.cs) case.run()
def loadFromCs(cs): """ Function to load Blueprints based on supplied ``CaseSettings``. """ from armi.utils import directoryChangers # circular import protection with directoryChangers.DirectoryChanger(cs.inputDirectory): with open(cs["loadingFile"], "r") as bpYaml: try: bp = Blueprints.load(bpYaml) except yamlize.yamlizing_error.YamlizingError as err: if "cross sections" in err.args[0]: runLog.error( "The loading file {} contains invalid `cross sections` input. " "Please run the `modify` entry point on this case to automatically convert." "".format(cs["loadingFile"])) raise return bp
def loadFromCs(cs): """ Function to load Blueprints based on supplied ``CaseSettings``. """ # pylint: disable=import-outside-toplevel; circular import protection from armi.utils import directoryChangers with directoryChangers.DirectoryChanger(cs.inputDirectory, dumpOnException=False): with open(cs["loadingFile"], "r") as bpYaml: root = pathlib.Path(cs["loadingFile"]).parent.absolute() bpYaml = textProcessors.resolveMarkupInclusions(bpYaml, root) try: bp = Blueprints.load(bpYaml) except yamlize.yamlizing_error.YamlizingError as err: if "cross sections" in err.args[0]: runLog.error( "The loading file {} contains invalid `cross sections` input. " "Please run the `modify` entry point on this case to automatically convert." "".format(cs["loadingFile"])) raise return bp
def loadFromCs(cs): """ Function to load Blueprints based on supplied ``CaseSettings``. """ # pylint: disable=import-outside-toplevel; circular import protection from armi.utils import directoryChangers textProcessors.registerYamlIncludeConstructor() with directoryChangers.DirectoryChanger(cs.inputDirectory): with open(cs["loadingFile"], "r") as bpYaml: # Make sure that the !include constructor is registered bpYaml = textProcessors.resolveMarkupInclusions(bpYaml) try: bp = Blueprints.load(bpYaml) except yamlize.yamlizing_error.YamlizingError as err: if "cross sections" in err.args[0]: runLog.error( "The loading file {} contains invalid `cross sections` input. " "Please run the `modify` entry point on this case to automatically convert." "".format(cs["loadingFile"])) raise return bp
def createTestXSLibraryFiles(cachePath): r"""This method is used to generate 5 ISOTXS files used during testing. Notes ----- It runs a batch file pointing to the MC**2-v3 executable with MC**2-v3 inputs within the repository, instead of placing the larger binary ISOTXS files within the repository. Also, the _CREATE_ERROR module attribute is used to track whether we have already tried to generate ISOTXS files. Basically, this method can (and should) be called in the setUp/setUpClass of any test that uses the generated ISOTXS files. Therefore, it is possible that for some reason the ISOTXS generation fails, and it would not be worth the time to continually try to recreate the ISOTXS files for each test that uses them, instead just raise the error that occurred the first time. """ cs = settings.Settings() cs["outputCacheLocation"] = cachePath mc2v3 = cs.get("mc2v3.path").default with directoryChangers.DirectoryChanger(RUN_DIR): # the two lines below basically copy the inputs to be used for PMATRX and GAMISO generation. # Since they are inputs to secondary calculations, the inputs need to be created before any # other output is generated. Do not move the two lines below to, for exmaple just before they # are used, otherwise the input to the GAMISO calculation would be younger than the output # DLAYXS, which would cause this the @fixture to determine that targets are out of date. # The result would be that the targets will never be up to date, which defeats the purpose ;-). # IMPORTANT!! these two lines cannot move! copyInputForPmatrxAndGamsio("combine-AA-AB.inp") copyInputForPmatrxAndGamsio("combine-and-lump-AA-AB.inp") # IMPORTANT!! these two lines cannot move! ############################################################ ## ## ## GENERATE DLAYXS ## ## ## ############################################################ outputCache.cacheCall(cs["outputCacheLocation"], mc2v3, ["mc2v3-dlayxs.inp"], ["DLAYXS"]) shutil.move("DLAYXS", DLAYXS_MCC3) ############################################################ ## ## ## GENERATE ISOTXS ## ## ## ############################################################ outputCache.cacheCall( cs["outputCacheLocation"], mc2v3, ["mc2v3-AA.inp"], [ "ISOTXS.merged", "GAMISO.merged", "PMATRX.merged", "output.flux_ufg" ], ) shutil.move("ISOTXS.merged", ISOTXS_AA) shutil.move("GAMISO.merged", GAMISO_AA) shutil.move("PMATRX.merged", PMATRX_AA) shutil.move("output.flux_ufg", UFG_FLUX_EDIT) outputCache.cacheCall( cs["outputCacheLocation"], mc2v3, ["mc2v3-AB.inp"], ["ISOTXS.merged", "GAMISO.merged", "PMATRX.merged"], ) shutil.move("ISOTXS.merged", ISOTXS_AB) shutil.move("GAMISO.merged", GAMISO_AB) shutil.move("PMATRX.merged", PMATRX_AB) # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # :: :: # :: COMBINE :: # :: :: # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: outputCache.cacheCall(cs["outputCacheLocation"], mc2v3, ["combine-AA-AB.inp"], ["ISOTXS.merged"]) shutil.move("ISOTXS.merged", ISOTXS_AA_AB) outputCache.cacheCall( cs["outputCacheLocation"], mc2v3, ["combine-AA-AB.pmatrx.inp"], ["PMATRX.merged"], ) shutil.move("PMATRX.merged", PMATRX_AA_AB) outputCache.cacheCall( cs["outputCacheLocation"], mc2v3, ["combine-AA-AB.gamiso.inp"], ["ISOTXS.merged"], ) shutil.move("ISOTXS.merged", GAMISO_AA_AB) # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # :: :: # :: COMBINE AND LUMP :: # :: :: # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: subprocess.call([mc2v3, "combine-and-lump-AA-AB.inp"]) shutil.move("ISOTXS.merged", ISOTXS_LUMPED) subprocess.call([mc2v3, "combine-and-lump-AA-AB.pmatrx.inp"]) shutil.move("PMATRX.merged", PMATRX_LUMPED) subprocess.call([mc2v3, "combine-and-lump-AA-AB.gamiso.inp"]) shutil.move("ISOTXS.merged", GAMISO_LUMPED)
def setUpClass(cls): cls.directoryChanger = directoryChangers.DirectoryChanger( os.path.join(TEST_ROOT, "tutorials")) cls.directoryChanger.open()
def test_change_to_nonexisting_fails(self): """Fail if destination doesn't exist.""" with self.assertRaises(OSError): with directoryChangers.DirectoryChanger(self.temp_directory): pass
def fuelHandlerFactory(operator): """ Return an instantiated FuelHandler object based on user settings. The FuelHandler is expected to be a short-lived object that only lives for the cycle upon which it acts. At the next cycle, this factory will be called again to instantiate a new FuelHandler. """ cs = operator.cs fuelHandlerClassName = cs["fuelHandlerName"] fuelHandlerModulePath = cs["shuffleLogic"] if not fuelHandlerClassName: # User did not request a custom fuel handler. # This is code coupling that should be untangled. # Special case for equilibrium-mode shuffling if cs["eqDirect"] and cs["runType"].lower() == RunTypes.STANDARD.lower(): from terrapower.physics.neutronics.equilibrium import fuelHandler as efh return efh.EqDirectFuelHandler(operator) else: # give the default FuelHandler. This does not have an implemented outage, but # still offers moving capabilities. Useful when you just need to make explicit # moves but do not have a fully-defined fuel management input. return fuelHandlers.FuelHandler(operator) # User did request a custom fuel handler. We must go find and import it # from the input directory. with directoryChangers.DirectoryChanger(cs.inputDirectory, dumpOnException=False): try: module = pathTools.importCustomPyModule(fuelHandlerModulePath) if not hasattr(module, fuelHandlerClassName): raise KeyError( "The requested fuel handler object {0} is not " "found in the fuel management input file {1} from CWD {2}. " "Check input" "".format( fuelHandlerClassName, fuelHandlerModulePath, cs.inputDirectory ) ) # instantiate the custom object fuelHandlerCls = getattr(module, fuelHandlerClassName) fuelHandler = fuelHandlerCls(operator) # also get getFactorList function from module level if it's there. # This is a legacy input option, getFactorList should now generally # be an method of the FuelHandler object if hasattr(module, "getFactorList"): # staticmethod binds the provided getFactorList function to the # fuelHandler object without passing the implicit self argument. # The __get__ pulls the actual function out from the descriptor. fuelHandler.getFactorList = staticmethod(module.getFactorList).__get__( fuelHandlerCls ) except IOError: raise ValueError( "Either the file specified in the `shuffleLogic` setting ({}) or the " "fuel handler class name specified in the `fuelHandlerName` setting ({}) " "cannot be found. CWD is: {}. Update input.".format( fuelHandlerModulePath, fuelHandlerClassName, cs.inputDirectory ) ) return fuelHandler