Skip to content

whl2conda.settings

Settings for whl2conda.

Internally, the settings are accessed through the settings global variable, which is an instance of Whl2CondaSettings

The settings are loaded from a persistent JSON file, whose default location depends on the operating system, e.g.:

OS Path
Windows ~/AppData/Local/whl2conda/whl2conda/settings.json
Linux ~/.config/whl2conda/settings.json
MacOS ~/Library/Application Support/whl2conda/settings.json

The location of the settings file may also be overridden by --settings command line argument to whl2conda.

Use the settings_file attribute to get the path used to load a given settings object.

Settings may be viewed and modified at the command line using whl2conda config.

Attributes

settings module-attribute

settings = from_file()

User settings.

Classes

Whl2CondaSettings dataclass

User settings for whl2conda.

These are accessed through the global settings variable.

The following settings are currently supported:

Source code in src/whl2conda/settings.py
@dataclasses.dataclass(kw_only=True)
class Whl2CondaSettings:
    """
    User settings for whl2conda.

    These are accessed through the global [settings][(m).] variable.

    The following settings are currently supported:

    * [auto_update_std_renames][.] - whether to automatically update std rename mappings
    * [conda_format][.] - default output conda package format
    * [pypi_indexes][.] - table of known extra pypi indexes

    """

    SETTINGS_FILENAME: ClassVar[str] = "settings.json"
    """Default base filename for saved settings."""

    DEFAULT_SETTINGS_FILE: ClassVar[Path] = (
        user_config_path("whl2conda") / SETTINGS_FILENAME
    )
    """Default filepath for saved settings."""

    # TODO:
    #   - difftool
    #   - pyproject defaults

    auto_update_std_renames: _BoolField = _BoolField()
    """
    Whether to automatically update the standard renames for operations
    that need them. Default is false.
    """

    conda_format: _CondaPackageFormatField = _CondaPackageFormatField()
    """
    The default output conda package format if not specified. Default is V2.
    """

    pypi_indexes: _SettingsField = _SettingsField(default=dict)
    """
    Dictionary of aliases for pypi package indexes from which wheels can be
    downloaded. Default is empty.
    """

    #
    # Internal attributes
    #

    _settings_file: Path = dataclasses.field(
        default=DEFAULT_SETTINGS_FILE, compare=False
    )
    """
    Location of underlying settings file.
    """

    _fieldnames: ClassVar[frozenset[str]] = frozenset()
    """
    Set of public field names.
    """

    @property
    def settings_file(self) -> Path:
        """
        Settings file for this settings object.

        Set from [from_file][..] constructor or else will be
        [DEFAULT_SETTINGS_FILE][(c).].
        """
        return self._settings_file

    #
    # Settings access/modification methods
    #

    def to_dict(self) -> dict[str, Any]:
        """
        Return dictionary containing public settings data.
        """
        return {
            k: v for k, v in dataclasses.asdict(self).items() if not k.startswith("_")
        }

    def get(self, key: str) -> Any:
        """
        Get a value from the settings by string key.

        The key may either be just the field name (e.g. 'conda-format')
        or can refer to am entry within dictionary-valued field
        (e.g. 'pypi-indexes.acme'). Note that the dashes in the first
        component of the key will be converted to underscores.
        """
        name, subkey = self._split_key(key)
        value = getattr(self, name)

        if subkey:
            if not isinstance(value, dict):
                raise KeyError(
                    f"Bad settings key '{key}': '{name}' is not a dictionary"
                )
            if subkey not in value:
                raise KeyError(f"'{key}' is not set'")
            value = value[subkey]

        return value

    def set(self, key: str, value: Any) -> None:
        """
        Set a value in the settings by string key.

        See [get][..] for details on key format.

        This does not save the settings file.
        """
        name, subkey = self._split_key(key)

        if not subkey:
            setattr(self, name, value)

        else:
            d = getattr(self, name)
            if not isinstance(d, dict):
                raise KeyError(
                    f"Bad settings key '{key}': '{name}' is not a dictionary"
                )
            d[subkey] = value

    def unset(self, key: str) -> None:
        """
        Unset attribute with given key.

        The setting will revert to its original value.

        See [get][..] for details on key format.

        This does not save the settings file.
        """
        name, subkey = self._split_key(key)

        if not subkey:
            delattr(self, name)

        else:
            d = getattr(self, name)
            if not isinstance(d, dict):
                raise KeyError(
                    f"Bad settings key '{key}': '{name}' is not a dictionary"
                )
            try:
                del d[subkey]
            except KeyError:
                pass

    def unset_all(self) -> None:
        """
        Unset all settings, and revert to default values.
        """
        for k in self._fieldnames:
            self.unset(k)

    #
    # File operations
    #

    @classmethod
    def from_file(cls, filename: Path | str = "") -> Whl2CondaSettings:
        """
        Return settings read from file.

        Arguments:
            filename: relative path to settings file (may start with '~')
                defaults to [DEFAULT_SETTINGS_FILE][(c).] if not specified.
        """
        settings = cls()
        settings.load(filename or cls.DEFAULT_SETTINGS_FILE)
        return settings

    def load(self, filename: Path | str, reset_all: bool = False) -> None:
        """
        Reload settings from file

        Args:
            filename: relative path to settings file (may start with '~')
            reset_all: if True, then all settings will be unset and reverted
                to default value prior to loading.
        """
        filepath = Path(Path(filename).expanduser())
        self._settings_file = filepath
        if reset_all:
            self.unset_all()
        if filepath.exists():
            contents = filepath.read_text("utf8")
            json_obj = json.loads(contents)
            for k, v in json_obj.items():
                if k in self._fieldnames:
                    try:
                        setattr(self, k, v)
                    except Exception as ex:
                        print(
                            f"Cannot read '{k}' from '{filepath}': {ex}",
                            file=sys.stderr,
                        )

    def save(self, filename: Path | str = "") -> None:
        """
        Write settings to specified file in JSON format.

        Args:
            filename: file to write. Defaults to [settings_file][..]
        """
        filepath = Path(filename or self._settings_file)
        json_obj = self.to_dict()
        json_obj["$whl2conda-version"] = __version__
        json_obj["$created"] = str(dt.datetime.now(tz=dt.timezone.utc))
        filepath.parent.mkdir(parents=True, exist_ok=True)
        filepath.write_text(json.dumps(json_obj, indent=2))

    #
    # Internal methods
    #

    def _split_key(self, key: str) -> tuple[str, str]:
        parts = key.split(".", maxsplit=1)
        name = _toidentifier(parts[0])
        if name not in self._fieldnames:
            raise KeyError(f"Unknown settings key '{key}'")
        return name, parts[1] if len(parts) > 1 else ""

