API Reference

class sunset.Settings[source]

A collection of keys that can be saved to and loaded from text, and supports subsections.

Under the hood, a Settings class is a dataclass, and can be used in the same manner, i.e. by defining attributes directly on the class itself.

Settings instances support subsections: calling the newSection() method on an instance creates a subsection of that instance. This subsection holds the same keys, with independant values. If a key of the subsection does not have a value, its value will be looked up on its parent section instead. The hierarchy of sections can be arbitrarily deep.

When saving a Settings instance, its subsections are saved with it under a distinct heading for each, provided they have a name. A section is given a name by passing it to the newSection() method, or by using the setSectionName() method on the new section after creation.

The name of each section is used to construct the heading it is saved under. The top-level Settings instance is saved under the [main] heading by default.

Anonymous (unnamed) sections do not get saved.

Example:

>>> from sunset import Key, Settings
>>> class AnimalSettings(Settings):
...     hearts: Key[int] = Key(default=0)
...     legs: Key[int]   = Key(default=0)
...     wings: Key[int]  = Key(default=0)
...     fur: Key[bool]   = Key(default=False)
>>> animals = AnimalSettings()
>>> animals.hearts.set(1)
True
>>> mammals = animals.newSection(name="mammals")
>>> mammals.fur.set(True)
True
>>> mammals.legs.set(4)
True
>>> humans = mammals.newSection(name="humans")
>>> humans.legs.set(2)
True
>>> humans.fur.set(False)
True
>>> birds = animals.newSection(name="birds")
>>> birds.legs.set(2)
True
>>> birds.wings.set(2)
True
>>> aliens = animals.newSection()  # No name given!
>>> aliens.hearts.set(2)
True
>>> aliens.legs.set(7)
True
>>> print(mammals.hearts.get())
1
>>> print(mammals.legs.get())
4
>>> print(mammals.wings.get())
0
>>> print(mammals.fur.get())
True
>>> print(birds.hearts.get())
1
>>> print(birds.legs.get())
2
>>> print(birds.wings.get())
2
>>> print(birds.fur.get())
False
>>> print(humans.hearts.get())
1
>>> print(humans.legs.get())
2
>>> print(humans.wings.get())
0
>>> print(humans.fur.get())
False
>>> print(aliens.hearts.get())
2
>>> print(aliens.legs.get())
7
>>> print(aliens.wings.get())
0
>>> print(aliens.fur.get())
False
>>> import io
>>> txt = io.StringIO()
>>> animals.save(txt)
>>> print(txt.getvalue(), end="")
[main]
hearts = 1
[birds]
legs = 2
wings = 2
[mammals]
fur = true
legs = 4
[mammals/humans]
fur = false
legs = 2
load(file: IO[str]) None[source]

Loads settings from the given text file object.

If the given file contains lines that don’t make sense – for instance, if the line is garbage, or refers to a key that does not exist in this Settings class, or it exists but with an incompatible type – then the faulty line is skipped silently.

If the text file object contains multiple headings, those headings will be used to create subsections with the corresponding names.

Note that loading new settings resets the current settings.

Parameters:

file – A text file open in reading mode.

save(file: IO[str], *, blanklines: bool = False) None[source]

Writes the contents of this Settings instance and its subsections in text form to the given file object.

Parameters:
  • file – A text file object where to save this Settings instance.

  • blanklines – Whether to add a blank line before section headings.

autosave(path: str | Path, *, save_on_update: bool = True, save_delay: int = 0, raise_on_error: bool = False, logger: Logger | None = None) AutoSaver[source]

Returns a context manager that loads these Settings from the given file path on instantiation and saves them on exit.

By default, it will also automatically save the settings whenever they are updated from inside the application. Optionally, the updates can be batched over a given delay before being saved.

See the documentation of AutoSaver for the details.

