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.
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## 0.1.0 - 2026-09-02
6
+
7
+ - Prepared environment
8
+ - Added complete project documentation in README and docs/ pages
@@ -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,5 @@
1
+ include LICENSE
2
+ include CHANGELOG.md
3
+ include README.md
4
+ recursive-include docs *.md
5
+ recursive-include src/configreader py.typed
@@ -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,10 @@
1
+ # Documentation
2
+
3
+ Documentation index:
4
+
5
+ - [Overview](overview.md)
6
+ - [Providers](providers.md)
7
+ - [API Reference](api.md)
8
+ - [Examples](examples.md)
9
+
10
+ For a quick introduction, start from [README.md](../README.md).
@@ -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.