stratified_packager.toolbelt.settings

QGIS-specific persistence proxies: typed settings, project entries, variables, layer properties.

This module wraps the disparate QGIS persistence APIs documented in the PyQGIS Developer Cookbook (Reading and Storing Settings) behind a small set of Pythonic objects that read and write values while converting to and from the appropriate Python types:

Proxy

Backing QGIS API

SettingsProxy

qgis.core.QgsSettings (flat key/value)

PluginSettingsBase

the above plus typed QgsSettingsEntry* objects

ProjectEntries

qgis.core.QgsProject.readEntry() / writeEntry

ProjectVariables

qgis.core.QgsExpressionContextUtils project scope

LayerCustomProperties

qgis.core.QgsMapLayer.customProperty()

LayerVariables

qgis.core.QgsExpressionContextUtils layer scope

Two complementary access styles are offered, mirroring how QgsSettingsEntry* sits over a flat store:

  • Dict-like — every proxy is a MutableMapping keyed by string, so arbitrary dynamic keys work out of the box:

    gs = SettingsProxy()
    gs["ui/theme"]  # raw stored value
    gs.get("max_threads", 4, cast=int)  # with type and default
    
  • Typed descriptorsPluginSettingsBase subclasses declare known keys as class attributes whose Setting descriptors read and write typed QgsSettingsEntry* objects registered under the plugin’s node in the global settings tree:

    class MySettings(PluginSettingsBase):
        _PLUGIN_NAME = "my_plugin"
        debug_mode = BoolSetting(default=False)
    
    
    s = MySettings()
    s.debug_mode  # -> bool
    s.debug_mode = True  # persisted
    

The proxies build on the QGIS-free mapping_proxy: they subclass its MappingProxy and read and write through its conversion registry (to_storage() / from_storage()). That registry covers the stdlib types; this module registers the QGIS-only QColor converter at import so ColorSetting and cast=QColor round-trip.

Warning

Every proxy here touches main-thread QGIS objects (QgsProject, QgsMapLayer), so they must only be used on the GUI thread. qgis.core.QgsSettings is the sole exception (it is thread-safe), but the proxies make no special accommodation for off-thread use.

Classes

BoolSetting(default[, description, key])

A bool setting backed by QgsSettingsEntryBool.

ColorSetting(default[, description, key])

A QColor setting.

DoubleSetting(default[, description, key])

A float setting backed by QgsSettingsEntryDouble.

EnumSetting(enum_type, default[, ...])

An enum.Enum setting persisted by its member value.

IntSetting(default[, description, key])

An int setting backed by QgsSettingsEntryInteger.

LayerCustomProperties(layer)

Dict-like proxy over a layer's custom properties.

LayerVariables(layer)

Dict-like proxy over a layer's expression variables.

PluginSettingsBase(*[, settings])

Plugin-agnostic base for a plugin's typed settings schema, scoped under plugins/<name>.

ProjectEntries(scope, *[, project])

Dict-like proxy over a project's custom entries (qgis.core.QgsProject.writeEntry()).

ProjectVariables(*[, project])

Dict-like proxy over a project's expression variables.

Setting(default[, description, key])

Descriptor mapping a class attribute to a typed QgsSettingsEntry*.

SettingsProxy([prefix, settings])

Dict-like proxy over qgis.core.QgsSettings, optionally scoped to a prefix.

StringListSetting(default[, description, key])

A list[str] setting backed by QgsSettingsEntryStringList.

StringSetting(default[, description, key])

A str setting backed by QgsSettingsEntryString.

VariantMapSetting(default[, description, key])

A dict[str, Any] setting backed by QgsSettingsEntryVariantMap.

VariantSetting(default[, description, key])

A free-form setting backed by QgsSettingsEntryVariant.

class stratified_packager.toolbelt.settings.BoolSetting(default, description='', *, key=None)[source]

A bool setting backed by QgsSettingsEntryBool.

Parameters:
class stratified_packager.toolbelt.settings.ColorSetting(default, description='', *, key=None)[source]

A QColor setting.

Backed by QgsSettingsEntryColor.

Parameters:
class stratified_packager.toolbelt.settings.DoubleSetting(default, description='', *, key=None)[source]

A float setting backed by QgsSettingsEntryDouble.

