betterconf


Namebetterconf JSON
Version 3.1.0 PyPI version JSON
download
home_pagehttps://github.com/prostomarkeloff/betterconf
SummaryMinimalistic Python library for your configs.
upload_time2024-07-30 18:49:52
maintainerNone
docs_urlNone
authorprostomarkeloff
requires_python<4.0,>=3.8
licenseMIT
keywords configs config env .env
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Minimalistic Python library for your configs.

Betterconf (**better config**) is a Python library for project configuration
management. It allows you define your config like a regular Python class.

Features:

* Easy to hack.
* Less boilerplate.
* Minimal code to do big things.

## Installation

I recommend you to use poetry:

```sh
poetry add betterconf
```

However, you can use pip:

```sh
pip install betterconf
```

## How to?

This is a guide written for betterconf 3.x, earlier versions can work differently

Try to write a simple config:
```python
from betterconf import field, Config

class MyConfig(Config):
    my_var = field("my_var")

cfg = MyConfig()
print(cfg.my_var)
```

Try to run:
```sh
my_var=1 python our_file.py
```

With default values:
```python
from betterconf import field, Config

class MyConfig(Config):
    my_var = field("my_var", default="hello world")
    my_second_var = field("my_second_var", default=lambda: "hi") # can be callable!

cfg = MyConfig()
print(cfg.my_var)
print(cfg.my_second_var)
# hello world
# hi
```

Override values when it's needed (for an example: test cases)
```python
from betterconf import field, Config

class MyConfig(Config):
    my_var = field("my_var", default="hello world")

cfg = MyConfig(my_var="WOW!")
print(cfg.my_var)
# WOW!
```

By default, **betterconf** gets all values from `os.environ` but sometimes we need more.
You can create own `field's value provider` in minutes:

```python
from betterconf import field, Config
from betterconf.config import AbstractProvider

class NameProvider(AbstractProvider):
    def get(self, name: str):
        return name

class Cfg(Config):
    my_var = field("my_var", provider=NameProvider())

cfg = Cfg()
print(cfg.my_var)
# my_var
```

You can specify the class' default provider manually:

```python
from betterconf import field, Config
from betterconf.config import AbstractProvider

class FancyNameProvider(AbstractProvider):
    def get(self, name: str) -> str:
        return f"fancy_{name}"
    
class Cfg(Config):
    _provider_ = FancyNameProvider()
    
    val1 = field("val1")
    val2 = field("val2")
    
cfg = Cfg()
print(cfg.val1, cfg.val2)
# fancy_val1, fancy_val2

# or you can change the provider at initialization moment
cfg = Cfg(_provider_=FancyNameProvider())
...

# However, this won't work with nested configs; their provider will be as it's set in `_provider_` field

```

Also, we can cast our values to python objects (or just manipulate them):

```python
from betterconf import field, Config
# out of the box we have `to_bool` and `to_int`
from betterconf.caster import to_bool, to_int, AbstractCaster


class DashToDotCaster(AbstractCaster):
    def cast(self, val: str):
        return val.replace("-", ".")

to_dot = DashToDotCaster()

class Cfg(Config):
    integer = field("integer", caster=to_int)
    boolean = field("boolean", caster=to_bool)
    dots = field("dashes", caster=to_dot)

cfg = Cfg()
print(cfg.integer, cfg.boolean, cfg.dots)
# -500, True, hello.world

```

```sh
integer=-500 boolean=true dashes=hello-world python our_file.py
```

Sometimes we need to reference one field value in another one.

```python
from betterconf import Config, field, reference_field
from betterconf.caster import to_int

class MyConfig(Config):
    money = field("MONEY_VAR", caster=to_int)
    name = field("NAME_VAR")
    
    money_if_a_lot: int = reference_field(money, func=lambda m: m * 1000)
    greeting: str = reference_field(money, name, func=lambda m, n: f"Hello, my name is {n} and I'm rich for {m}")
    
```

There is a builtin support for constant fields and getting field's value on-fly at any place of code:

```python
from betterconf import value, constant_field, Config
from betterconf.caster import to_int

class Constants(Config):
    admin_id: int = constant_field(1)
    timezone: str = constant_field("UTC+3")
    
debug: bool = value("DEBUG", default=True)
print("Current status of debbuging is ", debug)

# betterconf can be used as a casting framework!
val: int = value(default="123", caster=to_int)
assert val == 123

```


## License
This project is licensed under MIT License.

See [LICENSE](LICENSE) for details.


Made with :heart: by [prostomarkeloff](https://github.com/prostomarkeloff) and our contributors.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/prostomarkeloff/betterconf",
    "name": "betterconf",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.8",
    "maintainer_email": null,
    "keywords": "configs, config, env, .env",
    "author": "prostomarkeloff",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/91/d7/348353068a6df63dd208ebb3c68a7aa8ff9afbe10763dec4bf5a46206eee/betterconf-3.1.0.tar.gz",
    "platform": null,
    "description": "# Minimalistic Python library for your configs.\n\nBetterconf (**better config**) is a Python library for project configuration\nmanagement. It allows you define your config like a regular Python class.\n\nFeatures:\n\n* Easy to hack.\n* Less boilerplate.\n* Minimal code to do big things.\n\n## Installation\n\nI recommend you to use poetry:\n\n```sh\npoetry add betterconf\n```\n\nHowever, you can use pip:\n\n```sh\npip install betterconf\n```\n\n## How to?\n\nThis is a guide written for betterconf 3.x, earlier versions can work differently\n\nTry to write a simple config:\n```python\nfrom betterconf import field, Config\n\nclass MyConfig(Config):\n    my_var = field(\"my_var\")\n\ncfg = MyConfig()\nprint(cfg.my_var)\n```\n\nTry to run:\n```sh\nmy_var=1 python our_file.py\n```\n\nWith default values:\n```python\nfrom betterconf import field, Config\n\nclass MyConfig(Config):\n    my_var = field(\"my_var\", default=\"hello world\")\n    my_second_var = field(\"my_second_var\", default=lambda: \"hi\") # can be callable!\n\ncfg = MyConfig()\nprint(cfg.my_var)\nprint(cfg.my_second_var)\n# hello world\n# hi\n```\n\nOverride values when it's needed (for an example: test cases)\n```python\nfrom betterconf import field, Config\n\nclass MyConfig(Config):\n    my_var = field(\"my_var\", default=\"hello world\")\n\ncfg = MyConfig(my_var=\"WOW!\")\nprint(cfg.my_var)\n# WOW!\n```\n\nBy default, **betterconf** gets all values from `os.environ` but sometimes we need more.\nYou can create own `field's value provider` in minutes:\n\n```python\nfrom betterconf import field, Config\nfrom betterconf.config import AbstractProvider\n\nclass NameProvider(AbstractProvider):\n    def get(self, name: str):\n        return name\n\nclass Cfg(Config):\n    my_var = field(\"my_var\", provider=NameProvider())\n\ncfg = Cfg()\nprint(cfg.my_var)\n# my_var\n```\n\nYou can specify the class' default provider manually:\n\n```python\nfrom betterconf import field, Config\nfrom betterconf.config import AbstractProvider\n\nclass FancyNameProvider(AbstractProvider):\n    def get(self, name: str) -> str:\n        return f\"fancy_{name}\"\n    \nclass Cfg(Config):\n    _provider_ = FancyNameProvider()\n    \n    val1 = field(\"val1\")\n    val2 = field(\"val2\")\n    \ncfg = Cfg()\nprint(cfg.val1, cfg.val2)\n# fancy_val1, fancy_val2\n\n# or you can change the provider at initialization moment\ncfg = Cfg(_provider_=FancyNameProvider())\n...\n\n# However, this won't work with nested configs; their provider will be as it's set in `_provider_` field\n\n```\n\nAlso, we can cast our values to python objects (or just manipulate them):\n\n```python\nfrom betterconf import field, Config\n# out of the box we have `to_bool` and `to_int`\nfrom betterconf.caster import to_bool, to_int, AbstractCaster\n\n\nclass DashToDotCaster(AbstractCaster):\n    def cast(self, val: str):\n        return val.replace(\"-\", \".\")\n\nto_dot = DashToDotCaster()\n\nclass Cfg(Config):\n    integer = field(\"integer\", caster=to_int)\n    boolean = field(\"boolean\", caster=to_bool)\n    dots = field(\"dashes\", caster=to_dot)\n\ncfg = Cfg()\nprint(cfg.integer, cfg.boolean, cfg.dots)\n# -500, True, hello.world\n\n```\n\n```sh\ninteger=-500 boolean=true dashes=hello-world python our_file.py\n```\n\nSometimes we need to reference one field value in another one.\n\n```python\nfrom betterconf import Config, field, reference_field\nfrom betterconf.caster import to_int\n\nclass MyConfig(Config):\n    money = field(\"MONEY_VAR\", caster=to_int)\n    name = field(\"NAME_VAR\")\n    \n    money_if_a_lot: int = reference_field(money, func=lambda m: m * 1000)\n    greeting: str = reference_field(money, name, func=lambda m, n: f\"Hello, my name is {n} and I'm rich for {m}\")\n    \n```\n\nThere is a builtin support for constant fields and getting field's value on-fly at any place of code:\n\n```python\nfrom betterconf import value, constant_field, Config\nfrom betterconf.caster import to_int\n\nclass Constants(Config):\n    admin_id: int = constant_field(1)\n    timezone: str = constant_field(\"UTC+3\")\n    \ndebug: bool = value(\"DEBUG\", default=True)\nprint(\"Current status of debbuging is \", debug)\n\n# betterconf can be used as a casting framework!\nval: int = value(default=\"123\", caster=to_int)\nassert val == 123\n\n```\n\n\n## License\nThis project is licensed under MIT License.\n\nSee [LICENSE](LICENSE) for details.\n\n\nMade with :heart: by [prostomarkeloff](https://github.com/prostomarkeloff) and our contributors.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Minimalistic Python library for your configs.",
    "version": "3.1.0",
    "project_urls": {
        "Documentation": "https://github.com/prostomarkeloff/betterconf",
        "Homepage": "https://github.com/prostomarkeloff/betterconf",
        "Repository": "https://github.com/prostomarkeloff/betterconf"
    },
    "split_keywords": [
        "configs",
        " config",
        " env",
        " .env"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "240a7e9f0fcddfd9d7868f18e42c39ccfd83f98dbb7f4dcfcd8fd3db4654f975",
                "md5": "e024e37c65f5bcad173d58efae68d701",
                "sha256": "75baace602815bc3433eb680ad1778bdf8fb8ad794af99418b349922d355fb7e"
            },
            "downloads": -1,
            "filename": "betterconf-3.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e024e37c65f5bcad173d58efae68d701",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.8",
            "size": 7946,
            "upload_time": "2024-07-30T18:49:51",
            "upload_time_iso_8601": "2024-07-30T18:49:51.472683Z",
            "url": "https://files.pythonhosted.org/packages/24/0a/7e9f0fcddfd9d7868f18e42c39ccfd83f98dbb7f4dcfcd8fd3db4654f975/betterconf-3.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "91d7348353068a6df63dd208ebb3c68a7aa8ff9afbe10763dec4bf5a46206eee",
                "md5": "b27dd5591535b088aa2a9e418f77a5a6",
                "sha256": "e2cc017d8e4ef258974a01c6b4b33ee8927dc7d1bd79c8e2956cf122d7ccbafc"
            },
            "downloads": -1,
            "filename": "betterconf-3.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "b27dd5591535b088aa2a9e418f77a5a6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.8",
            "size": 6532,
            "upload_time": "2024-07-30T18:49:52",
            "upload_time_iso_8601": "2024-07-30T18:49:52.943206Z",
            "url": "https://files.pythonhosted.org/packages/91/d7/348353068a6df63dd208ebb3c68a7aa8ff9afbe10763dec4bf5a46206eee/betterconf-3.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-07-30 18:49:52",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "prostomarkeloff",
    "github_project": "betterconf",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "betterconf"
}
        
Elapsed time: 0.31258s