Parameters:
  • path – The full path to the file to load the settings from and save them to. If this file does not exist yet, it will be created when saving for the first time.

  • save_on_update – Whether to save the settings when they are updated in any way. Default: True.

  • save_delay – How long to wait, in seconds, before actually saving the settings when save_on_update is True and an update occurs. Setting this to a few seconds will batch updates for that long before triggering a save. If set to 0, the save is triggered immediately. Default: 0.

  • raise_on_error – Whether OS errors occurring while loading and saving the settings should raise an exception. If False, errors will only be logged. Default: False.

  • logger – A logger instance that will be used to log OS errors, if any, while loading or saving settings. If none is given, the default root logger will be used.

Returns:

An AutoSaver context manager.

newSection(name: str = '') Self[source]

Creates and returns a new instance of this class. Each key of the new instance will inherit from the key of the same name on the parent instance.

When saving Settings with the save() method, each section’s name is used to generate the heading under which that section is saved. If the new section is created without a name, it will be skipped when saving. A name can still be given to a section after creation with the setSectionName() method.

If this Settings instance already has a section with the given name, the new section will be created with a unique name generated by appending a numbered suffix to that name.

Parameters:

name – The name that will be used to generate a heading for this section when saving it to text. The given name will be normalized to lowercase alphanumeric characters.

Returns:

An instance of the same type as self.

getOrCreateSection(name: str) Self[source]

Finds and returns the section of these Settings with the given name if it exists, and creates it if it doesn’t.

If the given name is empty, this is equivalent to calling newSection() instead.

Parameters:

name – The name that will be used to generate a heading for this section when saving it to text. The given name will be normalized to lowercase alphanumeric characters.

Returns:

An instance of the same type as self.

getSection(name: str) Self | None[source]

Finds and returns a section of this instance with the given name, if it exists, else None.

Parameters:

name – The name of the section to return.

Returns:

An instance of the same type as self, or None.

sections() Iterable[Self][source]

Returns an iterable with the subsections of this Settings instance. Note that the subsections are only looked up one level deep, that is to say, no recursing into the section hierarchy occurs.

Returns:

An iterable of Settings instances of the same type as this one.

sectionName() str[source]

Returns the current name of this Settings instance. This name will be used to generate the heading under which this Settings instance will be persisted by the save() method.

Returns:

The name of this Settings instance.

setSectionName(name: str) str[source]

Sets the unique name under which this Settings instance will be persisted by the save() method. The given name will be normalized to lowercase, without space or punctuation.

This name is guaranteed to be unique. If the given name is already used by a section of the same Settings instance, then a numbered suffix is generated to make this one’s name unique.

If the given name is empty, these settings will be skipped when saving.

The toplevel Settings instance is named “main” by default. It cannot be unnamed; it will revert to its default name instead.

Parameters:

name – The name that will be used to generate a heading for these settings when saving them to text.

Returns:

The given name, normalized, and made unique if needed.

Example:

>>> from sunset import Settings
>>> class TestSettings(Settings):
...     pass
>>> parent = TestSettings()
>>> section1 = parent.newSection()
>>> section2 = parent.newSection()
>>> section3 = parent.newSection()
>>> section1.setSectionName("  T ' e ? S / t")
'test'
>>> section2.setSectionName("TEST")
'test_1'
>>> section3.setSectionName("test")
'test_2'
>>> # This should not change this section's name.
>>> section3.setSectionName("test")
'test_2'
onUpdateCall(callback: Callable[[Any], Any]) None[source]

Adds a callback to be called whenever this Settings instance is updated. A Settings instance is considered updated when any of its fields is updated, or when its name is updated.

The callback will be called with as its argument whichever field was just updated.

Parameters:

callback – A callable that will be called with one argument of type List, Bunch or Key.

Note

This method does not increase the reference count of the given callback.

skipOnSave() bool[source]

Internal.

Returns whether this entity should be disregarded when saving these settings. For entities with an attribute name, it’s equivalent to checking if the attribute is private (its name starts with an underscore). For entities with a section name, it’s equivalent to checking if the section name is empty.

Can be overridden in subclasses.

Returns:

