xsettings


Namexsettings JSON
Version 1.4.0 PyPI version JSON
download
home_pagehttps://github.com/xyngular/py-xsettings
SummaryWays to document, centeralize, retreive and validate settings.
upload_time2023-05-24 19:07:00
maintainer
docs_urlNone
authorJosh Orr
requires_python>=3.8,<4.0
license
keywords settings lazy configuration
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.8|%203.9|%203.10|%203.11&color=blue?style=flat-square&logo=python)
![PyPI version](https://badge.fury.io/py/xsettings.svg?)

- [Introduction](#introduction)
- [Documentation](#documentation)
- [Install](#install)
- [Quick Start](#quick-start)
- [Licensing](#licensing)

# Introduction

Helps document and centralizing settings in a python project/library.

Facilitates looking up BaseSettings from `retrievers`, such as an environmental variable retriever.

Converts and standardizes any retrieved values to the type-hint on the setting attribute (such as bool, int, datetime, etc).

Interface to provide own custom retrievers, to grab settings/configuration from wherever you want.

Retrievers can be stacked, so multiple ones can be consulted when retrieving a setting.

See **[xsettings docs](https://xyngular.github.io/py-xsettings/latest/)**.

# Documentation

**[📄 Detailed Documentation](https://xyngular.github.io/py-xsettings/latest/)** | **[🐍 PyPi](https://pypi.org/project/xsettings/)**

# Install

```bash
# via pip
pip install xsettings

# via poetry
poetry add xsettings
```

# Quick Start

```python
from xsettings import EnvVarSettings, SettingsField
from xsettings.errors import SettingsValueError
from typing import Optional
import dataclasses
import os

# Used to showcase looking up env-vars automatically:
os.environ['app_version'] = '1.2.3'

# Used to showcase complex setting types:
@dataclasses.dataclass
class DBConfig:
    @classmethod
    def from_dict(cls, values: dict):
        return DBConfig(**values)

    user: str
    host: str
    password: str


# Some defined settings:
class MySettings(EnvVarSettings):
    app_env: str = 'dev'
    app_version: str
    api_endpoint_url: str
    
    some_number: int

    # For Full Customization, allocate SettingsField,
    # In this case an alternate setting lookup-name
    # if you want the attribute name to differ from lookup name:
    token: Optional[str] = SettingsField(name='API_TOKEN')

    # Or if you wanted a custom-converter for a more complex obj:
    db_config: DBConfig = SettingsField(
        converter=DBConfig.from_dict
    )

# BaseSettings subclasses are singleton-like dependencies that are
# also injectables and lazily-created on first-use.
# YOu can use a special `BaseSettings.grab()` class-method to
# get the current settings object.
#
# So you can grab the current MySettings object lazily via
# its `grab` class method:
MySettings.grab().some_number = 3

assert MySettings.grab().some_number == 3

# You can also use a proxy-object, it will lookup and use
# the current settings object each time its used:
my_settings = MySettings.proxy()

# Here I showcase setting a dict here and using the converter
# I defined on the SettingsField to convert it for me:
my_settings.db_config = {
    'user': 'my-user',
    'password': 'my-password',
    'host': 'my-host'
}


expected = DBConfig(
    user='my-user',
    password='my-password',
    host='my-host'
)

# The dict gets converted automatically to the DBConfig obj:
assert MySettings.grab().db_config == expected

# If you set a setting with the same/exact type as
# it's type-hint, then it won't call the converter:
my_settings.db_config = expected

# It's the same exact object-instance still (ie: not changed/converted):
assert my_settings.db_config is expected


# Will use the default value of `dev` (default value on class)
# since it was not set to anything else and there is no env-var for it:
assert my_settings.app_env == 'dev'

# EnvVarSettings (superclass) is configured to use the EnvVar retriever,
# and so it will find this in the environmental vars since it was not
# explicitly set to anything on settings object:
assert my_settings.app_version == '1.2.3'

# Any BaseSettings subclass can use dependency-injection:
assert my_settings.token is None

with MySettings(token='my-token'):
    assert my_settings.token == 'my-token'

    # Parent is still consulted for any settings unset on child but set on parent:
    assert my_settings.db_config == expected

    # Can set settings like you expect,
    # this will go into the child created in above `with` statement:
    my_settings.app_env = 'prod'

    assert my_settings.app_env == 'prod'

# After `with` child is not the current settings object anymore,
# reverts back to what it was before:
assert my_settings.token is None

try:
    # If a setting is undefined and required (ie: not-optional),
    # and it was not set to anything nor is there a default or an env-var for it;
    # BaseSettings will raise an exception when getting it:
    print(my_settings.api_endpoint_url)
except SettingsValueError as e:
    assert True
else:
    assert False

try:
    # `SettingsValueError` inherits from both AttributeError and ValueError,
    # as the error could be due to either aspect; so you can also do an except
    # for either standard error:
    print(my_settings.api_endpoint_url)
except ValueError as e:
    assert True
else:
    assert False
```



# Licensing

This library is licensed under the MIT-0 License. See the LICENSE file.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/xyngular/py-xsettings",
    "name": "xsettings",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "settings,lazy,configuration",
    "author": "Josh Orr",
    "author_email": "josh@orr.blue",
    "download_url": "https://files.pythonhosted.org/packages/08/64/ec581d934b4b2ae2ce79b593cdb0eb2a7431dd470e75ac830e2b6efd74e6/xsettings-1.4.0.tar.gz",
    "platform": null,
    "description": "![PythonSupport](https://img.shields.io/static/v1?label=python&message=%203.8|%203.9|%203.10|%203.11&color=blue?style=flat-square&logo=python)\n![PyPI version](https://badge.fury.io/py/xsettings.svg?)\n\n- [Introduction](#introduction)\n- [Documentation](#documentation)\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Licensing](#licensing)\n\n# Introduction\n\nHelps document and centralizing settings in a python project/library.\n\nFacilitates looking up BaseSettings from `retrievers`, such as an environmental variable retriever.\n\nConverts and standardizes any retrieved values to the type-hint on the setting attribute (such as bool, int, datetime, etc).\n\nInterface to provide own custom retrievers, to grab settings/configuration from wherever you want.\n\nRetrievers can be stacked, so multiple ones can be consulted when retrieving a setting.\n\nSee **[xsettings docs](https://xyngular.github.io/py-xsettings/latest/)**.\n\n# Documentation\n\n**[\ud83d\udcc4 Detailed Documentation](https://xyngular.github.io/py-xsettings/latest/)** | **[\ud83d\udc0d PyPi](https://pypi.org/project/xsettings/)**\n\n# Install\n\n```bash\n# via pip\npip install xsettings\n\n# via poetry\npoetry add xsettings\n```\n\n# Quick Start\n\n```python\nfrom xsettings import EnvVarSettings, SettingsField\nfrom xsettings.errors import SettingsValueError\nfrom typing import Optional\nimport dataclasses\nimport os\n\n# Used to showcase looking up env-vars automatically:\nos.environ['app_version'] = '1.2.3'\n\n# Used to showcase complex setting types:\n@dataclasses.dataclass\nclass DBConfig:\n    @classmethod\n    def from_dict(cls, values: dict):\n        return DBConfig(**values)\n\n    user: str\n    host: str\n    password: str\n\n\n# Some defined settings:\nclass MySettings(EnvVarSettings):\n    app_env: str = 'dev'\n    app_version: str\n    api_endpoint_url: str\n    \n    some_number: int\n\n    # For Full Customization, allocate SettingsField,\n    # In this case an alternate setting lookup-name\n    # if you want the attribute name to differ from lookup name:\n    token: Optional[str] = SettingsField(name='API_TOKEN')\n\n    # Or if you wanted a custom-converter for a more complex obj:\n    db_config: DBConfig = SettingsField(\n        converter=DBConfig.from_dict\n    )\n\n# BaseSettings subclasses are singleton-like dependencies that are\n# also injectables and lazily-created on first-use.\n# YOu can use a special `BaseSettings.grab()` class-method to\n# get the current settings object.\n#\n# So you can grab the current MySettings object lazily via\n# its `grab` class method:\nMySettings.grab().some_number = 3\n\nassert MySettings.grab().some_number == 3\n\n# You can also use a proxy-object, it will lookup and use\n# the current settings object each time its used:\nmy_settings = MySettings.proxy()\n\n# Here I showcase setting a dict here and using the converter\n# I defined on the SettingsField to convert it for me:\nmy_settings.db_config = {\n    'user': 'my-user',\n    'password': 'my-password',\n    'host': 'my-host'\n}\n\n\nexpected = DBConfig(\n    user='my-user',\n    password='my-password',\n    host='my-host'\n)\n\n# The dict gets converted automatically to the DBConfig obj:\nassert MySettings.grab().db_config == expected\n\n# If you set a setting with the same/exact type as\n# it's type-hint, then it won't call the converter:\nmy_settings.db_config = expected\n\n# It's the same exact object-instance still (ie: not changed/converted):\nassert my_settings.db_config is expected\n\n\n# Will use the default value of `dev` (default value on class)\n# since it was not set to anything else and there is no env-var for it:\nassert my_settings.app_env == 'dev'\n\n# EnvVarSettings (superclass) is configured to use the EnvVar retriever,\n# and so it will find this in the environmental vars since it was not\n# explicitly set to anything on settings object:\nassert my_settings.app_version == '1.2.3'\n\n# Any BaseSettings subclass can use dependency-injection:\nassert my_settings.token is None\n\nwith MySettings(token='my-token'):\n    assert my_settings.token == 'my-token'\n\n    # Parent is still consulted for any settings unset on child but set on parent:\n    assert my_settings.db_config == expected\n\n    # Can set settings like you expect,\n    # this will go into the child created in above `with` statement:\n    my_settings.app_env = 'prod'\n\n    assert my_settings.app_env == 'prod'\n\n# After `with` child is not the current settings object anymore,\n# reverts back to what it was before:\nassert my_settings.token is None\n\ntry:\n    # If a setting is undefined and required (ie: not-optional),\n    # and it was not set to anything nor is there a default or an env-var for it;\n    # BaseSettings will raise an exception when getting it:\n    print(my_settings.api_endpoint_url)\nexcept SettingsValueError as e:\n    assert True\nelse:\n    assert False\n\ntry:\n    # `SettingsValueError` inherits from both AttributeError and ValueError,\n    # as the error could be due to either aspect; so you can also do an except\n    # for either standard error:\n    print(my_settings.api_endpoint_url)\nexcept ValueError as e:\n    assert True\nelse:\n    assert False\n```\n\n\n\n# Licensing\n\nThis library is licensed under the MIT-0 License. See the LICENSE file.\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Ways to document, centeralize, retreive and validate settings.",
    "version": "1.4.0",
    "project_urls": {
        "Homepage": "https://github.com/xyngular/py-xsettings",
        "Repository": "https://github.com/xyngular/py-xsettings"
    },
    "split_keywords": [
        "settings",
        "lazy",
        "configuration"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b5513c4d196b259088ff75b9b90aaa79220e052f74943b1302c3f946cfc37e07",
                "md5": "8c3e2104379d6bde98374fee42e8f9ba",
                "sha256": "dbba45b78670335a4e07d5d137c60a5f9e2c058d7899f7476b8e1b710bc8ad40"
            },
            "downloads": -1,
            "filename": "xsettings-1.4.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8c3e2104379d6bde98374fee42e8f9ba",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 22462,
            "upload_time": "2023-05-24T19:06:58",
            "upload_time_iso_8601": "2023-05-24T19:06:58.498904Z",
            "url": "https://files.pythonhosted.org/packages/b5/51/3c4d196b259088ff75b9b90aaa79220e052f74943b1302c3f946cfc37e07/xsettings-1.4.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0864ec581d934b4b2ae2ce79b593cdb0eb2a7431dd470e75ac830e2b6efd74e6",
                "md5": "5eb05845779d591ea945f1f1b0a9bed2",
                "sha256": "b8eb46add0ea378aa284ed983c23c3e9c0eea65c9199529b53bab285fff2a60e"
            },
            "downloads": -1,
            "filename": "xsettings-1.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "5eb05845779d591ea945f1f1b0a9bed2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 21385,
            "upload_time": "2023-05-24T19:07:00",
            "upload_time_iso_8601": "2023-05-24T19:07:00.257442Z",
            "url": "https://files.pythonhosted.org/packages/08/64/ec581d934b4b2ae2ce79b593cdb0eb2a7431dd470e75ac830e2b6efd74e6/xsettings-1.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-24 19:07:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "xyngular",
    "github_project": "py-xsettings",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "xsettings"
}
        
Elapsed time: 0.07985s