Attributes

DEFAULT_SETTINGS_FILE class-attribute
DEFAULT_SETTINGS_FILE: Path = (
    user_config_path("whl2conda") / SETTINGS_FILENAME
)

Default filepath for saved settings.

SETTINGS_FILENAME class-attribute
SETTINGS_FILENAME: str = 'settings.json'

Default base filename for saved settings.

auto_update_std_renames class-attribute instance-attribute
auto_update_std_renames: _BoolField = _BoolField()

Whether to automatically update the standard renames for operations that need them. Default is false.

conda_format class-attribute instance-attribute
conda_format: _CondaPackageFormatField = (
    _CondaPackageFormatField()
)

The default output conda package format if not specified. Default is V2.

pypi_indexes class-attribute instance-attribute
pypi_indexes: _SettingsField = _SettingsField(default=dict)

Dictionary of aliases for pypi package indexes from which wheels can be downloaded. Default is empty.

settings_file property
settings_file: Path

Settings file for this settings object.

Set from from_file constructor or else will be DEFAULT_SETTINGS_FILE.

Functions

from_file classmethod
from_file(filename: Path | str = '') -> Whl2CondaSettings

Return settings read from file.

PARAMETER DESCRIPTION
filename

relative path to settings file (may start with '~') defaults to DEFAULT_SETTINGS_FILE if not specified.

TYPE: Path | str DEFAULT: ''

Source code in src/whl2conda/settings.py
@classmethod
def from_file(cls, filename: Path | str = "") -> Whl2CondaSettings:
    """
    Return settings read from file.

    Arguments:
        filename: relative path to settings file (may start with '~')
            defaults to [DEFAULT_SETTINGS_FILE][(c).] if not specified.
    """
    settings = cls()
    settings.load(filename or cls.DEFAULT_SETTINGS_FILE)
    return settings
get
get(key: str) -> Any

Get a value from the settings by string key.

The key may either be just the field name (e.g. 'conda-format') or can refer to am entry within dictionary-valued field (e.g. 'pypi-indexes.acme'). Note that the dashes in the first component of the key will be converted to underscores.