Parameters:
class stratified_packager.toolbelt.settings.EnumSetting(enum_type, default, description='', *, key=None)[source]

An enum.Enum setting persisted by its member value.

The backing QgsSettingsEntry* is chosen from the type of the default member’s value (bool/int/float/str, falling back to QgsSettingsEntryVariant). Reading reconstructs the member via enum_type(stored_value), which also handles enum.IntFlag combinations. This sidesteps the inconsistent return typing of QgsSettingsEntryEnumFlag while still persisting through a typed entry.

Parameters:
__init__(enum_type, default, description='', *, key=None)[source]

Initialize the descriptor.

Parameters:
  • enum_type (type[TypeVar(E, bound= Enum)]) – The concrete enum.Enum subclass.

  • default (TypeVar(E, bound= Enum)) – Default member.

  • description (str) – Human-readable description stored on the entry.

  • key (str | None) – Storage key; defaults to the attribute name.

_build_entry(plugin_name)[source]

Construct a typed entry storing the member value (see the class docstring).

Parameters:

plugin_name (str) – Plugin name inserted into the entry key.

Return type:

QgsSettingsEntryVariant

Returns:

A backing entry whose value type matches the enum’s values.

_decode(entry)[source]

Rebuild the enum member from the stored value.

Parameters:

entry (QgsSettingsEntryVariant) – The backing entry to read.

Return type:

TypeVar(E, bound= Enum)

Returns:

The reconstructed enum member.

_encode(value)[source]

Reduce the enum member to its stored value.

Parameters:

value (TypeVar(E, bound= Enum)) – The enum member being assigned.

Return type:

object

Returns:

value.value.

class stratified_packager.toolbelt.settings.IntSetting(default, description='', *, key=None)[source]

An int setting backed by QgsSettingsEntryInteger.

Parameters:
class stratified_packager.toolbelt.settings.LayerCustomProperties(layer)[source]

Dict-like proxy over a layer’s custom properties.

Wraps qgis.core.QgsMapLayer.customProperty() / setCustomProperty() — arbitrary key/value pairs persisted with the layer in the project file.

Parameters:

layer (QgsMapLayer)

__init__(layer)[source]

Initialize the proxy.

Parameters:

layer (QgsMapLayer) – The layer whose custom properties are proxied.

_raw_del(key)[source]

Remove custom property key.

Parameters:

key (str) – The property key.

Return type:

None

_raw_get(key)[source]

Read custom property key.

Parameters:

key (str) – The property key.

Return type:

tuple[object, bool]

Returns:

A (value, present) pair.

_raw_keys()[source]

Return the layer’s custom property keys.

Return type:

list[str]

Returns:

The list of property keys.

_raw_set(key, value)[source]

Set custom property key.

Parameters:
  • key (str) – The property key.

  • value (object) – The storable value.

Return type:

None

_abc_impl = <_abc._abc_data object>
class stratified_packager.toolbelt.settings.LayerVariables(layer)[source]

Dict-like proxy over a layer’s expression variables.

Wraps qgis.core.QgsExpressionContextUtils’ layer scope — the @-variables shown under Layer Properties → Variables.

As with ProjectVariables, iteration and membership reflect the full layer scope (including built-ins such as layer_name/layer_id). QGIS exposes no removeLayerVariable, so deletion rewrites the layer’s user-defined variables without the removed key via qgis.core.QgsExpressionContextUtils.setLayerVariables(); deleting a name that exists only as a built-in therefore has no effect.

Parameters:

layer (QgsMapLayer)

__init__(layer)[source]

Initialize the proxy.

Parameters:

layer (QgsMapLayer) – The layer whose variables are proxied.

_custom_pairs()[source]

Return the layer’s user-defined variables from its custom properties.

Return type:

dict[str, str]

Returns:

A mapping of user-defined variable names to their stored values.

_raw_del(key)[source]

Remove the user-defined layer variable key by rewriting the rest.

Parameters:

key (str) – The variable name.

Return type:

None

_raw_get(key)[source]

Read variable key from the layer scope.

Parameters:

key (str) – The variable name.

Return type:

tuple[object, bool]

Returns:

A (value, present) pair.

_raw_keys()[source]

Return all variable names in the layer scope (custom and built-in).

Return type:

list[str]

Returns:

The list of variable names.

_raw_set(key, value)[source]