A bool used internally by the settings saving logic.

setParent(parent: Self | None) None[source]

Makes the given Settings instance the parent of this one. If None, remove this instance’s parent, if any.

All the Key, List and Bunch fields defined on this instance will be recursively reparented to the corresponding Key / List / Bunch field on the given parent.

This method is for internal purposes and you will typically not need to call it directly.

Parameters:

parent – Either a Settings instance that will become this instance’s parent, or None. The parent Settings instance must have the same type as this instance.

parent() Self | None

Returns the parent of this Bunch, if any.

Returns:

A Bunch instance of the same type as this one, or None.

children() Iterable[Self]

Returns an iterable with the Bunch instances that have this Bunch as their parent.

Returns:

An iterable of Bunch instances of the same type as this one.

class sunset.Key(default: _T, serializer: Serializer[_T] | None = None, validator: Callable[[_T], bool] | None = None, value_type: type[_T] | None = None)[source]

A single setting key containing a typed value.

Keys support inheritance. If a Key does not have a value explicitly set, and it has a parent, then its value will be that of its parent. Else its value if unset is the default value it was instantiated with.

Keys can call a callback when their reported value changes, whether it’s their own value that changed, or that inherited from a parent. Set this callback with the onValueChangeCall() method.

You can control the values that can be set on this Key by passing a validator argument when instantiating it.

Parameters:
  • default

    The value that this Key will return when not otherwise set; the type of this default determines the type of the values that can be set on this Key.

    If the type of the default is not one of bool, int, float, str, or an enum.Enum subclass, and is also not a class that implements the Serializable protocol, then a serializer argument must also be passed.

  • serializer – An implementation of the Serializer protocol for the type of this Key’s values. This argument must be passed if the type in question is not supported by a native SunsetSettings serializer. If a serializer is passed, it will be used even if SunsetSettings has its own serializer for that type.

  • validator – A function that returns True if the given value can be set on this Key, else False. This allows you to control what values are allowable for this Key. Default: None.

  • value_type – If given, the type that will be used by runtime safety checks instead of the type of the default value. This is rarely needed, but can be useful e.g. if the Key is meant to hold values from multiple possible subclasses of a base class.

Example:

>>> from sunset import Key
>>> key: Key[int] = Key(default=0)
>>> key.get()
0
>>> key.set(42)
True
>>> key.get()
42
>>> child_key: Key[int] = Key(default=0)
>>> child_key.setParent(key)
>>> child_key.get()
42
>>> child_key.set(101)
True
>>> child_key.get()
101
>>> key.set(36)
True
>>> key.get()
36
>>> child_key.get()
101
>>> child_key.clear()
>>> child_key.get()
36
set(value: _T) bool[source]

Sets the given value on this Key.

Parameters:

value – The value that this Key will now hold. Must be of the type bound to this Key, i.e. the same type as this Key’s default value.

Returns:

True if the value was successfully set, else False, for instance if the validator refused the value.

get() _T[source]

Returns the current value of this Key.

If this Key does not currently have a value set on it, return its fallback value, that being, the value of its parent if it has one, else the default.

Returns:

This Key’s apparent value.

isSet() bool[source]

Returns whether there is a value currently set on this Key.

Returns:

True if a value is set on this Key, else False.

fallback() _T[source]

Returns the value that this Key will fall back to when it does not have a value currently set.

That value is the value of its parent if it has one, or the default value for the Key if not.

updateValue(updater: Callable[[_T], _T]) None[source]

Atomically updates this Key’s value using the given update function. The function will be called with the Key’s current value, and the value it returns will be set as the Key’s new value.

Parameters:

updater – A function that takes an argument of the same type held in this key, and returns an argument of the same type.

clear() None[source]

Clears the value currently set on this Key, if any.

setValidator(validator: Callable[[_T], bool]) None[source]

Replaces this Key’s validator.

Parameters:

validator – A function that returns True if the given value can be set on this Key, else False. This allows you to control what values are allowable for this Key.

