Name | thatway JSON |
Version |
0.6.0
JSON |
| download |
home_page | |
Summary | |
upload_time | 2023-08-09 12:04:56 |
maintainer | |
docs_url | None |
author | Justin Lorieau |
requires_python | >=3.8 |
license | |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
ThatWay
=======
.. image:: https://img.shields.io/pypi/v/thatway.svg
:target: https://pypi.org/project/thatway/
:alt: PyPI version
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Black formatted
Thatway is a simple, decentralized configuration manager.
Place your configuration settings throughout your application--not in a
centralized file or submodule--and thatway collects them and allows you to
modify them through configurations files. Decentralized configuration reduces
the complexity of submodules and the coupling between submodules.
Quickstart
----------
1. Create a package with settings.
`examples/mypkg/moduleA/file.py <examples/mypkg/moduleA/file.py>`_
.. code-block:: python
from thatway import Setting
class FirstClass:
my_attribute = Setting(True, desc="Whether 'my_attribute' is an attribute")
max_instances = Setting(3, desc="Maximum number of instances")
`examples/mypkg/moduleB/file.py <examples/mypkg/moduleB/file.py>`_
.. code-block:: python
from thatway import config, Setting
config.moduleB.msg = Setting("This is my message")
2. View settings:
.. code-block:: python
import examples.mypkg
from thatway import config
print(config.dumps_yaml())
FirstClass:
my_attribute: true # Whether 'my_attribute' is an antribue
max_instances: 3 # Maximum number of instances
moduleB:
msg: This is my message
3. Load different settings:
`examples/mypkg/new_settings.yaml <examples/mypkg/new_settings.yaml>`_
.. code-block:: yaml
FirstClass:
my_attribute: false
max_instances: 2
with python:
.. code-block:: python
from pathlib import Path
import examples.mypkg
from thatway import config
config.load_yaml(str(Path("examples") / "mypkg" / "new_settings.yaml"))
print(config.dumps_yaml())
FirstClass:
my_attribute: false # Whether 'my_attribute' is an antribue
max_instances: 2 # Maximum number of instances
moduleB:
msg: This is my message
Rules
-----
The following are design decisions on the behavior of thatway's configuration
manager.
1. Configure directly
~~~~~~~~~~~~~~~~~~~~~
Settings can be set directly on the config object.
.. code-block:: python
>>> from thatway import config, Setting
>>> config.a = Setting(3)
>>> config.a
3
>>> config.nested.b = Setting("nested")
>>> config.nested.b
'nested'
Trying to set an entry in the config without a setting raises an exception.
.. code-block:: python
>>> from thatway import config
>>> config.new_value = 3
Traceback (most recent call last):
...
thatway.base.ConfigException: Only Settings can be inserted in the Config
2. Configure object attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Settings can be set as object attributes.
.. code-block:: python
>>> from thatway import Setting
>>> class Obj:
... attribute = Setting("my value")
>>> obj = Obj()
>>> obj.attribute
'my value'
3. Configuration locking
~~~~~~~~~~~~~~~~~~~~~~~~
Settings cannot be accidentally modified. Once they're set, they're set until
the config's ``update`` or ``load`` methods are used.
.. code-block:: python
>>> from thatway import Setting
>>> config.b = Setting(3)
>>> config.b
3
>>> config.b = Setting(5) # oops!
Traceback (most recent call last):
...
thatway.base.ConfigException: Entry 'b' already in the Config--use a Config.update or load method to change its value.
>>> config.b = 5 # oops!
Traceback (most recent call last):
...
thatway.base.ConfigException: Only Settings can be inserted in the Config
>>> config.update({'b': 5})
>>> config.b
5
The one exception is that settings defined on a class can be replaced on the
class itself--not a class instance. This is because settings act as
descriptors for classes.
4. Type Enforcement
~~~~~~~~~~~~~~~~~~~
Setting types are checked and maintained with either the setting's value type,
or the ``allowed_types`` optional argument.
.. code-block:: python
>>> from thatway import Setting
>>> config.c = Setting(5, allowed_types=(int, str))
>>> config.update({'c': 'my new c value'})
>>> config.c
'my new c value'
>>> config.d = Setting(6)
>>> config.update({'d': 'my new d value'})
Traceback (most recent call last):
...
ValueError: Could not convert 'my new d value' into any of the following types: [<class 'int'>]
6. Missing Settings
~~~~~~~~~~~~~~~~~~~
Trying to update a setting that doesn't exist is not possible. This behavior
is designed to avoid trying to change a setting but using an incorrect setting
name and location.
.. code-block:: python
>>> from thatway import Setting
>>> config.update({'e': 'unassigned'}) # 'f' doesn't exist in config
Traceback (most recent call last):
...
KeyError: "Tried assigning setting with name 'e' which does not exist in the Config"
7. Immutable Settings Values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Setting values can only be immutable objects.
.. code-block::
>>> from thatway import Setting
>>> config.cli.color = Setting(True)
>>> config.cli.default_filenames = Setting(('a.html', 'b.html'))
>>> config.cli.value_list = Setting([1, 2]) # lists are mutable
Traceback (most recent call last):
...
thatway.base.ConfigException: Setting value '[1, 2]' must be immutable
Features
--------
1. Setting descriptions
~~~~~~~~~~~~~~~~~~~~~~~~~
Settings can include descriptions.
.. code-block:: python
>>> from thatway import Setting
>>> config.e = Setting(4, desc="The 'e' attribute")
2. Yaml processing
~~~~~~~~~~~~~~~~~~
Settings can be dumped in `yaml <https://yaml.org>`_.
``config.dumps_yaml()``
.. code-block:: yaml
Obj:
a: 1
b: name # The 'b' setting
nested:
c: true
And `yaml <https://yaml.org>`_ strings or files can be loaded with
``config.loads_yaml(string)`` and ``config.load_yaml(filepath)``, respectively.
3. Toml processing
~~~~~~~~~~~~~~~~~~
Settings can be dumped in `toml <https://toml.io/en/>`_.
``config.dumps_toml()``
.. code-block:: toml
[Obj]
a = 1
b = "name" # The 'b' setting
[nested]
c = true
And `toml <https://toml.io/en/>`_ strings or files can be loaded with
``config.loads_toml(string)`` and ``config.load_toml(filepath)``, respectively.
Raw data
{
"_id": null,
"home_page": "",
"name": "thatway",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "",
"author": "Justin Lorieau",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/59/08/4c0f5f17cf9a6cdb6c68189871f5bf0cc1eacf4d446dae671d29e756c0a5/thatway-0.6.0.tar.gz",
"platform": null,
"description": "ThatWay\n=======\n.. image:: https://img.shields.io/pypi/v/thatway.svg\n :target: https://pypi.org/project/thatway/\n :alt: PyPI version\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Black formatted\n\nThatway is a simple, decentralized configuration manager.\n\nPlace your configuration settings throughout your application--not in a\ncentralized file or submodule--and thatway collects them and allows you to\nmodify them through configurations files. Decentralized configuration reduces\nthe complexity of submodules and the coupling between submodules.\n\nQuickstart\n----------\n\n1. Create a package with settings.\n\n`examples/mypkg/moduleA/file.py <examples/mypkg/moduleA/file.py>`_\n\n.. code-block:: python\n\n from thatway import Setting\n\n\n class FirstClass:\n my_attribute = Setting(True, desc=\"Whether 'my_attribute' is an attribute\")\n\n max_instances = Setting(3, desc=\"Maximum number of instances\")\n\n`examples/mypkg/moduleB/file.py <examples/mypkg/moduleB/file.py>`_\n\n.. code-block:: python\n\n from thatway import config, Setting\n\n config.moduleB.msg = Setting(\"This is my message\")\n\n2. View settings:\n\n.. code-block:: python\n\n import examples.mypkg\n from thatway import config\n print(config.dumps_yaml())\n FirstClass:\n my_attribute: true # Whether 'my_attribute' is an antribue\n max_instances: 3 # Maximum number of instances\n moduleB:\n msg: This is my message\n\n3. Load different settings:\n\n`examples/mypkg/new_settings.yaml <examples/mypkg/new_settings.yaml>`_\n\n.. code-block:: yaml\n\n FirstClass:\n my_attribute: false\n max_instances: 2\n\nwith python:\n\n.. code-block:: python\n\n from pathlib import Path\n import examples.mypkg\n from thatway import config\n config.load_yaml(str(Path(\"examples\") / \"mypkg\" / \"new_settings.yaml\"))\n print(config.dumps_yaml())\n FirstClass:\n my_attribute: false # Whether 'my_attribute' is an antribue\n max_instances: 2 # Maximum number of instances\n moduleB:\n msg: This is my message\n\nRules\n-----\n\nThe following are design decisions on the behavior of thatway's configuration\nmanager.\n\n1. Configure directly\n~~~~~~~~~~~~~~~~~~~~~\n\nSettings can be set directly on the config object.\n\n.. code-block:: python\n\n >>> from thatway import config, Setting\n >>> config.a = Setting(3)\n >>> config.a\n 3\n >>> config.nested.b = Setting(\"nested\")\n >>> config.nested.b\n 'nested'\n\nTrying to set an entry in the config without a setting raises an exception.\n\n.. code-block:: python\n\n >>> from thatway import config\n >>> config.new_value = 3\n Traceback (most recent call last):\n ...\n thatway.base.ConfigException: Only Settings can be inserted in the Config\n\n2. Configure object attributes\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSettings can be set as object attributes.\n\n.. code-block:: python\n\n >>> from thatway import Setting\n >>> class Obj:\n ... attribute = Setting(\"my value\")\n >>> obj = Obj()\n >>> obj.attribute\n 'my value'\n\n3. Configuration locking\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nSettings cannot be accidentally modified. Once they're set, they're set until\nthe config's ``update`` or ``load`` methods are used.\n\n.. code-block:: python\n\n >>> from thatway import Setting\n >>> config.b = Setting(3)\n >>> config.b\n 3\n >>> config.b = Setting(5) # oops!\n Traceback (most recent call last):\n ...\n thatway.base.ConfigException: Entry 'b' already in the Config--use a Config.update or load method to change its value.\n >>> config.b = 5 # oops!\n Traceback (most recent call last):\n ...\n thatway.base.ConfigException: Only Settings can be inserted in the Config\n >>> config.update({'b': 5})\n >>> config.b\n 5\n\nThe one exception is that settings defined on a class can be replaced on the\nclass itself--not a class instance. This is because settings act as\ndescriptors for classes.\n\n4. Type Enforcement\n~~~~~~~~~~~~~~~~~~~\n\nSetting types are checked and maintained with either the setting's value type,\nor the ``allowed_types`` optional argument.\n\n.. code-block:: python\n\n >>> from thatway import Setting\n >>> config.c = Setting(5, allowed_types=(int, str))\n >>> config.update({'c': 'my new c value'})\n >>> config.c\n 'my new c value'\n >>> config.d = Setting(6)\n >>> config.update({'d': 'my new d value'})\n Traceback (most recent call last):\n ...\n ValueError: Could not convert 'my new d value' into any of the following types: [<class 'int'>]\n\n6. Missing Settings\n~~~~~~~~~~~~~~~~~~~\n\nTrying to update a setting that doesn't exist is not possible. This behavior\nis designed to avoid trying to change a setting but using an incorrect setting\nname and location.\n\n.. code-block:: python\n\n >>> from thatway import Setting\n >>> config.update({'e': 'unassigned'}) # 'f' doesn't exist in config\n Traceback (most recent call last):\n ...\n KeyError: \"Tried assigning setting with name 'e' which does not exist in the Config\"\n\n7. Immutable Settings Values\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSetting values can only be immutable objects.\n\n.. code-block::\n\n >>> from thatway import Setting\n >>> config.cli.color = Setting(True)\n >>> config.cli.default_filenames = Setting(('a.html', 'b.html'))\n >>> config.cli.value_list = Setting([1, 2]) # lists are mutable\n Traceback (most recent call last):\n ...\n thatway.base.ConfigException: Setting value '[1, 2]' must be immutable\n\nFeatures\n--------\n\n1. Setting descriptions\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSettings can include descriptions.\n\n.. code-block:: python\n\n >>> from thatway import Setting\n >>> config.e = Setting(4, desc=\"The 'e' attribute\")\n\n2. Yaml processing\n~~~~~~~~~~~~~~~~~~\n\nSettings can be dumped in `yaml <https://yaml.org>`_.\n\n``config.dumps_yaml()``\n\n.. code-block:: yaml\n\n Obj:\n a: 1\n b: name # The 'b' setting\n nested:\n c: true\n\nAnd `yaml <https://yaml.org>`_ strings or files can be loaded with\n``config.loads_yaml(string)`` and ``config.load_yaml(filepath)``, respectively.\n\n3. Toml processing\n~~~~~~~~~~~~~~~~~~\n\nSettings can be dumped in `toml <https://toml.io/en/>`_.\n\n``config.dumps_toml()``\n\n.. code-block:: toml\n\n [Obj]\n a = 1\n b = \"name\" # The 'b' setting\n [nested]\n c = true\n\nAnd `toml <https://toml.io/en/>`_ strings or files can be loaded with\n``config.loads_toml(string)`` and ``config.load_toml(filepath)``, respectively.\n",
"bugtrack_url": null,
"license": "",
"summary": "",
"version": "0.6.0",
"project_urls": {
"Homepage": "https://github.com/jlorieau/thatway"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b5bb993dab3ae29aa834c6863287da971b7da6071c6a89aae9ba1f8158b39dc7",
"md5": "9285db2e84007e0ff3a1b5761b8970aa",
"sha256": "d16403381f802f00eadd96612b8ee8756411d5826c004ae378ac43266ec77ba9"
},
"downloads": -1,
"filename": "thatway-0.6.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9285db2e84007e0ff3a1b5761b8970aa",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 8089,
"upload_time": "2023-08-09T12:04:54",
"upload_time_iso_8601": "2023-08-09T12:04:54.754710Z",
"url": "https://files.pythonhosted.org/packages/b5/bb/993dab3ae29aa834c6863287da971b7da6071c6a89aae9ba1f8158b39dc7/thatway-0.6.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "59084c0f5f17cf9a6cdb6c68189871f5bf0cc1eacf4d446dae671d29e756c0a5",
"md5": "04da424929dde8bf592207a906477a0f",
"sha256": "dbab86a53182cfe0fc71ca0b9c57540a46e4f6670add17e4f5f6db7ec4b6cf58"
},
"downloads": -1,
"filename": "thatway-0.6.0.tar.gz",
"has_sig": false,
"md5_digest": "04da424929dde8bf592207a906477a0f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 11211,
"upload_time": "2023-08-09T12:04:56",
"upload_time_iso_8601": "2023-08-09T12:04:56.197772Z",
"url": "https://files.pythonhosted.org/packages/59/08/4c0f5f17cf9a6cdb6c68189871f5bf0cc1eacf4d446dae671d29e756c0a5/thatway-0.6.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-09 12:04:56",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jlorieau",
"github_project": "thatway",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "thatway"
}