Skip to content

configparser

Base module for pyRevit config parsing.

Classes

ConfigSection(section_name, configuration)

Bases: object

Read/write access to the options of a single config section.

Options can be accessed either as attributes (section.option) or through the explicit get_option/set_option methods. Values are stored as JSON and decoded tolerantly on read.

Parameters:

Name Type Description Default
section_name str

canonical name of the section

required
configuration

the backing IConfiguration, or a zero-argument callable returning it. A callable keeps a section usable after the backing store is replaced, so a section handed to a script does not become an orphan that silently discards its edits.

required
Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def __init__(self, section_name, configuration):
    self.__section_name = section_name
    self.__configuration_source = configuration

Attributes

header property

str: Full canonical name of this section.

subheader property

str: Last component of the section's canonical name.

Methods:

has_option(option_name)

Check if this section contains the given option.

Parameters:

Name Type Description Default
option_name str

name of the option

required

Returns:

Type Description
bool

whether the option exists

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def has_option(self, option_name):
    """Check if this section contains the given option.

    Args:
        option_name (str): name of the option

    Returns:
        (bool): whether the option exists
    """
    return self.__config().HasSectionKey(self.__section_name, option_name)
get_option(op_name, default_value=None)

Get the value of an option, decoding it tolerantly.

A missing key returns default_value; an explicitly stored empty string is treated as a real value. Values that are not valid JSON (legacy single-quoted strings, Python bools, bare paths) are decoded tolerantly rather than raising.

Parameters:

Name Type Description Default
op_name str

name of the option

required
default_value

value to return when the option is not set

None

Returns:

Type Description

the decoded option value, or default_value when unset

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def get_option(self, op_name, default_value=None):
    """Get the value of an option, decoding it tolerantly.

    A missing key returns ``default_value``; an explicitly stored empty
    string is treated as a real value. Values that are not valid JSON
    (legacy single-quoted strings, Python bools, bare paths) are decoded
    tolerantly rather than raising.

    Args:
        op_name (str): name of the option
        default_value: value to return when the option is not set

    Returns:
        the decoded option value, or ``default_value`` when unset
    """
    value = self.__config().GetRawValueOrDefault(self.__section_name, op_name, None)
    if value is None:
        return default_value
    return decode_option_value(value)
set_option(op_name, value)

Set the value of an option, encoding it as JSON.

Parameters:

Name Type Description Default
op_name str

name of the option

required
value

value to store

required
Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def set_option(self, op_name, value):
    """Set the value of an option, encoding it as JSON.

    Args:
        op_name (str): name of the option
        value: value to store
    """
    self.__config().SetRawValue(
        self.__section_name,
        op_name,
        json.dumps(value, separators=(",", ":"), ensure_ascii=False),
    )
remove_option(option_name)

Remove an option from this section.

Parameters:

Name Type Description Default
option_name str

name of the option

required

Returns:

Type Description
bool

whether an option was removed

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def remove_option(self, option_name):
    """Remove an option from this section.

    Args:
        option_name (str): name of the option

    Returns:
        (bool): whether an option was removed
    """
    return self.__config().RemoveOption(self.__section_name, option_name)
has_subsection(section_name)

Check if section has any subsections.

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def has_subsection(self, section_name):
    """Check if section has any subsections."""
    return True if self.get_subsection(section_name) else False
add_subsection(section_name)

Add subsection to section.

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def add_subsection(self, section_name):
    """Add subsection to section."""
    canonical_name = coreutils.make_canonical_name(
        self.__section_name, section_name
    )
    self.__config().AddSection(canonical_name)
    return ConfigSection(canonical_name, self.__configuration_source)
get_subsections()

Return all subsections nested under this section.

Returns:

Type Description
list[ConfigSection]

the nested subsections

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def get_subsections(self):
    """Return all subsections nested under this section.

    Returns:
        (list[ConfigSection]): the nested subsections
    """
    subsections = []
    for section_name in self.__config().GetSectionNames():
        if section_name.startswith(self.__section_name + "."):
            subsec = ConfigSection(section_name, self.__configuration_source)
            subsections.append(subsec)
    return subsections
get_subsection(section_name)

Return the named subsection nested under this section.

Parameters:

Name Type Description Default
section_name str

short name of the subsection

required

Returns:

Type Description
ConfigSection

the subsection, or None if not found

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def get_subsection(self, section_name):
    """Return the named subsection nested under this section.

    Args:
        section_name (str): short name of the subsection

    Returns:
        (ConfigSection): the subsection, or None if not found
    """
    for subsection in self.get_subsections():
        if subsection.subheader == section_name:
            return subsection
    return None

ConfigSections(configuration_service)

Bases: object

Access the sections of the default configuration.

Sections can be reached either as attributes (sections.core) or through the explicit section methods. Iterating yields section names.

Parameters:

Name Type Description Default
configuration_service

the backing IConfigurationService, or a zero-argument callable returning it. A callable lets the container and every section it has already handed out follow a reload that replaces the service.

required
Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def __init__(self, configuration_service):
    self.__service_source = configuration_service

Methods:

has_section(section_name)

Check if the config contains the given section.

Parameters:

Name Type Description Default
section_name str

name of the section

required

Returns:

Type Description
bool

whether the section exists

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def has_section(self, section_name):
    """Check if the config contains the given section.

    Args:
        section_name (str): name of the section

    Returns:
        (bool): whether the section exists
    """
    return self.__get_default_config().HasSection(section_name)
