> ***Savor what you feel and what you see / Things that may not seem important now / But may be tomorrow***
>
> *–Chuck Schuldiner*
# Nostalgic
A drop-in configuration module to save and restore end-user and
application settings.
- No meta-files
- Built using only the Python standard library
- Handle UI syncing
# Install
```python
pip install nostalgic
```
# Motivation
Many configuration packages themselves require configuration files.
This often is extraneous.
Others provide a non-Pythonic API which hinders comprehension. For
example, QSettings looks like
```python
# bad
self.settings.setValue("my_tracked_variable", value)
```
and
```python
# bad
self.settings.value("my_tracked_variable", DEFAULT_SETTINGS["my_tracked_variable"])
```
How you work with a variable depends on whether or not it's been
touched by Qt.
With Nostalgic, these calls look simply like
```python
# good
self.settings.my_tracked_value = value
```
and
```python
# good
self.settings.my_tracked_value
```
Furthermore, most applications likely require only a single
configuration. Nostalgic uses a Configuration singleton for this
reason. Instantiate a Configuration and the next time one is created,
it will be a reference to the already extant Configuration. This
means explicit references to the Configuration don't need to be passed
around.
# Quick Start
A Configuration is a collection of Settings.
- Use a dot to get the Setting value (like an attribute)
- Settings can have a default initial value
- `write()` settings to disk and `read()` them back in
```python
# basic usage
import os # needed only for demonstration
import sys # needed only for demonstration
import nostalgic
if __name__ == '__main__':
# create configuration in current directory
cfg = nostalgic.Configuration("sample_config")
# declare a setting 'foo' with initial value
cfg.add_setting("foo", default="bar")
print(cfg.foo) # "bar"
# change the value
cfg.foo = "baz"
try:
# second run
cfg.read()
print("Config just read")
print(cfg.foo) # "baz"
os.remove(cfg.config_file)
if not os.path.exists(cfg.config_file):
print("Removed config file")
except FileNotFoundError:
# first run, no config yet
cfg.write()
print("Wrote config")
sys.exit()
```
```sh
$ python3 "/home/ahab/Projects/nostalgic/scratch/sample1.py"
bar
Wrote config
$ python3 "/home/ahab/Projects/nostalgic/scratch/sample1.py"
bar
Config just read
baz
Removed config file
```
## Advanced: coordinate a configuration with the UI
Optional setter and getter functions handle updating other parts of your code.
```python
# demonstrate getting on write() and setting on read()
import os # needed only for demonstration
import sys # needed only for demonstration
import nostalgic
class SettingsUI:
def __init__(self):
self.some_ui_thing_the_end_user_uses = 0
class Main:
def __init__(self):
self.cfg = nostalgic.Configuration("sample_config")
self.settings_ui = SettingsUI()
self.cfg.add_setting(
"ui_related_thing",
setter=self.custom_setter, # called on read()
getter=self.custom_getter) # called on write()
def custom_setter(self, value):
print(f"Setting some_ui_thing_the_end_user_uses")
self.settings_ui.some_ui_thing_the_end_user_uses = value
def custom_getter(self):
print(f"Getting some_ui_thing_the_end_user_uses")
return self.settings_ui.some_ui_thing_the_end_user_uses
if __name__ == '__main__':
main = Main()
print(f"some_ui_thing_the_end_user_uses: "
f"{main.settings_ui.some_ui_thing_the_end_user_uses}") # 0, the initial value
try:
# second run
main.cfg.read()
print("Config just read")
print(f"some_ui_thing_the_end_user_uses: "
f"{main.settings_ui.some_ui_thing_the_end_user_uses}")
os.remove(main.cfg.config_file)
if not os.path.exists(main.cfg.config_file):
print("Removed config file")
except FileNotFoundError:
# first run, no config yet
# user changed the UI thing
main.settings_ui.some_ui_thing_the_end_user_uses = 42
main.cfg.write()
print("Wrote config")
sys.exit()
```
The first run gets the end-user value before writing:
```sh
$ python3 "/home/ahab/Projects/nostalgic/scratch/sample2.py"
some_ui_thing_the_end_user_uses: 0
Getting some_ui_thing_the_end_user_uses
Wrote config
```
The second run sets the end-user's previous value:
```sh
$ python3 "/home/ahab/Projects/nostalgic/scratch/sample2.py"
some_ui_thing_the_end_user_uses: 0
Setting some_ui_thing_the_end_user_uses
Config just read
some_ui_thing_the_end_user_uses: 42
Removed config file
```
Use the `sync` parameter of `read()` and `write()` to toggle whether
setters or getters are called.
Use `Configuration.set()` and `Configuration.get()` to apply or update
settings en masse without accessing the hard disk.
# Notes
- Shadowing Configuration methods with Settings of the same name is
possible, although not recommended. A warning will be given.
# Development
Install as "editable" using `pip`:
```sh
~$ cd Projects/nostalgic
~/Projects/nostalgic$ python3 -m venv venv
~/Projects/nostalgic$ source venv/bin/activate
(venv) ~/Projects/nostalgic$ pip install -e .
```
## Testing
Run tests using:
```sh
(venv) ~/Projects/nostalgic$ python3 tests/test_nostalgic.py
```
Raw data
{
"_id": null,
"home_page": "https://codeberg.org/excalamus/nostalgic",
"name": "nostalgic",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": "",
"keywords": "settings,configuration,configure,config,development,application",
"author": "Matt Trzcinski",
"author_email": "matt@excalamus.com",
"download_url": "https://files.pythonhosted.org/packages/d8/46/8f28b4eb0db69d1ca9aa07b074ccf98beab1fc141f03c83a406139e9a9b1/nostalgic-1.4.1.tar.gz",
"platform": null,
"description": "> ***Savor what you feel and what you see / Things that may not seem important now / But may be tomorrow***\n>\n> *\u2013Chuck Schuldiner*\n\n# Nostalgic\nA drop-in configuration module to save and restore end-user and\napplication settings.\n\n- No meta-files\n- Built using only the Python standard library\n- Handle UI syncing\n\n# Install\n```python\npip install nostalgic\n```\n\n# Motivation\nMany configuration packages themselves require configuration files.\nThis often is extraneous.\n\nOthers provide a non-Pythonic API which hinders comprehension. For\nexample, QSettings looks like\n\n```python\n# bad\nself.settings.setValue(\"my_tracked_variable\", value)\n```\n\nand\n\n```python\n# bad\nself.settings.value(\"my_tracked_variable\", DEFAULT_SETTINGS[\"my_tracked_variable\"])\n```\n\nHow you work with a variable depends on whether or not it's been\ntouched by Qt.\n\nWith Nostalgic, these calls look simply like\n\n```python\n# good\nself.settings.my_tracked_value = value\n```\n\nand\n\n```python\n# good\nself.settings.my_tracked_value\n```\n\nFurthermore, most applications likely require only a single\nconfiguration. Nostalgic uses a Configuration singleton for this\nreason. Instantiate a Configuration and the next time one is created,\nit will be a reference to the already extant Configuration. This\nmeans explicit references to the Configuration don't need to be passed\naround.\n\n# Quick Start\nA Configuration is a collection of Settings.\n\n- Use a dot to get the Setting value (like an attribute)\n- Settings can have a default initial value\n- `write()` settings to disk and `read()` them back in\n\n```python\n# basic usage\nimport os # needed only for demonstration\nimport sys # needed only for demonstration\nimport nostalgic\n\n\nif __name__ == '__main__':\n # create configuration in current directory\n cfg = nostalgic.Configuration(\"sample_config\")\n\n # declare a setting 'foo' with initial value\n cfg.add_setting(\"foo\", default=\"bar\")\n\n print(cfg.foo) # \"bar\"\n\n # change the value\n cfg.foo = \"baz\"\n\n try:\n # second run\n cfg.read()\n print(\"Config just read\")\n print(cfg.foo) # \"baz\"\n os.remove(cfg.config_file)\n if not os.path.exists(cfg.config_file):\n print(\"Removed config file\")\n except FileNotFoundError:\n # first run, no config yet\n cfg.write()\n print(\"Wrote config\")\n sys.exit()\n\n```\n\n```sh\n$ python3 \"/home/ahab/Projects/nostalgic/scratch/sample1.py\"\nbar\nWrote config\n\n$ python3 \"/home/ahab/Projects/nostalgic/scratch/sample1.py\"\nbar\nConfig just read\nbaz\nRemoved config file\n```\n\n## Advanced: coordinate a configuration with the UI\nOptional setter and getter functions handle updating other parts of your code.\n\n```python\n# demonstrate getting on write() and setting on read()\nimport os # needed only for demonstration\nimport sys # needed only for demonstration\nimport nostalgic\n\n\nclass SettingsUI:\n\n def __init__(self):\n self.some_ui_thing_the_end_user_uses = 0\n\n\nclass Main:\n\n def __init__(self):\n self.cfg = nostalgic.Configuration(\"sample_config\")\n self.settings_ui = SettingsUI()\n\n self.cfg.add_setting(\n \"ui_related_thing\",\n setter=self.custom_setter, # called on read()\n getter=self.custom_getter) # called on write()\n\n def custom_setter(self, value):\n print(f\"Setting some_ui_thing_the_end_user_uses\")\n self.settings_ui.some_ui_thing_the_end_user_uses = value\n\n def custom_getter(self):\n print(f\"Getting some_ui_thing_the_end_user_uses\")\n return self.settings_ui.some_ui_thing_the_end_user_uses\n\n\nif __name__ == '__main__':\n main = Main()\n\n print(f\"some_ui_thing_the_end_user_uses: \"\n f\"{main.settings_ui.some_ui_thing_the_end_user_uses}\") # 0, the initial value\n\n try:\n # second run\n main.cfg.read()\n print(\"Config just read\")\n print(f\"some_ui_thing_the_end_user_uses: \"\n f\"{main.settings_ui.some_ui_thing_the_end_user_uses}\")\n os.remove(main.cfg.config_file)\n if not os.path.exists(main.cfg.config_file):\n print(\"Removed config file\")\n except FileNotFoundError:\n # first run, no config yet\n\n # user changed the UI thing\n main.settings_ui.some_ui_thing_the_end_user_uses = 42\n main.cfg.write()\n print(\"Wrote config\")\n sys.exit()\n\n```\n\nThe first run gets the end-user value before writing:\n\n```sh\n$ python3 \"/home/ahab/Projects/nostalgic/scratch/sample2.py\"\nsome_ui_thing_the_end_user_uses: 0\nGetting some_ui_thing_the_end_user_uses\nWrote config\n```\n\nThe second run sets the end-user's previous value:\n\n```sh\n$ python3 \"/home/ahab/Projects/nostalgic/scratch/sample2.py\"\nsome_ui_thing_the_end_user_uses: 0\nSetting some_ui_thing_the_end_user_uses\nConfig just read\nsome_ui_thing_the_end_user_uses: 42\nRemoved config file\n\n```\n\nUse the `sync` parameter of `read()` and `write()` to toggle whether\nsetters or getters are called.\n\nUse `Configuration.set()` and `Configuration.get()` to apply or update\nsettings en masse without accessing the hard disk.\n\n# Notes\n- Shadowing Configuration methods with Settings of the same name is\n possible, although not recommended. A warning will be given.\n\n# Development\nInstall as \"editable\" using `pip`:\n\n```sh\n~$ cd Projects/nostalgic\n~/Projects/nostalgic$ python3 -m venv venv\n~/Projects/nostalgic$ source venv/bin/activate\n(venv) ~/Projects/nostalgic$ pip install -e .\n```\n\n## Testing\nRun tests using:\n\n```sh\n(venv) ~/Projects/nostalgic$ python3 tests/test_nostalgic.py\n```\n",
"bugtrack_url": null,
"license": "",
"summary": "A drop-in configuration module to save and restore end-user and application settings",
"version": "1.4.1",
"split_keywords": [
"settings",
"configuration",
"configure",
"config",
"development",
"application"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "31809a8ea41cdd40eb34f31f01ea82f5",
"sha256": "e42e2ab6462c0b69c404bba81126f3f96fc82c36a95e3200df12e860dd3d8895"
},
"downloads": -1,
"filename": "nostalgic-1.4.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "31809a8ea41cdd40eb34f31f01ea82f5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 6967,
"upload_time": "2022-06-21T00:41:24",
"upload_time_iso_8601": "2022-06-21T00:41:24.700927Z",
"url": "https://files.pythonhosted.org/packages/b2/c6/b7a514929d544533a49e89a298bbad11922328b13ca8bd557e9484272af5/nostalgic-1.4.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "c976d1d021c863222520b028dac3272d",
"sha256": "8cb093dc27a949beb8b6671bf10ca5b8c991c140df1ae8fd948e0eaa9317eaf2"
},
"downloads": -1,
"filename": "nostalgic-1.4.1.tar.gz",
"has_sig": false,
"md5_digest": "c976d1d021c863222520b028dac3272d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 8531,
"upload_time": "2022-06-21T00:41:26",
"upload_time_iso_8601": "2022-06-21T00:41:26.378592Z",
"url": "https://files.pythonhosted.org/packages/d8/46/8f28b4eb0db69d1ca9aa07b074ccf98beab1fc141f03c83a406139e9a9b1/nostalgic-1.4.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-06-21 00:41:26",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "nostalgic"
}