ga-configreader 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ga_configreader-0.1.3/CHANGELOG.md +8 -0
- ga_configreader-0.1.3/LICENSE +21 -0
- ga_configreader-0.1.3/MANIFEST.in +5 -0
- ga_configreader-0.1.3/PKG-INFO +239 -0
- ga_configreader-0.1.3/README.md +201 -0
- ga_configreader-0.1.3/docs/api.md +75 -0
- ga_configreader-0.1.3/docs/examples.md +82 -0
- ga_configreader-0.1.3/docs/index.md +10 -0
- ga_configreader-0.1.3/docs/overview.md +35 -0
- ga_configreader-0.1.3/docs/providers.md +53 -0
- ga_configreader-0.1.3/pyproject.toml +103 -0
- ga_configreader-0.1.3/setup.cfg +4 -0
- ga_configreader-0.1.3/src/configreader/__init__.py +8 -0
- ga_configreader-0.1.3/src/configreader/_version.py +1 -0
- ga_configreader-0.1.3/src/configreader/configreader.py +481 -0
- ga_configreader-0.1.3/src/configreader/py.typed +1 -0
- ga_configreader-0.1.3/src/ga_configreader.egg-info/PKG-INFO +239 -0
- ga_configreader-0.1.3/src/ga_configreader.egg-info/SOURCES.txt +20 -0
- ga_configreader-0.1.3/src/ga_configreader.egg-info/dependency_links.txt +1 -0
- ga_configreader-0.1.3/src/ga_configreader.egg-info/requires.txt +15 -0
- ga_configreader-0.1.3/src/ga_configreader.egg-info/top_level.txt +1 -0
- ga_configreader-0.1.3/tests/test_basic.py +83 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrea Gemma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ga-configreader
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Read configuration values from INI, DB, environment variables, and dictionaries
|
|
5
|
+
Author-email: Andrea Gemma <andrea.gemma@uniroma3.it>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Documentation, https://github.com/andreagemma/configreader#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/andreagemma/configreader/issues
|
|
9
|
+
Project-URL: Source, https://github.com/andreagemma/configreader
|
|
10
|
+
Keywords: configuration,ini,environment,sqlalchemy,settings
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Database :: Front-Ends
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Provides-Extra: db
|
|
26
|
+
Requires-Dist: sqlalchemy>=2.0; extra == "db"
|
|
27
|
+
Provides-Extra: test
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
29
|
+
Requires-Dist: pytest-cov>=5.0; extra == "test"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
32
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
36
|
+
Requires-Dist: twine>=5.1; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# configreader
|
|
40
|
+
|
|
41
|
+
Python library to read configuration values from multiple sources with configurable precedence.
|
|
42
|
+
|
|
43
|
+
Supported sources:
|
|
44
|
+
- INI file
|
|
45
|
+
- SQL database through SQLAlchemy (optional)
|
|
46
|
+
- environment variables
|
|
47
|
+
- in-memory Python dictionary
|
|
48
|
+
|
|
49
|
+
Values are resolved in order, and the first non-empty match is returned.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
### From PyPI
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install ga-configreader
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### From source
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git clone https://github.com/andreagemma/configreader.git
|
|
63
|
+
cd configreader
|
|
64
|
+
pip install -e .
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Database support (optional)
|
|
68
|
+
|
|
69
|
+
Install SQLAlchemy if you want to use the DB provider:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install sqlalchemy
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or install the project with DB extras:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install "configreader[db]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Quickstart
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from configreader import ConfigReader
|
|
85
|
+
|
|
86
|
+
reader = ConfigReader(
|
|
87
|
+
file="config.ini",
|
|
88
|
+
use_env=True,
|
|
89
|
+
dictionary={"DEFAULT": {"timeout": "30"}},
|
|
90
|
+
providers=["env", "ini", "dict"],
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
host = reader.get("host", default="127.0.0.1")
|
|
94
|
+
port = reader.getint("port", default=8080)
|
|
95
|
+
debug = reader.getboolean("debug", default=False)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Provider Precedence
|
|
99
|
+
|
|
100
|
+
The providers list defines lookup order.
|
|
101
|
+
|
|
102
|
+
Example:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
providers = ["env", "db", "ini", "dict"]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Meaning:
|
|
109
|
+
1. check environment first
|
|
110
|
+
2. then check database
|
|
111
|
+
3. then check INI file
|
|
112
|
+
4. then check dictionary
|
|
113
|
+
|
|
114
|
+
## Environment Variables
|
|
115
|
+
|
|
116
|
+
Naming rules:
|
|
117
|
+
- if section="DEFAULT", variable name is NAME
|
|
118
|
+
- for custom sections, variable name is SECTION_NAME
|
|
119
|
+
|
|
120
|
+
Examples:
|
|
121
|
+
- reader.get("host", section="DEFAULT") reads HOST
|
|
122
|
+
- reader.get("host", section="app") reads APP_HOST
|
|
123
|
+
|
|
124
|
+
## Using INI Files
|
|
125
|
+
|
|
126
|
+
Example config.ini:
|
|
127
|
+
|
|
128
|
+
```ini
|
|
129
|
+
[DEFAULT]
|
|
130
|
+
host = localhost
|
|
131
|
+
port = 5432
|
|
132
|
+
debug = true
|
|
133
|
+
items = [1, 2, 3]
|
|
134
|
+
|
|
135
|
+
[app]
|
|
136
|
+
workers = 4
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Code:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
reader = ConfigReader(file="config.ini")
|
|
143
|
+
|
|
144
|
+
host = reader.get("host")
|
|
145
|
+
port = reader.getint("port")
|
|
146
|
+
debug = reader.getboolean("debug")
|
|
147
|
+
items = reader.getlist("items")
|
|
148
|
+
workers = reader.getint("workers", section="app")
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Using a Dictionary
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
reader = ConfigReader(
|
|
155
|
+
dictionary={
|
|
156
|
+
"DEFAULT": {
|
|
157
|
+
"host": "localhost",
|
|
158
|
+
"allowed": "['admin', 'user']",
|
|
159
|
+
},
|
|
160
|
+
"service": {
|
|
161
|
+
"retries": "3",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
providers=["dict"],
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
allowed = reader.getlist("allowed")
|
|
168
|
+
retries = reader.getint("retries", section="service")
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Using a Database
|
|
172
|
+
|
|
173
|
+
Constructor:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
reader = ConfigReader(
|
|
177
|
+
db_url="sqlite:///settings.db",
|
|
178
|
+
db_query="SELECT value FROM settings WHERE section = :section AND name = :name",
|
|
179
|
+
providers=["db", "env"],
|
|
180
|
+
)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Default query shape:
|
|
184
|
+
|
|
185
|
+
```sql
|
|
186
|
+
SELECT value FROM settings WHERE section = :section AND name = :name
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
DB utility methods:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
ok = ConfigReader.check_db_connection("sqlite:///settings.db")
|
|
193
|
+
exists = ConfigReader.check_db_exists("sqlite:///settings.db", table_name="settings")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Main API
|
|
197
|
+
|
|
198
|
+
- `get(name, default=None, section="DEFAULT") -> str | None`
|
|
199
|
+
- `getint(name, default=None, section="DEFAULT") -> int | None`
|
|
200
|
+
- `getboolean(name, default=None, section="DEFAULT") -> bool | None`
|
|
201
|
+
- `getfloat(name, default=None, section="DEFAULT") -> float | None`
|
|
202
|
+
- `getlist(name, default=None, section="DEFAULT") -> list[Any] | None`
|
|
203
|
+
- `getset(name, default=None, section="DEFAULT") -> set[Any] | None`
|
|
204
|
+
- `gettuple(name, default=None, section="DEFAULT") -> tuple[Any, ...] | None`
|
|
205
|
+
- `getdict(name, default=None, section="DEFAULT") -> dict[Any, Any] | None`
|
|
206
|
+
- `items()` iterator over loaded INI entries
|
|
207
|
+
|
|
208
|
+
Full details in [docs/api.md](docs/api.md).
|
|
209
|
+
|
|
210
|
+
## Errors And Type Conversion
|
|
211
|
+
|
|
212
|
+
- `FileNotFoundError` is raised if the provided INI file does not exist.
|
|
213
|
+
- Typed getters (`getint`, `getfloat`, `getlist`, etc.) propagate parsing/conversion errors.
|
|
214
|
+
- If SQLAlchemy is not installed, DB features are unavailable.
|
|
215
|
+
|
|
216
|
+
## Development
|
|
217
|
+
|
|
218
|
+
Install development dependencies:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
pip install -e .[dev]
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Run tests:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
pytest
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## More Documentation
|
|
231
|
+
|
|
232
|
+
- [docs/overview.md](docs/overview.md)
|
|
233
|
+
- [docs/providers.md](docs/providers.md)
|
|
234
|
+
- [docs/api.md](docs/api.md)
|
|
235
|
+
- [docs/examples.md](docs/examples.md)
|
|
236
|
+
|
|
237
|
+
## License
|
|
238
|
+
|
|
239
|
+
Distributed under the MIT License. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# configreader
|
|
2
|
+
|
|
3
|
+
Python library to read configuration values from multiple sources with configurable precedence.
|
|
4
|
+
|
|
5
|
+
Supported sources:
|
|
6
|
+
- INI file
|
|
7
|
+
- SQL database through SQLAlchemy (optional)
|
|
8
|
+
- environment variables
|
|
9
|
+
- in-memory Python dictionary
|
|
10
|
+
|
|
11
|
+
Values are resolved in order, and the first non-empty match is returned.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
### From PyPI
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install ga-configreader
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### From source
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/andreagemma/configreader.git
|
|
25
|
+
cd configreader
|
|
26
|
+
pip install -e .
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Database support (optional)
|
|
30
|
+
|
|
31
|
+
Install SQLAlchemy if you want to use the DB provider:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install sqlalchemy
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or install the project with DB extras:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install "configreader[db]"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quickstart
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from configreader import ConfigReader
|
|
47
|
+
|
|
48
|
+
reader = ConfigReader(
|
|
49
|
+
file="config.ini",
|
|
50
|
+
use_env=True,
|
|
51
|
+
dictionary={"DEFAULT": {"timeout": "30"}},
|
|
52
|
+
providers=["env", "ini", "dict"],
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
host = reader.get("host", default="127.0.0.1")
|
|
56
|
+
port = reader.getint("port", default=8080)
|
|
57
|
+
debug = reader.getboolean("debug", default=False)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Provider Precedence
|
|
61
|
+
|
|
62
|
+
The providers list defines lookup order.
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
providers = ["env", "db", "ini", "dict"]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Meaning:
|
|
71
|
+
1. check environment first
|
|
72
|
+
2. then check database
|
|
73
|
+
3. then check INI file
|
|
74
|
+
4. then check dictionary
|
|
75
|
+
|
|
76
|
+
## Environment Variables
|
|
77
|
+
|
|
78
|
+
Naming rules:
|
|
79
|
+
- if section="DEFAULT", variable name is NAME
|
|
80
|
+
- for custom sections, variable name is SECTION_NAME
|
|
81
|
+
|
|
82
|
+
Examples:
|
|
83
|
+
- reader.get("host", section="DEFAULT") reads HOST
|
|
84
|
+
- reader.get("host", section="app") reads APP_HOST
|
|
85
|
+
|
|
86
|
+
## Using INI Files
|
|
87
|
+
|
|
88
|
+
Example config.ini:
|
|
89
|
+
|
|
90
|
+
```ini
|
|
91
|
+
[DEFAULT]
|
|
92
|
+
host = localhost
|
|
93
|
+
port = 5432
|
|
94
|
+
debug = true
|
|
95
|
+
items = [1, 2, 3]
|
|
96
|
+
|
|
97
|
+
[app]
|
|
98
|
+
workers = 4
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Code:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
reader = ConfigReader(file="config.ini")
|
|
105
|
+
|
|
106
|
+
host = reader.get("host")
|
|
107
|
+
port = reader.getint("port")
|
|
108
|
+
debug = reader.getboolean("debug")
|
|
109
|
+
items = reader.getlist("items")
|
|
110
|
+
workers = reader.getint("workers", section="app")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Using a Dictionary
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
reader = ConfigReader(
|
|
117
|
+
dictionary={
|
|
118
|
+
"DEFAULT": {
|
|
119
|
+
"host": "localhost",
|
|
120
|
+
"allowed": "['admin', 'user']",
|
|
121
|
+
},
|
|
122
|
+
"service": {
|
|
123
|
+
"retries": "3",
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
providers=["dict"],
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
allowed = reader.getlist("allowed")
|
|
130
|
+
retries = reader.getint("retries", section="service")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Using a Database
|
|
134
|
+
|
|
135
|
+
Constructor:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
reader = ConfigReader(
|
|
139
|
+
db_url="sqlite:///settings.db",
|
|
140
|
+
db_query="SELECT value FROM settings WHERE section = :section AND name = :name",
|
|
141
|
+
providers=["db", "env"],
|
|
142
|
+
)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Default query shape:
|
|
146
|
+
|
|
147
|
+
```sql
|
|
148
|
+
SELECT value FROM settings WHERE section = :section AND name = :name
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
DB utility methods:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
ok = ConfigReader.check_db_connection("sqlite:///settings.db")
|
|
155
|
+
exists = ConfigReader.check_db_exists("sqlite:///settings.db", table_name="settings")
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Main API
|
|
159
|
+
|
|
160
|
+
- `get(name, default=None, section="DEFAULT") -> str | None`
|
|
161
|
+
- `getint(name, default=None, section="DEFAULT") -> int | None`
|
|
162
|
+
- `getboolean(name, default=None, section="DEFAULT") -> bool | None`
|
|
163
|
+
- `getfloat(name, default=None, section="DEFAULT") -> float | None`
|
|
164
|
+
- `getlist(name, default=None, section="DEFAULT") -> list[Any] | None`
|
|
165
|
+
- `getset(name, default=None, section="DEFAULT") -> set[Any] | None`
|
|
166
|
+
- `gettuple(name, default=None, section="DEFAULT") -> tuple[Any, ...] | None`
|
|
167
|
+
- `getdict(name, default=None, section="DEFAULT") -> dict[Any, Any] | None`
|
|
168
|
+
- `items()` iterator over loaded INI entries
|
|
169
|
+
|
|
170
|
+
Full details in [docs/api.md](docs/api.md).
|
|
171
|
+
|
|
172
|
+
## Errors And Type Conversion
|
|
173
|
+
|
|
174
|
+
- `FileNotFoundError` is raised if the provided INI file does not exist.
|
|
175
|
+
- Typed getters (`getint`, `getfloat`, `getlist`, etc.) propagate parsing/conversion errors.
|
|
176
|
+
- If SQLAlchemy is not installed, DB features are unavailable.
|
|
177
|
+
|
|
178
|
+
## Development
|
|
179
|
+
|
|
180
|
+
Install development dependencies:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
pip install -e .[dev]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Run tests:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
pytest
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## More Documentation
|
|
193
|
+
|
|
194
|
+
- [docs/overview.md](docs/overview.md)
|
|
195
|
+
- [docs/providers.md](docs/providers.md)
|
|
196
|
+
- [docs/api.md](docs/api.md)
|
|
197
|
+
- [docs/examples.md](docs/examples.md)
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
Distributed under the MIT License. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## ConfigSource Enum
|
|
4
|
+
|
|
5
|
+
Available values:
|
|
6
|
+
- ConfigSource.INI ("ini")
|
|
7
|
+
- ConfigSource.DB ("db")
|
|
8
|
+
- ConfigSource.ENV ("env")
|
|
9
|
+
- ConfigSource.DICT ("dict")
|
|
10
|
+
|
|
11
|
+
Methods:
|
|
12
|
+
- ConfigSource.parse(value: str) -> ConfigSource | None
|
|
13
|
+
|
|
14
|
+
## ConfigReader Class
|
|
15
|
+
|
|
16
|
+
### Constructor
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
ConfigReader(
|
|
20
|
+
file: str | Path | None = None,
|
|
21
|
+
dictionary: dict[str, dict[str, str]] | None = None,
|
|
22
|
+
db_url: str | None = None,
|
|
23
|
+
db_query: str | None = None,
|
|
24
|
+
use_env: bool = True,
|
|
25
|
+
providers: list[ConfigSource | str] | None = None,
|
|
26
|
+
)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Parameters:
|
|
30
|
+
- file: path to an INI file.
|
|
31
|
+
- dictionary: in-memory source grouped by section and key.
|
|
32
|
+
- db_url: SQLAlchemy database URL.
|
|
33
|
+
- db_query: SQL query using :section and :name parameters.
|
|
34
|
+
- use_env: enable or disable environment variable lookup.
|
|
35
|
+
- providers: provider precedence order.
|
|
36
|
+
|
|
37
|
+
### Main Methods
|
|
38
|
+
|
|
39
|
+
- get(name, default=None, section="DEFAULT") -> str | None
|
|
40
|
+
: reads the raw value as string.
|
|
41
|
+
|
|
42
|
+
- getint(name, default=None, section="DEFAULT") -> int | None
|
|
43
|
+
: converts using int(...).
|
|
44
|
+
|
|
45
|
+
- getboolean(name, default=None, section="DEFAULT") -> bool | None
|
|
46
|
+
: returns True when lowercased value is in ("true", "1", "yes"), else False.
|
|
47
|
+
|
|
48
|
+
- getfloat(name, default=None, section="DEFAULT") -> float | None
|
|
49
|
+
: converts using float(...).
|
|
50
|
+
|
|
51
|
+
- getlist(name, default=None, section="DEFAULT") -> list[Any] | None
|
|
52
|
+
: parses with ast.literal_eval(...).
|
|
53
|
+
|
|
54
|
+
- getset(name, default=None, section="DEFAULT") -> set[Any] | None
|
|
55
|
+
: parses with set(ast.literal_eval(...)).
|
|
56
|
+
|
|
57
|
+
- gettuple(name, section="DEFAULT", default=None) -> tuple[Any, ...] | None
|
|
58
|
+
: parses with tuple(ast.literal_eval(...)).
|
|
59
|
+
|
|
60
|
+
- getdict(name, section="DEFAULT", default=None) -> dict[Any, Any] | None
|
|
61
|
+
: parses with dict(ast.literal_eval(...)).
|
|
62
|
+
|
|
63
|
+
- items()
|
|
64
|
+
: iterator of (section, name, value) from loaded INI sections.
|
|
65
|
+
|
|
66
|
+
### DB Utility Static Methods
|
|
67
|
+
|
|
68
|
+
- ConfigReader.check_db_connection(db_url: str) -> bool
|
|
69
|
+
- ConfigReader.check_db_exists(db_url: str, table_name: str = "settings") -> bool
|
|
70
|
+
|
|
71
|
+
## Important Behavior
|
|
72
|
+
|
|
73
|
+
- If no provider returns a value, default is returned.
|
|
74
|
+
- Typed conversions may raise parsing/conversion exceptions.
|
|
75
|
+
- Without SQLAlchemy, DB methods are unavailable.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
## 1) Fallback Env -> INI
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from configreader import ConfigReader
|
|
7
|
+
|
|
8
|
+
reader = ConfigReader(
|
|
9
|
+
file="config.ini",
|
|
10
|
+
use_env=True,
|
|
11
|
+
providers=["env", "ini"],
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
api_url = reader.get("api_url", default="http://localhost:8000")
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
With this order, an environment variable overrides the INI value.
|
|
18
|
+
|
|
19
|
+
## 2) Dictionary Only (useful in tests)
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from configreader.configreader import ConfigReader
|
|
23
|
+
|
|
24
|
+
reader = ConfigReader(
|
|
25
|
+
dictionary={
|
|
26
|
+
"DEFAULT": {
|
|
27
|
+
"retries": "3",
|
|
28
|
+
"enabled": "true",
|
|
29
|
+
},
|
|
30
|
+
"service": {
|
|
31
|
+
"weights": "[0.4, 0.6]",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
providers=["dict"],
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
retries = reader.getint("retries", default=1)
|
|
38
|
+
enabled = reader.getboolean("enabled", default=False)
|
|
39
|
+
weights = reader.getlist("weights", section="service", default=[1.0])
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 3) DB With Custom Query
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from configreader.configreader import ConfigReader
|
|
46
|
+
|
|
47
|
+
reader = ConfigReader(
|
|
48
|
+
db_url="sqlite:///settings.db",
|
|
49
|
+
db_query="""
|
|
50
|
+
SELECT setting_value
|
|
51
|
+
FROM app_settings
|
|
52
|
+
WHERE section = :section AND key_name = :name
|
|
53
|
+
""",
|
|
54
|
+
providers=["db"],
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
timeout = reader.getint("timeout", section="http", default=30)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Make sure the query returns exactly one value column.
|
|
61
|
+
|
|
62
|
+
## 4) Full Chain With All Providers
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from configreader.configreader import ConfigReader
|
|
66
|
+
|
|
67
|
+
reader = ConfigReader(
|
|
68
|
+
file="config.ini",
|
|
69
|
+
db_url="sqlite:///settings.db",
|
|
70
|
+
use_env=True,
|
|
71
|
+
dictionary={"DEFAULT": {"workers": "2"}},
|
|
72
|
+
providers=["env", "db", "ini", "dict"],
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
workers = reader.getint("workers", default=1)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Practical order:
|
|
79
|
+
1. quick overrides via env
|
|
80
|
+
2. central configuration from DB
|
|
81
|
+
3. local fallback from INI
|
|
82
|
+
4. final hard-coded fallback from dictionary
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Overview
|
|
2
|
+
|
|
3
|
+
configreader is a small utility library that centralizes configuration lookup across multiple sources.
|
|
4
|
+
|
|
5
|
+
Core goals:
|
|
6
|
+
- automatic fallback between providers
|
|
7
|
+
- configurable provider precedence
|
|
8
|
+
- uniform API for raw and typed values
|
|
9
|
+
|
|
10
|
+
## Supported Sources
|
|
11
|
+
|
|
12
|
+
- ini: local INI file
|
|
13
|
+
- db: SQL query through SQLAlchemy
|
|
14
|
+
- env: environment variables
|
|
15
|
+
- dict: in-memory Python dictionary
|
|
16
|
+
|
|
17
|
+
## Resolution Flow
|
|
18
|
+
|
|
19
|
+
1. a get* method is called
|
|
20
|
+
2. providers are checked in the configured order
|
|
21
|
+
3. the first non-None value is returned
|
|
22
|
+
4. if no value is found, default is returned
|
|
23
|
+
|
|
24
|
+
## When To Use
|
|
25
|
+
|
|
26
|
+
- applications with environment-based overrides
|
|
27
|
+
- services with central DB settings and local fallback
|
|
28
|
+
- tests where values are injected from a dictionary
|
|
29
|
+
|
|
30
|
+
## When Not To Use
|
|
31
|
+
|
|
32
|
+
- complex schema validation for configuration payloads
|
|
33
|
+
- advanced secret management with rotation policies
|
|
34
|
+
|
|
35
|
+
In these scenarios, pair this library with dedicated validators or secret management tools.
|