onValueChangeCall(callback: Callable[[_T], Any]) None[source]

Adds a callback to be called whenever the value returned by calling get() on this Key would change, even if this Key itself was not updated; for instance, this will happen if there is no value currently set on it and its parent’s value changed.

The callback will be called with the new value as its argument.

If you want a callback to be called whenever this Key is updated, even if its apparent value does not change, use onUpdateCall() instead. For example, if you call set() with a value of 0 on a Key newly created with a default value of 0, callbacks added with onUpdateCall() are called and callbacks added with onValueChangeCall() are not.

Parameters:

callback – A callable that takes one argument of the same type as the values held by this Key.

Note

This method does not increase the reference count of the given callback.

onUpdateCall(callback: Callable[[Key[_T]], Any]) None[source]

Adds a callback to be called whenever this Key is updated, even if the value returned by get() does not end up changing.

The callback will be called with this Key instance as its argument.

If you want a callback to be called only when the apparent value of this Key changes, use onValueChangeCall() instead. For example, if a Key has no value set on it and has a parent whose value is updated, then callbacks added on this Key with onValueChangeCall() are called, and callbacks added with onUpdateCall() are not, because it’s not this Key that was updated.

Parameters:

callback – A callable that will be called with one argument of type Key.

Note

This method does not increase the reference count of the given callback.

skipOnSave() bool

Internal.

Returns whether this entity should be disregarded when saving these settings. For entities with an attribute name, it’s equivalent to checking if the attribute is private (its name starts with an underscore). For entities with a section name, it’s equivalent to checking if the section name is empty.

Can be overridden in subclasses.

Returns:

A bool used internally by the settings saving logic.

setParent(parent: Self | None) None[source]

Makes the given Key the parent of this one. If None, remove this Key’s parent, if any.

A Key with a parent will inherit its parent’s value when this Key’s own value is not currently set.

This method is for internal purposes and you will typically not need to call it directly.

Parameters:

parent – Either a Key that will become this Key’s parent, or None. The parent Key must have the same type as this Key.

Note

A Key and its parent, if any, do not increase each other’s reference count.

parent() Self | None[source]

Returns the parent of this Key, if any.

Returns:

A Key instance of the same type as this one, or None.

children() Iterable[Self][source]

Returns an iterable with the Keys that have this Key as their parent.

Returns:

An iterable of Keys of the same type as this one.

class sunset.Bunch[source]

A collection of related Keys.

Under the hood, a Bunch is a dataclass, and can be used in the same manner, i.e. by defining attributes directly on the class itself.

Example:

>>> from sunset import Bunch, Key
>>> class Appearance(Bunch):
...     class Font(Bunch):
...         name: Key[str] = Key(default="Arial")
...         size: Key[int] = Key(default=14)
...     main_font: Font      = Font()
...     secondary_font: Font = Font()
>>> appearance = Appearance()
>>> appearance.main_font.name.get()
'Arial'
>>> appearance.secondary_font.name.get()
'Arial'
>>> appearance.main_font.name.set("Times New Roman")
True
>>> appearance.secondary_font.name.set("Calibri")
True
>>> appearance.main_font.name.get()
'Times New Roman'
>>> appearance.secondary_font.name.get()
'Calibri'
onUpdateCall(callback: Callable[[Any], Any]) None[source]

Adds a callback to be called whenever this Bunch is updated. A Bunch is considered updated when any of its fields is updated.

The callback will be called with as its argument whichever field was just updated.

Parameters:

callback – A callable that will be called with one argument of type List, Bunch or Key.

Note

This method does not increase the reference count of the given callback.

skipOnSave() bool

Internal.

Returns whether this entity should be disregarded when saving these settings. For entities with an attribute name, it’s equivalent to checking if the attribute is private (its name starts with an underscore). For entities with a section name, it’s equivalent to checking if the section name is empty.

Can be overridden in subclasses.

Returns:

A bool used internally by the settings saving logic.

setParent(parent: Self | None) None[source]

