|
1 | 1 | # Magic Config
|
2 |
| -A simple library for easy handling of .env files and environment variables configurations. |
3 | 2 |
|
4 |
| -This library is a class for working with configurations. The class is implemented as a singleton, which allows you to always have exactly one instance of the same data registry everywhere. |
| 3 | +A simple library for easy handling of `.env` files and environment-variables configurations. |
| 4 | +Implements a singleton class so that everywhere in your code you get exactly one shared configuration registry. |
5 | 5 |
|
6 |
| -The configuration data itself is taken from the .env file or from environment variables. |
| 6 | +> **Requires:** Python 3.9+ (we make use of `str.removeprefix`/`removesuffix` from PEP 616 and modern typing features; Python 3.13 is recommended for full support of `Self`, `Final`, `|`-unions, etc.) |
| 7 | +
|
| 8 | +The configuration data is loaded in this order of precedence: |
| 9 | + |
| 10 | +1. **Explicit constructor arguments** (positional `data: dict` or any `**kwargs`) |
| 11 | +2. **`ENV_FILE` environment variable** (if set, points to your `.env` file) |
| 12 | +3. **`env_file=` constructor argument** (pass a path when instantiating) |
| 13 | +4. **Default `.env` in the current working directory** |
| 14 | +5. **Raw OS environment variables** |
| 15 | + |
| 16 | +Built-in support for: |
| 17 | + |
| 18 | +- **Case-insensitive** access (`Config.DEBUG`, `Config.debug`, `Config["Debug"]` all work) |
| 19 | +- **Automatic type casting** via a `magic.config` file in your project root |
| 20 | +- **Automatic MongoDB/MySQL URI generation** from individual host/user/password vars |
| 21 | +- **Flask integration** via `app.config.from_mapping(Config)` or `app.config.from_object(Config)` (with a `__dir__` override) |
| 22 | + |
| 23 | +--- |
7 | 24 |
|
8 | 25 | ## Installation
|
9 |
| -``` |
| 26 | + |
| 27 | +```bash |
10 | 28 | pip install magic-config
|
11 | 29 | ```
|
12 |
| - |
13 | 30 | ## Upgrade
|
14 | 31 | ```
|
15 | 32 | pip install --upgrade magic-config
|
16 | 33 | ```
|
17 | 34 |
|
18 |
| -Pypi url: https://pypi.org/project/magic-config/ |
19 |
| - |
| 35 | +PyPI URL: https://pypi.org/project/magic-config/ |
20 | 36 |
|
21 |
| - |
22 |
| -## Example: |
23 |
| -```sh |
24 |
| -DEBUG=1 myapp.py |
| 37 | +## Quickstart |
| 38 | +### 1. Simple usage |
| 39 | +```bash |
| 40 | +DEBUG=1 python myapp.py |
25 | 41 | ```
|
26 | 42 |
|
27 |
| -My app script: |
28 |
| - |
29 |
| -```py |
| 43 | +```python |
30 | 44 | from magic_config import Config
|
31 | 45 |
|
32 |
| -# You can access to variables as property of class object |
33 | 46 | if Config.DEBUG:
|
34 |
| - ... |
| 47 | + print("Debug mode is ON") |
| 48 | +``` |
35 | 49 |
|
36 |
| -# You can access to variables in lower case (and camel case, and other case) |
| 50 | +You can also do: |
| 51 | +```python |
37 | 52 | if Config.debug:
|
38 |
| - ... |
39 |
| - |
40 |
| -# You can access to variables as key of dict object |
41 |
| -if Config["debug"]: |
42 |
| - ... |
| 53 | + ... |
| 54 | +if Config["DeBuG"]: |
| 55 | + ... |
43 | 56 | ```
|
44 | 57 |
|
45 |
| -## Configure custom variables |
46 |
| -```py |
47 |
| -# You can add variables to the object |
| 58 | +### 2. Custom variables on the fly |
| 59 | +You can pass your own values when you first import/instantiate: |
| 60 | +```python |
| 61 | +from magic_config import MagicConfig, Config |
| 62 | +from pathlib import Path |
48 | 63 |
|
49 |
| -# as dict |
50 |
| -MagicConfig({ |
51 |
| - "Number": 456, |
52 |
| - "Boolean": True |
53 |
| -}) |
| 64 | +# Positional dict + kwargs |
| 65 | +MagicConfig( |
| 66 | + {"NUMBER": 456}, |
| 67 | + Boolean=True, |
| 68 | + BASE_DIR=Path(__file__).resolve().parent |
| 69 | +) |
54 | 70 |
|
55 |
| -# as named arguments |
| 71 | +# Or only kwargs |
56 | 72 | MagicConfig(
|
57 |
| - Number=456, |
58 |
| - Boolean=True |
| 73 | + BASE_DIR=Path(__file__).resolve().parent |
59 | 74 | )
|
| 75 | + |
| 76 | +# Afterwards you can read: |
| 77 | +print(Config.BASE_DIR) # e.g. /www/sites/newhr.org/data/server |
| 78 | +print(Config.NUMBER) # 456 |
| 79 | +print(Config.BOOLEAN) # True |
60 | 80 | ```
|
61 | 81 |
|
62 |
| -## Prepared autogenerators for DB URIs |
63 |
| -For example in .env file you can write only this data: |
| 82 | +### 3. Override .env file with ENV_FILE |
| 83 | +Instead of relying on the default .env lookup, simply set ENV_FILE in your shell: |
| 84 | +```bash |
| 85 | +ENV_FILE=dev-1.env python app.py |
64 | 86 | ```
|
65 |
| -MONGO_HOST="127.0.0.1" |
66 |
| -MONGO_USER="user" |
67 |
| -MONGO_PWD="*****" |
68 |
| -MONGO_DB="test" |
| 87 | + |
| 88 | +The library will load variables from dev-1.env (instead of .env in CWD). |
| 89 | + |
| 90 | +### 4. Automatic DB-URI generation |
| 91 | +In your .env: |
| 92 | +```ini |
| 93 | +MONGO_HOST=127.0.0.1 |
| 94 | +MONGO_USER=user |
| 95 | +MONGO_PWD=secret |
| 96 | +MONGO_DB=test |
69 | 97 | MONGO_PORT=27017
|
70 | 98 | ```
|
71 | 99 |
|
72 |
| -and in code you can call the MONGO_URL |
73 |
| - |
74 |
| -```py |
| 100 | +```python |
75 | 101 | from magic_config import Config
|
76 | 102 |
|
77 |
| -Config.MONGO_URL |
78 |
| - |
79 |
| -# output: |
80 |
| -# mongodb://user:[email protected]:27017/test?authSource=admin&tls=false |
| 103 | +print(Config.MONGO_URI) |
| 104 | +# => "mongodb://user:[email protected]:27017/test?authSource=admin&tls=false" |
81 | 105 | ```
|
82 | 106 |
|
83 |
| -## Set type casting for environment variables |
| 107 | +Likewise for MYSQL_HOST, MYSQL_USER, etc. — just call Config.MYSQL_URI. |
84 | 108 |
|
85 |
| -For example if you create in source root magic.config file and write: |
86 |
| -```bash |
| 109 | +### 5. Type casting via magic.config |
| 110 | +Create magic.config in your project root: |
| 111 | +```ini |
87 | 112 | DEBUG="bool"
|
88 |
| -DEBUG_STEP="bool" |
89 |
| -DEBUG_USER_ID="int" |
| 113 | +MAX_USERS="int" |
| 114 | +FEATURE_FLAGS="obj" |
90 | 115 | ```
|
91 | 116 |
|
92 |
| -then you run |
93 |
| - |
94 | 117 | ```bash
|
95 |
| -DEBUG=1 DEBUG_STEP=1 DEBUG_USER_ID=1 DEBUG_USER_ID=10011888 python server.py |
| 118 | +DEBUG=1 MAX_USERS=42 FEATURE_FLAGS='{"beta":true}' python server.py |
96 | 119 | ```
|
97 | 120 |
|
98 |
| -```py |
99 |
| -Config.DEBUG # True |
100 |
| -Config.DEBUG_STEP # True |
101 |
| -Config.DEBUG_USER_ID # int(10011888) |
102 |
| -``` |
| 121 | +```python |
| 122 | +from magic_config import Config |
103 | 123 |
|
104 |
| -## Custom file path |
105 |
| -Instead default .env file in source root you can configure path to .env file: |
| 124 | +assert isinstance(Config.DEBUG, bool) # True |
| 125 | +assert isinstance(Config.MAX_USERS, int) # 42 |
| 126 | +assert isinstance(Config.FEATURE_FLAGS, dict) # {"beta": True} |
| 127 | +``` |
106 | 128 |
|
107 |
| -```py |
108 |
| -# for example |
| 129 | +### 6. Flask integration |
| 130 | +By default Flask’s app.config.from_object() only picks up actual attributes listed in dir(obj). |
| 131 | +We provide a small `__dir__` override in MagicConfig so you can do: |
| 132 | +```python |
| 133 | +from flask import Flask |
| 134 | +from magic_config import Config |
109 | 135 |
|
110 |
| -env_file = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + "/../my.env") |
111 |
| -MagicConfig(env_file=env_file) |
| 136 | +app = Flask(__name__) |
| 137 | +app.config.from_object(Config) |
| 138 | +``` |
112 | 139 |
|
| 140 | +All your uppercase keys will be imported. |
| 141 | +Alternatively, you can treat Config as a plain mapping: |
| 142 | +```python |
| 143 | +app.config.from_mapping(Config) |
| 144 | +# or |
| 145 | +app.config.update(Config) |
113 | 146 | ```
|
| 147 | + |
| 148 | +Enjoy a cleaner, more powerful way to manage your application configuration! |
0 commit comments