add_section(section_name)

Add a new section to the config.

Parameters:

Name Type Description Default
section_name str

name of the section

required

Returns:

Type Description
ConfigSection

the added section

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def add_section(self, section_name):
    """Add a new section to the config.

    Args:
        section_name (str): name of the section

    Returns:
        (ConfigSection): the added section
    """
    self.__get_default_config().AddSection(section_name)
    return ConfigSection(section_name, self.__get_default_config)
get_section(section_name)

Get the named config section.

Parameters:

Name Type Description Default
section_name str

name of the section

required

Returns:

Type Description
ConfigSection

the requested section

Raises:

Type Description
AttributeError

if the section does not exist

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def get_section(self, section_name):
    """Get the named config section.

    Args:
        section_name (str): name of the section

    Returns:
        (ConfigSection): the requested section

    Raises:
        AttributeError: if the section does not exist
    """
    if not self.__get_default_config().HasSection(section_name):
        raise AttributeError(
            'Section "{}" does not exist in config file.'.format(section_name)
        )
    return ConfigSection(section_name, self.__get_default_config)
remove_section(section_name)

Remove the named section, and its subsections, from the config.

Subsections are stored as sibling sections under a dotted name rather than nested inside their parent, so they must be found and removed explicitly here - dropping the parent alone would leave them behind for a reinstall to silently inherit.

Parameters:

Name Type Description Default
section_name str

name of the section

required
Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def remove_section(self, section_name):
    """Remove the named section, and its subsections, from the config.

    Subsections are stored as sibling sections under a dotted name rather
    than nested inside their parent, so they must be found and removed
    explicitly here - dropping the parent alone would leave them behind
    for a reinstall to silently inherit.

    Args:
        section_name (str): name of the section
    """
    config = self.__get_default_config()
    subsection_prefix = section_name + "."
    for existing_name in list(config.GetSectionNames()):
        if existing_name.startswith(subsection_prefix):
            config.RemoveSection(existing_name)

    config.RemoveSection(section_name)
save()

Write pending changes to the backing file.

Option writes land in the in-memory store only, so a caller that edits a config must call this for the change to survive the session.

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def save(self):
    """Write pending changes to the backing file.

    Option writes land in the in-memory store only, so a caller that edits
    a config must call this for the change to survive the session.
    """
    self.__get_default_config().SaveConfiguration()

Functions:

decode_option_value(raw_value)

Decode a stored option value across every encoding pyRevit has written.

Falls through, in order: the JSON candidates in :func:_json_candidates; a bare unquoted Python bool (True/False, case-insensitive - a string that merely spells "True" is stored quoted and already decoded by the JSON pass); a bare hex integer (e.g. 0x0, which JSON's number grammar rejects). Matching the C# reader's fallback order here is what keeps the two readers agreeing on the same stored value.

Parameters:

Name Type Description Default
raw_value str

stored value text

required

Returns:

Type Description

the decoded value, or the raw text when no encoding accounts for it

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def decode_option_value(raw_value):
    """Decode a stored option value across every encoding pyRevit has written.

    Falls through, in order: the JSON candidates in :func:`_json_candidates`;
    a bare unquoted Python bool (``True``/``False``, case-insensitive - a
    string that merely spells "True" is stored quoted and already decoded by
    the JSON pass); a bare hex integer (e.g. ``0x0``, which JSON's number
    grammar rejects). Matching the C# reader's fallback order here is what
    keeps the two readers agreeing on the same stored value.

    Args:
        raw_value (str): stored value text

    Returns:
        the decoded value, or the raw text when no encoding accounts for it
    """
    for candidate in _json_candidates(raw_value):
        try:
            return json.loads(candidate)
        except (ValueError, TypeError):
            pass

    token = raw_value.strip()
    if token.lower() in ("true", "false"):
        return token.lower() == "true"

    if _HEX_INTEGER_REGEX.match(token):
        return int(token, 16)

    return raw_value

open_config_file(cfg_file_path, read_only=False)

Open an ini file of your own, separate from the pyRevit user config.

For tool settings that belong in their own file rather than in the shared pyRevit config. To read or write the shared config, use :obj:pyrevit.userconfig.user_config instead.

Parameters:

Name Type Description Default
cfg_file_path str

path to the ini file; it need not exist yet

required
read_only bool

open without allowing writes

False

Returns:

Type Description
ConfigSections

the sections of the given file

Note

Imports pyrevit.labs locally: that module imports this one, so a module-level import here would close the cycle.

Source code in pyrevitlib/pyrevit/coreutils/configparser.py
def open_config_file(cfg_file_path, read_only=False):
    """Open an ini file of your own, separate from the pyRevit user config.

    For tool settings that belong in their own file rather than in the shared
    pyRevit config. To read or write the shared config, use
    :obj:`pyrevit.userconfig.user_config` instead.

    Args:
        cfg_file_path (str): path to the ini file; it need not exist yet
        read_only (bool): open without allowing writes

    Returns:
        (ConfigSections): the sections of the given file

    Note:
        Imports ``pyrevit.labs`` locally: that module imports this one, so a
        module-level import here would close the cycle.
    """
    from pyrevit.labs import ConfigurationBuilder, IniConfiguration

    configuration = IniConfiguration.Create(cfg_file_path, read_only)
    return ConfigSections(
        ConfigurationBuilder(read_only).AddConfigurationSource(configuration).Build()
    )