Makes the given Bunch the parent of this one. If None, remove this Bunch’s parent, if any.

All the Key, List and Bunch fields defined on this Bunch instance will be recursively reparented to the corresponding Key / List / Bunch field on the given parent.

This method is for internal purposes and you will typically not need to call it directly.

Parameters:

parent – Either a Bunch that will become this Bunch’s parent, or None. The parent Bunch must have the same type as this Bunch.

Note

A Bunch and its parent, if any, do not increase each other’s reference count.

parent() Self | None[source]

Returns the parent of this Bunch, if any.

Returns:

A Bunch instance of the same type as this one, or None.

children() Iterable[Self][source]

Returns an iterable with the Bunch instances that have this Bunch as their parent.

Returns:

An iterable of Bunch instances of the same type as this one.

class sunset.List(template: ListItemT, order: IterOrder = IterOrder.NO_PARENT)[source]

A list-like container for Keys or Bunches of a given type, to be used in a Settings’ definition.

It is type-compatible with standard Python lists and supports indexing, insertion, appending, etc.

In addition, it offers support for update notification callbacks, and inheritance. The inheritance is used when iterating on the List’s contents using the iter() method, which iterates on a List and, optionally, its parents.

Instead of creating a new instance of the contained type and inserting or appending it, you can use the appendOne() or insertOne() methods to do it in one step.

Parameters:
  • template – A Key or a Bunch instance that represents the items that will be contained in this List. (The template itself will not be added to the List.)

  • order – One of List.NO_PARENT, List.PARENT_FIRST or List.PARENT_LAST. Sets the default iteration order used in iter() when not otherwise specified. Default: List.NO_PARENT.

Example:

>>> from sunset import Bunch, Key, List, Settings
>>> class ExampleSettings(Settings):
...     class ExampleBunch(Bunch):
...         a: Key[str] = Key(default="")
...     key_list: List[Key[int]]         = List(Key(default=0))
...     bunch_list: List[ExampleBunch] = List(ExampleBunch())
>>> settings = ExampleSettings()
>>> settings.bunch_list
[]
>>> settings.bunch_list.appendOne().a.set("demo")
True
>>> settings.bunch_list
[ExampleSettings.ExampleBunch(a=<Key[str]:demo>)]
>>> settings.key_list
[]
>>> settings.key_list.appendOne().set(12)
True
>>> settings.key_list
[<Key[int]:12>]
iter(order: IterOrder | None = None) Iterable[ListItemT][source]

Returns the elements contained in this List, and optionally in its parents, if any.

Parameters:

order

One of List.NO_PARENT, List.PARENT_FIRST, List.PARENT_LAST, or None.

  • If List.NO_PARENT, this method only returns the contents of this List instance.

  • If List.PARENT_FIRST, it recursively returns items from this List’s parents, if any, then from this List itself.

  • If List.PARENT_LAST, it returns items from this List itself, then recursively from its parents, if any.

  • If None, the order set on the List itself at creation time will be used.

Default: None.

Returns:

An iterable on the items contained in this List and optionally its parents.

Example:

>>> from sunset import Key, List
>>> show = lambda l: [key.get() for key in l]
>>> parent = List(Key(default=0))
>>> parent.appendOne().set(1)
True
>>> parent.appendOne().set(2)
True
>>> child = List(Key(default=0))
>>> child.appendOne().set(3)
True
>>> child.appendOne().set(4)
True
>>> show(parent)
[1, 2]
>>> show(child)
[3, 4]
>>> child.setParent(parent)
>>> show(child.iter())
[3, 4]
>>> show(child.iter(order=List.PARENT_FIRST))
[1, 2, 3, 4]
>>> show(child.iter(order=List.PARENT_LAST))
[3, 4, 1, 2]
appendOne() ListItemT[source]

Creates a new item of the type contained in this List, appends it to this List, and returns it.

Returns:

An instance of the item type contained in this List.

insertOne(index: int) ListItemT[source]

