Example #1
0
    def __setstate__(self, state):
        """
        Rebuild schema upon unpickling since schema is unpickleable.

        Pickling happens during mpi broadcasts and also
        during testing where the test reactor is cached.

        See Also
        --------
        armi.settings.setting.Setting.__getstate__ : removes schema
        """
        from armi import getApp  # pylint: disable=import-outside-toplevel

        self.__settings = getApp().getSettings()

        # restore non-setting instance attrs
        for key, val in state.items():
            if key != "_Settings__settings":
                setattr(self, key, val)

        # with schema restored, restore all setting values
        for name, settingState in state["_Settings__settings"].items():
            # pylint: disable=protected-access
            if name in self.__settings:
                self.__settings[name]._value = settingState.value
            elif isinstance(settingState, Setting):
                self.__settings[name] = copy(settingState)
            else:
                raise NonexistentSetting(name)
Example #2
0
    def _directAccessOfSettingAllowed(self, key):
        """
        A way to check if specific settings can be grabbed out of the case settings.

        Could be updated with other specific instances as necessary.

        Notes
        -----
        Checking the validity of grabbing specific settings at this point,
        as is done for the SIMPLE_CYCLES_INPUT's, feels
        a bit intrusive and out of place. In particular, the fact that the check
        is done every time that a setting is reached for, no matter if it is the
        setting in question, is quite clunky. In the future, it would be desirable
        if the settings system were more flexible to control this type of thing
        at a deeper level.
        """
        if key not in self.__settings:
            return False, NonexistentSetting(key)

        if key in SIMPLE_CYCLES_INPUTS and self.__settings[
                "cycles"].value != []:
            err = ValueError(
                "Cannot grab simple cycles information from the case settings"
                " when detailed cycles information is also entered.\n In general"
                " cycles information should be pulled off the operator or parsed"
                " using the appropriate getter in the utils.")

            return False, err

        return True, None
Example #3
0
    def getSetting(self, key, default=None):
        """
        Return a copy of an actual Setting object, instead of just its value.

        NOTE: This is used very rarely, try to organize your code to only need a Setting value.
        """
        if key in self.__settings:
            return copy(self.__settings[key])
        elif default is not None:
            return default
        else:
            raise NonexistentSetting(key)
Example #4
0
File: case.py Project: ntouran/armi
def copyInterfaceInputs(cs,
                        destination: str,
                        sourceDir: Optional[str] = None) -> Dict[str, str]:
    """
    Copy sets of files that are considered "input" from each active interface.

    This enables developers to add new inputs in a plugin-dependent/ modular way.

    In parameter sweeps, these often have a sourceDir associated with them that is
    different from the cs.inputDirectory.

    Parameters
    ----------
    cs : CaseSettings
        The source case settings to find input files

    destination: str
        The target directory to copy input files to

    sourceDir: str, optional
        The directory from which to copy files. Defaults to cs.inputDirectory

    Notes
    -----

    This may seem a bit overly complex, but a lot of the behavior is important. Relative
    paths are copied into the target directory, which in some cases requires updating
    the setting that pointed to the file in the first place. This is necessary to avoid
    case dependencies in relavive locations above the input directory, which can lead to
    issues when cloneing case suites. In the future this could be simplified by adding a
    concept for a suite root directory, below which it is safe to copy files without
    needing to update settings that point with a relative path to files that are below
    it.

    """
    activeInterfaces = interfaces.getActiveInterfaceInfo(cs)
    sourceDir = sourceDir or cs.inputDirectory
    sourceDirPath = pathlib.Path(sourceDir)
    destPath = pathlib.Path(destination)

    newSettings = {}

    assert destPath.is_dir()

    for klass, _ in activeInterfaces:
        interfaceFileNames = klass.specifyInputs(cs)
        # returned files can be absolute paths, relative paths, or even glob patterns.
        # Since we don't have an explicit way to signal about these, we sort of have to
        # guess. In future, it might be nice to have interfaces specify which
        # explicitly.
        for key, files in interfaceFileNames.items():

            if not isinstance(key, settings.Setting):
                try:
                    key = cs.getSetting(key)
                except NonexistentSetting(key):
                    raise ValueError(
                        "{} is not a valid setting. Ensure the relevant specifyInputs method uses a correct setting name."
                        .format(key))
            label = key.name

            for f in files:
                path = pathlib.Path(f)
                if path.is_absolute() and path.exists() and path.is_file():
                    # looks like an extant, absolute path; no need to do anything
                    pass
                else:
                    # An OSError can occur if a wildcard is included in the file name so
                    # this is wrapped in a try/except to circumvent instances where an
                    # interface requests to copy multiple files based on some prefix/suffix.
                    try:
                        if not (path.exists() and path.is_file()):
                            runLog.extra(
                                f"Input file `{f}` not found. Checking for file at path `{sourceDirPath}`"
                            )
                    except OSError:
                        pass

                    # relative path/glob. Should be safe to just use glob resolution.
                    # Note that `glob.glob` is being used here rather than `pathlib.glob` because
                    # `pathlib.glob` for Python 3.7.2 does not handle case sensitivity for file and
                    # path names. This is required for copying and using Python scripts (e.g., fuel management,
                    # control logic, etc.).
                    srcFiles = [
                        pathlib.Path(os.path.join(sourceDirPath, g))
                        for g in glob.glob(os.path.join(sourceDirPath, f))
                    ]
                    for sourceFullPath in srcFiles:
                        if not sourceFullPath:
                            continue
                        sourceName = os.path.basename(sourceFullPath.name)
                        destFilePath = os.path.abspath(destPath / sourceName)
                        pathTools.copyOrWarn(label, sourceFullPath,
                                             destFilePath)
                    if len(srcFiles) == 0:
                        runLog.warning(
                            f"No input files for `{label}` could be resolved "
                            f"with the following file path: `{f}`.")
                    elif len(srcFiles) > 1:
                        runLog.warning(
                            f"Input files for `{label}` resolved to more "
                            f"than one file; cannot update settings safely. "
                            f"Discovered input files: {srcFiles}")
                    elif len(srcFiles) == 1:
                        newSettings[label] = str(destFilePath)

    return newSettings
Example #5
0
 def __setitem__(self, key, val):
     # TODO: This potentially allows for invisible settings mutations and should be removed.
     if key in self.__settings:
         self.__settings[key].setValue(val)
     else:
         raise NonexistentSetting(key)
Example #6
0
 def __getitem__(self, key):
     if key in self.__settings:
         return self.__settings[key].value
     else:
         raise NonexistentSetting(key)