Source code in src/whl2conda/settings.py
def get(self, key: str) -> Any:
    """
    Get a value from the settings by string key.

    The key may either be just the field name (e.g. 'conda-format')
    or can refer to am entry within dictionary-valued field
    (e.g. 'pypi-indexes.acme'). Note that the dashes in the first
    component of the key will be converted to underscores.
    """
    name, subkey = self._split_key(key)
    value = getattr(self, name)

    if subkey:
        if not isinstance(value, dict):
            raise KeyError(
                f"Bad settings key '{key}': '{name}' is not a dictionary"
            )
        if subkey not in value:
            raise KeyError(f"'{key}' is not set'")
        value = value[subkey]

    return value
load
load(filename: Path | str, reset_all: bool = False) -> None

Reload settings from file

PARAMETER DESCRIPTION
filename

relative path to settings file (may start with '~')

TYPE: Path | str

reset_all

if True, then all settings will be unset and reverted to default value prior to loading.

TYPE: bool DEFAULT: False

Source code in src/whl2conda/settings.py
def load(self, filename: Path | str, reset_all: bool = False) -> None:
    """
    Reload settings from file

    Args:
        filename: relative path to settings file (may start with '~')
        reset_all: if True, then all settings will be unset and reverted
            to default value prior to loading.
    """
    filepath = Path(Path(filename).expanduser())
    self._settings_file = filepath
    if reset_all:
        self.unset_all()
    if filepath.exists():
        contents = filepath.read_text("utf8")
        json_obj = json.loads(contents)
        for k, v in json_obj.items():
            if k in self._fieldnames:
                try:
                    setattr(self, k, v)
                except Exception as ex:
                    print(
                        f"Cannot read '{k}' from '{filepath}': {ex}",
                        file=sys.stderr,
                    )
save
save(filename: Path | str = '') -> None

Write settings to specified file in JSON format.

PARAMETER DESCRIPTION
filename

file to write. Defaults to settings_file

TYPE: Path | str DEFAULT: ''

Source code in src/whl2conda/settings.py
def save(self, filename: Path | str = "") -> None:
    """
    Write settings to specified file in JSON format.

    Args:
        filename: file to write. Defaults to [settings_file][..]
    """
    filepath = Path(filename or self._settings_file)
    json_obj = self.to_dict()
    json_obj["$whl2conda-version"] = __version__
    json_obj["$created"] = str(dt.datetime.now(tz=dt.timezone.utc))
    filepath.parent.mkdir(parents=True, exist_ok=True)
    filepath.write_text(json.dumps(json_obj, indent=2))
set
set(key: str, value: Any) -> None

Set a value in the settings by string key.

See get for details on key format.

This does not save the settings file.

Source code in src/whl2conda/settings.py
def set(self, key: str, value: Any) -> None:
    """
    Set a value in the settings by string key.

    See [get][..] for details on key format.

    This does not save the settings file.
    """
    name, subkey = self._split_key(key)

    if not subkey:
        setattr(self, name, value)

    else:
        d = getattr(self, name)
        if not isinstance(d, dict):
            raise KeyError(
                f"Bad settings key '{key}': '{name}' is not a dictionary"
            )
        d[subkey] = value
to_dict
to_dict() -> dict[str, Any]

Return dictionary containing public settings data.

Source code in src/whl2conda/settings.py
def to_dict(self) -> dict[str, Any]:
    """
    Return dictionary containing public settings data.
    """
    return {
        k: v for k, v in dataclasses.asdict(self).items() if not k.startswith("_")
    }
unset
unset(key: str) -> None

Unset attribute with given key.

The setting will revert to its original value.

See get for details on key format.

This does not save the settings file.

Source code in src/whl2conda/settings.py
def unset(self, key: str) -> None:
    """
    Unset attribute with given key.

    The setting will revert to its original value.

    See [get][..] for details on key format.

    This does not save the settings file.
    """
    name, subkey = self._split_key(key)

    if not subkey:
        delattr(self, name)

    else:
        d = getattr(self, name)
        if not isinstance(d, dict):
            raise KeyError(
                f"Bad settings key '{key}': '{name}' is not a dictionary"
            )
        try:
            del d[subkey]
        except KeyError:
            pass
unset_all
unset_all() -> None

Unset all settings, and revert to default values.

Source code in src/whl2conda/settings.py
def unset_all(self) -> None:
    """
    Unset all settings, and revert to default values.
    """
    for k in self._fieldnames:
        self.unset(k)