Creates a new item of the type contained in this List, inserts it in this List at the given index, and returns it.

Parameters:

index – The list index where to insert the new item.

Returns:

An instance of the item type contained in this List.

onUpdateCall(callback: Callable[[Any], Any]) None[source]

Adds a callback to be called whenever this List, or any item contained in this List, is updated.

The callback will be called with whichever entity was updated as its argument: this List, or one of its items or sub-items.

Adding new items to or deleting items from a List is considered an update of that List, not of the elements in question.

Parameters:

callback – A callable that will be called with one argument of type List, Bunch or Key.

Note

This method does not increase the reference count of the given callback.

skipOnSave() bool

Internal.

Returns whether this entity should be disregarded when saving these settings. For entities with an attribute name, it’s equivalent to checking if the attribute is private (its name starts with an underscore). For entities with a section name, it’s equivalent to checking if the section name is empty.

Can be overridden in subclasses.

Returns:

A bool used internally by the settings saving logic.

setParent(parent: Self | None) None[source]

Makes the given List the parent of this one. If None, remove this List’s parent, if any.

Having a parent does not affect a List’s behavior outside of the iter() method.

This method is for internal purposes and you will typically not need to call it directly.

Parameters:

parent – Either a List that will become this List’s parent, or None. The parent List must have the same type as this List.

Note

A List and its parent, if any, do not increase each other’s reference count.

parent() Self | None[source]

Returns the parent of this List, if any.

Returns:

A List instance of the same type as this one, or None.

children() Iterable[Self][source]

Returns an iterable with the List instances that have this List as their parent.

Returns:

An iterable of List instances of the same type as this one.

class sunset.AutoSaver(settings: SavableProtocol, path: Path | str, *, save_on_update: bool = True, save_on_delete: bool = True, load_on_init: bool = True, save_delay: float = 0.0, raise_on_error: bool = False, logger: Logger | None = None)[source]

AutoSaver is a helper class that can take care of loading and saving settings automatically and safely.

On instantiation, it automatically loads settings from the given file path, if that file exists, unless the load_on_init argument is set to False.

When saving, it uses a two-steps mechanism to ensure the atomicity of the operation. That is to say, the operation either entirely succeeds or entirely fails; AutoSaver will never write an incomplete settings file.

Saving automatically creates the parent directories of the target path if those don’t exist yet.

If the save_on_update argument is set to True, AutoSaver will save the settings whenever they are updated from inside the application. If the save_on_delete argument is set to True, AutoSaver will save the settings when its own instance is about to get deleted.

AutoSaver can also be used as a context manager. Using it as a context manager is the recommended usage.

Parameters:
  • settings – The Settings instance to load to and save from.

  • path – The full path to the file from which to load and save the settings. If this file does not exist yet, it will be created when saving for the first time.

  • save_on_update – Whether to save the settings when they are updated in any way. Default: True.

  • save_on_delete – Whether to save the settings when this AutoSaver instance is garbage collected. Default: True.

  • load_on_init – Whether to load the settings when instantiating this AutoSaver, provided the settings path exists. Default: True.

  • save_delay – How long to wait, in seconds, before actually saving the settings when save_on_update is True and an update occurs. Setting this to a few seconds will batch updates for that long before triggering a save. If set to 0, the save is triggered immediately. Default: 0.

  • raise_on_error – Whether OS errors occurring while loading and saving the settings should raise an exception. If False, errors will only be logged. Default: False.

  • logger – A logger instance that will be used to log OS errors, if any, while loading or saving settings. If none is given, the default root logger will be used.

Example:

>>> from sunset import AutoSaver, Settings
>>> class ExampleSettings(Settings):
...     ...
>>> settings = ExampleSettings()
>>> with AutoSaver(settings, "~/.config/my_app.conf"):
...     main_program_loop(settings)
doLoad() bool[source]

Load the settings from this AutoSaver’s settings file path, if it exists.

Unsaved settings, if any, will be lost.