Set the user-defined layer variable key.

Parameters:
  • key (str) – The variable name.

  • value (object) – The storable value.

Return type:

None

_scope()[source]

Return a fresh layer expression scope.

Return type:

QgsExpressionContextScope

Returns:

The layer QgsExpressionContextScope.

Raises:

RuntimeError – If QGIS returns no layer scope.

_VARIABLE_NAMES_PROPERTY: ClassVar[str] = 'variableNames'

Custom-property key under which QGIS stores user-defined variable names.

_VARIABLE_VALUES_PROPERTY: ClassVar[str] = 'variableValues'

Custom-property key under which QGIS stores user-defined variable values.

_abc_impl = <_abc._abc_data object>
_layer: qgis.core.QgsMapLayer
class stratified_packager.toolbelt.settings.PluginSettingsBase(*, settings=None)[source]

Plugin-agnostic base for a plugin’s typed settings schema, scoped under plugins/<name>.

Concrete subclasses set a non-empty _PLUGIN_NAME and declare their known keys as typed Setting descriptors while remaining a full dict-like SettingsProxy for any additional keys. Because the scope matches the descriptors’ entry keys, self.<key> and self["<key>"] address the same stored value. Everything is derived from _PLUGIN_NAME, so this class carries no dependency on any particular plugin. The name is enforced at class-creation time (see __init_subclass__); an intermediate base that leaves it intentionally unset must opt out with class Mixin(PluginSettingsBase, abstract=True).

Parameters:

settings (QgsSettings | None)

classmethod teardown()[source]

Unregister the plugin’s settings-tree node and drop cached descriptor entries.

Call this from the plugin’s unload() so a subsequent reload can re-register the same Setting entries cleanly. Safe to call when nothing has been registered.

Return type:

None

__init__(*, settings=None)[source]

Initialize the proxy scoped to the plugin’s settings node.

Parameters:

settings (QgsSettings | None) – Existing QgsSettings to use; a fresh one is created when omitted.

reset_defaults()[source]

Remove every declared Setting’s stored value, restoring its default.

Return type:

None

_PLUGIN_NAME: ClassVar[str]

Plugin name (tree node and scope); a concrete subclass MUST set a non-empty value.

_abc_impl = <_abc._abc_data object>
class stratified_packager.toolbelt.settings.ProjectEntries(scope, *, project=None)[source]

Dict-like proxy over a project’s custom entries (qgis.core.QgsProject.writeEntry()).

Entries are persisted in the .qgs/.qgz file under a caller-supplied scope (group). They are not exposed as expression variables — use ProjectVariables for those.

QGIS reads project entries through type-specific methods, so for typed reads use get() with cast=; plain [] access returns the value as a string. Writes dispatch on the Python type to the matching writeEntry* method — writeEntryBool() / writeEntryDouble() for bool / float, and writeEntry() for everything else — so each value round-trips through its corresponding read*Entry (e.g. read a float back with cast=float). Iteration yields the immediate child entry keys of the scope; nested keys are reached with a proxy scoped one level deeper.

Parameters:
  • scope (str)

  • project (QgsProject | None)

__init__(scope, *, project=None)[source]

Initialize the proxy.

Parameters:
  • scope (str) – Entry scope (group) name (e.g. the plugin slug).

  • project (QgsProject | None) – Project to read/write; defaults to qgis.core.QgsProject.instance().

_raw_del(key)[source]

Remove key from the project scope.

Parameters:

key (str) – The entry key.

Raises:

RuntimeError – If QgsProject reports the removal failed.

Return type:

None

_raw_get(key)[source]

Read key as a string from the project scope.

Parameters:

key (str) – The entry key.

Return type:

tuple[object, bool]

Returns:

A (value, present) pair.

_raw_keys()[source]

Return the immediate child entry keys of the scope.

Return type:

list[str]

Returns:

The list of entry keys holding values.

_raw_set(key, value)[source]

Write value at key, dispatching on the storable type.

Parameters:
  • key (str) – The entry key.

  • value (object) – The storable value already passed through to_storage().

Raises:

RuntimeError – If QgsProject reports the write failed.

Return type:

None

_typed_get(key, cast)[source]

Read key with the QgsProject method matching cast.

bool, int, float and list route to readBoolEntry(), readNumEntry(), readDoubleEntry() and readListEntry() respectively; other casts read the string entry and convert via from_storage().

