def run(self): """ Run the executer steps. .. warning:: If a calculation requires anything different from what this method does, do not update this method with new complexity! Instead, simply make your own run sequence and/or class. This pattern is useful only in that it is fairly simple. By all means, do use ``DirectoryChanger`` and ``ExecuterOptions`` and other utilities. """ self.options.resolveDerivedOptions() runLog.debug(self.options.describe()) if self.options.executablePath and not os.path.exists( self.options.executablePath): raise IOError( f"Required executable `{self.options.executablePath}` not found for {self}" ) self._performGeometryTransformations() inputs, outputs = self._collectInputsAndOutputs() # must either write input to CWD for analysis and then copy to runDir # or not list it in inputs (for optimization) self.writeInput() with directoryChangers.ForcedCreationDirectoryChanger( self.options.runDir, filesToMove=inputs, filesToRetrieve=outputs) as dc: self.options.workingDir = dc.initial self._execute() output = self._readOutput() if self.options.applyResultsToReactor: output.apply(self.r) self._undoGeometryTransformations() return output
def createReportFromSettings(cs): """ Create BEGINNING reports, given a settings file. This will construct a reactor from the given settings and create BOL reports for that reactor/settings. """ # not sure if this is necessary, but need to investigate more to understand possible # side-effects before removing. Probably better to get rid of all uses of # getMasterCs(), then we can remove all setMasterCs() calls without worrying. settings.setMasterCs(cs) blueprint = blueprints.loadFromCs(cs) r = reactors.factory(cs, blueprint) report = reports.ReportContent("Overview") pm = getPluginManagerOrFail() report.title = r.name with directoryChangers.ForcedCreationDirectoryChanger("{}-reports".format( cs.caseTitle)): _ = pm.hook.getReportContents( r=r, cs=cs, report=report, stage=reports.ReportStage.Begin, blueprint=blueprint, ) site = report.writeReports() return site
def test_exception(self): """Make sure directory changers bring back full folder when an exception is raised.""" try: with directoryChangers.ForcedCreationDirectoryChanger(self.temp_directory): Path("file1.txt").touch() Path("file2.txt").touch() raise TestException("Ooops") except TestException: pass retrievedFolder = f"dump-{self.temp_directory}" self.assertTrue(os.path.exists(os.path.join(retrievedFolder, "file1.txt"))) self.assertTrue(os.path.exists(os.path.join(retrievedFolder, "file2.txt"))) shutil.rmtree(retrievedFolder)
def test_exception_disabled(self): """Make sure directory changers do not bring back full folder when handling is disabled.""" try: with directoryChangers.ForcedCreationDirectoryChanger( self.temp_directory, dumpOnException=False): Path("file1.txt").touch() Path("file2.txt").touch() raise ExpectedException("Ooops") except ExpectedException: pass self.assertFalse( os.path.exists( os.path.join(f"dump-{self.temp_directory}", "file1.txt")))
def run(self): """Perform DRAGON calculation for the current input file.""" runLog.important( "Preparing to run DRAGON with executable: " f"{self.options.executablePath}, on input: {self.options.inputFile}" ) self.writeInput() inputs, outputs = self._collectIONames() with directoryChangers.ForcedCreationDirectoryChanger( self.options.runDir, filesToMove=inputs, filesToRetrieve=outputs, ): self._execute()
def clone(self, oldRoot=None): """ Clone a CaseSuite to a new place. Creates a clone for each case within a CaseSuite. If ``oldRoot`` is not specified, then each case clone is made in a directory with the title of the case. If ``oldRoot`` is specified, then a relative path from ``oldRoot`` will be used to determine a new relative path to the current directory ``oldRoot``. Parameters ---------- oldRoot : str (optional) root directory of original case suite used to help filter when a suite contains one or more cases with the same case title. Notes ----- By design, a CaseSuite has no location dependence; this allows any set of cases to compose a CaseSuite. The thought is that the post-analysis capabilities without restricting a root directory could be beneficial. For example, this allows one to perform analysis on cases analyzed by Person A and Person B, even if the analyses were performed in completely different locations. As a consequence, when you want to clone, we need to infer a "root" of the original cases to attempt to mirror whatever existing directory structure there may have been. """ clone = CaseSuite(self.cs.duplicate()) modifiedSettings = { ss.name: ss.value for ss in self.cs.settings.values() if ss.offDefault } for case in self: if oldRoot: newDir = os.path.dirname(os.path.relpath( case.cs.path, oldRoot)) else: newDir = case.title with directoryChangers.ForcedCreationDirectoryChanger( newDir, clean=True, dumpOnException=False): clone.add(case.clone(modifiedSettings=modifiedSettings)) return clone
def writeReports(self): """Renders each report into a document for viewing.""" with directoryChangers.ForcedCreationDirectoryChanger("reports"): for report_ in self.reports: report_.writeHTML()
def test_change_to_nonexisting_works_forced(self): """Succeed with forced creation even when destination doesn't exist.""" with directoryChangers.ForcedCreationDirectoryChanger(self.temp_directory): pass
def invoke(self): nodes = self.args.nodes if self.args.h5db is None: # Just do begining stuff, no database is given... if self.cs is not None: site = createReportFromSettings(cs) if self.args.view: webbrowser.open(site) else: raise RuntimeError( "No Settings with Blueprint or Database, cannot gerenate a report" ) else: report = reports.ReportContent("Overview") pm = getPluginManagerOrFail() db = databaseFactory(self.args.h5db, "r") if self.args.bp is not None: blueprint = self.args.bp with db: with directoryChangers.ForcedCreationDirectoryChanger( "reportsOutputFiles"): dbNodes = list(db.genTimeSteps()) cs = db.loadCS() if self.args.bp is None: blueprint = db.loadBlueprints() r = reactors.factory(cs, blueprint) report.title = r.name pluginContent = getPluginManagerOrFail( ).hook.getReportContents( r=r, cs=cs, report=report, stage=reports.ReportStage.Begin, blueprint=blueprint, ) stage = reports.ReportStage.Standard for cycle, node in dbNodes: if nodes is not None and (cycle, node) not in nodes: continue if (self.args.min_node is not None and (cycle, node) < self.args.min_node): continue if (self.args.max_node is not None and (cycle, node) > self.args.max_node): continue r = db.load(cycle, node) cs = db.loadCS() pluginContent = pm.hook.getReportContents( r=r, cs=cs, report=report, stage=stage, blueprint=blueprint) stage = reports.ReportStage.End pluginContent = pm.hook.getReportContents( r=r, cs=cs, report=report, stage=stage, blueprint=blueprint) site = report.writeReports() if self.args.view: webbrowser.open(site)