OS errors occurring while loading, if any, will be logged to the logger provided to this AutoLoader’s constructor.

If this AutoSaver was constructed with the parameter raise_on_error set to True, these OS errors will then be re-raised.

Note that a missing file is not considered an error.

Returns:

True if loading succeeded, else False.

Note

Prefer letting AutoSaver load the settings during its initialization in order to avoid race conditions.

doSave() bool[source]

Unconditionally saves the settings attached to this AutoSaver instance.

This method uses a two-steps mechanism to perform the save, in order to make the save atomic. The settings are first saved to a temporary file, and if successful, that temporary file then replaces the actual settings file.

If the directory where the settings file is located does not exist, this method automatically creates it.

OS errors occurring while saving, if any, will be logged to the logger provided to this AutoLoader’s constructor.

If this AutoSaver was constructed with the parameter raise_on_error set to True, these OS errors will then be re-raised.

Returns:

True if saving succeeded, else False.

saveIfNeeded() bool[source]

Performs a save if and only if there are pending, unsaved changes in the settings attached to this AutoSaver instance.

Returns:

True if a save was performed and succeeded, else False.

class sunset.AutoLoader(settings: Settings, path: str | Path, *, raise_on_error: bool = False, logger: logging.Logger | None = None, _monitor_factory: Callable[[Any, Any], MonitorProtocol] = <class 'sunset.autoloader.MonitorForChange'>)[source]

A helper that loads settings from the given file and reloads them when the file changes.

On instantiation, it automatically loads settings from the given file path.

Afterward, it periodically checks the file for changes and reloads the settings whenever the file is modified. Note that the settings are only reloaded when the file has not been modified for a few seconds, in order to avoid attempting to load a file that is still being written to.

AutoLoader can also be used as a context manager. Using it as a context manager is the recommended usage.

Parameters:
  • settings – The Settings instance to load settings for.

  • path – The full path to the file to load the settings from.

  • raise_on_error – Whether OS errors occurring while loading the settings should raise an exception. If False, errors will only be logged. Default: False.

  • logger – A logger instance that will be used to log OS errors, if any, while loading settings. If none is given, the default root logger will be used.

Example:

>>> from sunset import Settings, AutoLoader
>>> class ExampleSettings(Settings):
...     ...
>>> settings = ExampleSettings()
>>> with AutoLoader(settings, "~/.config/my_app.conf"):
...     main_program_loop(settings)
doLoad() bool[source]

Perform a load now, without waiting for the next detected change in the settings file.

Unsaved settings, if any, will be lost.

OS errors occurring during the load, if any, will be logged to the logger provided to this AutoLoader’s constructor.

If this AutoLoader was constructed with the parameter raise_on_error set to True, these OS errors will then be re-raised.

Note that a missing file is not considered an error.

Returns:

True if loading succeeded, else False.

class sunset.Serializer(*args, **kwargs)[source]

A protocol that describes a way to serialize and deserialize an arbitrary type.

SunsetSettings provides its own serializers for common types (int, float, bool, str, enum.Enum). In order to store an arbitrary type in a Key, users need to provide a serializer for that type when instantiating a Key. That serializer should be an implementation of this protocol.

toStr(value: _T) str[source]

Returns a string representation of the given value, that can be used by fromStr() to reconstruct a copy of that value.

fromStr(string: str) _T | None[source]

Takes a string that represents a serialized instance of a value, and returns a newly created instance that corresponds to that string, or None if the string is not a valid representation of a value for this serializer’s type.

class sunset.Serializable(*args, **kwargs)[source]

A protocol to be implemented by a class in order to enable storing instances of that class in a Key.

The two methods to be implemented are toStr() and (classmethod) fromStr().

toStr() str[source]

Returns a string representation of this instance that can be used by fromStr() to reconstruct a copy of this instance.

classmethod fromStr(string: str) Self | None[source]

Takes a string that represents a serialized instance of this class, and returns a newly created instance that corresponds to that representation, or None if the string is not a valid serialized representation of an instance of this class.