Parameters:
  • key (str) – The entry key.

  • cast (type[object] | None) – Target Python type, or None for the string value.

Return type:

tuple[object, bool]

Returns:

A (value, present) pair.

_abc_impl = <_abc._abc_data object>
_project: qgis.core.QgsProject
_scope: str
class stratified_packager.toolbelt.settings.ProjectVariables(*, project=None)[source]

Dict-like proxy over a project’s expression variables.

Wraps qgis.core.QgsExpressionContextUtils’ project scope — the @-variables shown under Project Properties → Variables. Assignment creates or replaces a user-defined variable; deletion removes one.

Iteration and membership reflect the full project scope, which also includes QGIS’ built-in project variables (project_path, project_title, …). Those built-ins are read-only: deleting a name that exists only as a built-in has no effect.

Parameters:

project (QgsProject | None)

__init__(*, project=None)[source]

Initialize the proxy.

Parameters:

project (QgsProject | None) – Project to read/write; defaults to qgis.core.QgsProject.instance().

_raw_del(key)[source]

Remove the user-defined project variable key.

Parameters:

key (str) – The variable name.

Return type:

None

_raw_get(key)[source]

Read variable key from the project scope.

Parameters:

key (str) – The variable name.

Return type:

tuple[object, bool]

Returns:

A (value, present) pair.

_raw_keys()[source]

Return all variable names in the project scope (custom and built-in).

Return type:

list[str]

Returns:

The list of variable names.

_raw_set(key, value)[source]

Set the user-defined project variable key.

Parameters:
  • key (str) – The variable name.

  • value (object) – The storable value.

Return type:

None

_scope()[source]

Return a fresh project expression scope.

Return type:

QgsExpressionContextScope

Returns:

The project QgsExpressionContextScope.

Raises:

RuntimeError – If QGIS returns no project scope.

_abc_impl = <_abc._abc_data object>
_project: qgis.core.QgsProject
class stratified_packager.toolbelt.settings.Setting(default, description='', *, key=None)[source]

Descriptor mapping a class attribute to a typed QgsSettingsEntry*.

Declare instances as class attributes of a PluginSettingsBase subclass. On first access, the descriptor lazily constructs its backing entry using the plugin constructor of the relevant QgsSettingsEntry* class — keyed by the owning proxy’s PluginSettingsBase._PLUGIN_NAME — so the value is persisted at plugins/<plugin-name>/<key> and appears in the QGIS settings tree. That key coincides with the one a SettingsProxy prefixed with plugins/<plugin-name> produces, so descriptor access and dict access address the same stored value.

Subclasses set _ENTRY_CLASS to the concrete entry type; only EnumSetting needs to override the value-marshalling hooks.

Parameters:
__init__(default, description='', *, key=None)[source]

Initialize the descriptor.

Parameters:
  • default (TypeVar(T)) – Value returned when the setting has never been written.

  • description (str) – Human-readable description stored on the entry.

  • key (str | None) – Storage key; defaults to the attribute name the descriptor is assigned to.

_build_entry(plugin_name)[source]

Construct the backing entry under plugin_name’s settings node.

The concrete entry is built from _ENTRY_CLASS and viewed as a QgsSettingsEntryVariant so its value / setValue methods are visible to type checkers (the abstract base lacks them).

Parameters:

plugin_name (str) – Plugin name inserted into the entry key.

Return type:

QgsSettingsEntryVariant

Returns:

The backing entry, viewed as a variant entry.

_decode(entry)[source]

Marshal the entry’s stored value into T.

Parameters:

entry (QgsSettingsEntryVariant) – The backing entry to read.

Return type:

TypeVar(T)

Returns:

The typed value.

_encode(value)[source]

Marshal T into the form the entry persists.

Parameters:

value (TypeVar(T)) – The value being assigned.

Return type:

object

Returns:

The representation passed to QgsSettingsEntryBase.setValue.

_entry(owner)[source]

Return the backing entry for owner, building and caching it on first use.

Parameters:

owner (type[PluginSettingsBase]) – The PluginSettingsBase subclass owning the descriptor.

Return type:

QgsSettingsEntryVariant

Returns:

The cached backing entry.

_forget()[source]

Drop cached entries so they are rebuilt after a settings-tree teardown.

Return type:

None

reset(owner)[source]

Remove the stored value so the default applies again.

Parameters:

owner (type[PluginSettingsBase]) – The owning PluginSettingsBase subclass.

Return type:

None

_ENTRY_CLASS: ClassVar[type[QgsSettingsEntryBase]]

Concrete QgsSettingsEntry* class backing this descriptor.

_default: T
_description: str
_entries: dict[type, QgsSettingsEntryVariant]
_explicit_key: str | None
_name: str
property key: str

Storage key of this setting (the explicit key, or the attribute name).

Returns:

The key used under the plugin’s settings node.

class stratified_packager.toolbelt.settings.SettingsProxy(prefix='', *, settings=None)[source]

Dict-like proxy over qgis.core.QgsSettings, optionally scoped to a prefix.

Keys are joined to prefix with /; an empty prefix (the default) addresses the raw global namespace, so SettingsProxy()["ui/theme"] reads the same key the QGIS options dialog writes.

For typed reads prefer get() with cast= — it routes the native types (str, int, float, bool, list) through qgis.core.QgsSettings.value()’s own coercion (which correctly turns the string "true" back into True) and uses the converter registry for the rest. Plain [] access returns the raw stored value without coercion.

Parameters:
  • prefix (str)

  • settings (QgsSettings | None)

__init__(prefix='', *, settings=None)[source]

Initialize the proxy.

Parameters:
  • prefix (str) – Key prefix; surrounding slashes are stripped.

  • settings (QgsSettings | None) – Existing QgsSettings to use; a fresh one is created when omitted.

_full_key(key)[source]

Join key to the configured prefix.

Parameters:

key (str) – The relative key.

Return type:

str

Returns:

The fully qualified QgsSettings key.

_raw_del(key)[source]

Remove key and any sub-settings.

Parameters:

key (str) – The relative key.

Return type:

None

_raw_get(key)[source]

Read key from QgsSettings.

Parameters:

key (str) – The relative key.

Return type:

tuple[object, bool]

Returns:

A (value, present) pair.

_raw_keys()[source]

Return the keys under the configured prefix, relative to it.

Return type:

list[str]

Returns:

The list of relative keys.

_raw_set(key, value)[source]

Write value at key.

Parameters:
  • key (str) – The relative key.

  • value (object) – The storable value.

Return type:

None

_typed_get(key, cast)[source]

Read key, coercing native types through qgis.core.QgsSettings.value().

Parameters:
  • key (str) – The relative key.

  • cast (type[object] | None) – Target Python type, or None for the raw value.

Return type:

tuple[object, bool]

Returns:

A (value, present) pair.

_NATIVE_TYPES: ClassVar[tuple[type, ...]] = (<class 'str'>, <class 'int'>, <class 'float'>, <class 'bool'>, <class 'list'>)

Types qgis.core.QgsSettings.value() can coerce directly via its type= argument.

_abc_impl = <_abc._abc_data object>
_prefix: str
_settings: qgis.core.QgsSettings
class stratified_packager.toolbelt.settings.StringListSetting(default, description='', *, key=None)[source]

A list[str] setting backed by QgsSettingsEntryStringList.

Parameters:
class stratified_packager.toolbelt.settings.StringSetting(default, description='', *, key=None)[source]

A str setting backed by QgsSettingsEntryString.

Parameters:
class stratified_packager.toolbelt.settings.VariantMapSetting(default, description='', *, key=None)[source]

A dict[str, Any] setting backed by QgsSettingsEntryVariantMap.

Values round-trip type-preservingly (nested scalars and string lists keep their Python types). Like every descriptor this is read-replace: mutating the returned dict in place does not persist; reassign the whole value, e.g. proxy.conf = proxy.conf | {"key": value}.

Parameters:
class stratified_packager.toolbelt.settings.VariantSetting(default, description='', *, key=None)[source]

A free-form setting backed by QgsSettingsEntryVariant.

Parameters:
stratified_packager.toolbelt.settings._resolve_project(project)[source]

Return project, falling back to the singleton qgis.core.QgsProject.instance().

Parameters:

project (QgsProject | None) – An explicit project, or None to use the singleton.

Return type:

QgsProject

Returns:

A non-None QgsProject.

Raises:

RuntimeError – If no project is available.