Skip to content

Commit 033b97e

Browse files
HEROgoldCopilotCopilot
authored
Add support for nested configuration (#52)
* Add support for nested configuration * Update docs/examples/custom_data_type.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix docs: remove non-existent `Parser`/`set_parser` references (#53) * Initial plan * Fix documentation: remove non-existent Parser/set_parser references Co-authored-by: HEROgold <21345384+HEROgold@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: HEROgold <21345384+HEROgold@users.noreply.github.com> * mark as deprecation instead of private method * Raise ConfigPathConflictError when trying to path through a scalar. * fix ruff issue * ignore line len on deprecation warning * ruff fixes * add missing .env parse detection * Separate built-in parsers from msgspec optional dependency; fix MsgspecParser type handling and conflict detection (#54) * Initial plan * Move built-in parsers to confkit.parsers, fix type handling and conflict detection Co-authored-by: HEROgold <21345384+HEROgold@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: HEROgold <21345384+HEROgold@users.noreply.github.com> * fix docstr * fix ruff --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent dff4c76 commit 033b97e

40 files changed

+953
-250
lines changed

.github/copilot-instructions.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ confkit is a Python library for type-safe configuration management using descrip
1111
- `Config` descriptor (`config.py`): The main descriptor class that handles getting/setting values in config files
1212
- `ConfigContainerMeta` (`config.py`): Metaclass that enables setting Config descriptors on class variables
1313
- `BaseDataType` and implementations (`data_types.py`): Type converters for different data types
14-
- `ConfkitParser` protocol (`ext/parsers.py`): Protocol defining the parser interface
15-
- `MsgspecParser` (`ext/parsers.py`): Parser for JSON, YAML, and TOML files
16-
- `EnvParser` (`ext/parsers.py`): Parser for environment variables and .env files
14+
- `ConfkitParser` protocol (`parsers.py`): Defines the unified parser interface for all configuration file formats (INI, JSON, YAML, TOML, .env)
15+
- `IniParser` (`parsers.py`): Adapter for Python's built-in ConfigParser (INI files)
16+
- `MsgspecParser` (`ext/parsers.py`): Adapter for JSON, YAML, and TOML files using msgspec
17+
- `EnvParser` (`parsers.py`): Adapter for environment variables and .env files
1718
- `sentinels.py`: Provides the `UNSET` sentinel value for representing unset values
1819
- `exceptions.py`: Custom exceptions for configuration errors
1920
- `watcher.py`: File watching functionality to detect config file changes
@@ -44,6 +45,8 @@ uv sync --group test
4445
```bash
4546
# Run linting
4647
ruff check .
48+
# Fix issues using
49+
ruff check . --fix --unsafe-fixes
4750
# Update dependencies and run tests
4851
uv sync --upgrade --group dev; uv run pytest .
4952
```
@@ -172,33 +175,26 @@ The `with_setting` approach is more type-safe as it references an actual descrip
172175

173176
### Required Initialization
174177

175-
Always initialize Config with a file path before use. The parser can be set explicitly or will be auto-detected based on file extension:
178+
Always initialize Config with a file path before use. The parser is auto-detected based on file extension:
176179

177180
```python
178181
from pathlib import Path
179182
from confkit import Config
180183

181-
# Option 1: Auto-detect parser based on file extension
182-
Config.set_file(Path("config.ini")) # Uses ConfigParser
184+
# Parser is auto-detected based on file extension
185+
Config.set_file(Path("config.ini")) # Uses IniParser
183186
Config.set_file(Path("config.json")) # Uses MsgspecParser
184187
Config.set_file(Path("config.yaml")) # Uses MsgspecParser
185188
Config.set_file(Path("config.toml")) # Uses MsgspecParser
186-
Config.set_file(Path(".env")) # Uses EnvParser
187-
188-
# Option 2: Explicitly set parser (not recommended unless it's absolutely required.)
189-
from configparser import ConfigParser
190-
parser = ConfigParser()
191-
Config.set_parser(parser)
192-
Config.set_file(Path("config.ini"))
193189
```
194190

195191
### Supported File Formats
196192

197-
- **INI files** (`.ini`): Uses Python's `ConfigParser`, supports sections
193+
- **INI files** (`.ini`): Uses `IniParser`, supports sections
198194
- **JSON files** (`.json`): Uses `MsgspecParser`, requires `msgspec` extra
199195
- **YAML files** (`.yaml`, `.yml`): Uses `MsgspecParser`, requires `msgspec` extra
200196
- **TOML files** (`.toml`): Uses `MsgspecParser`, requires `msgspec` extra
201-
- **Environment files** (`.env`): Uses `EnvParser`, no sections (flat key-value pairs)
197+
- **Environment files** (`.env`): Uses `EnvParser`, no sections (flat key-value pairs) — not auto-detected by `set_file`
202198

203199
### List Type Handling
204200

docs/examples/custom_data_type.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@ Shows how to create and use a custom [`BaseDataType`](pdoc:confkit.BaseDataType)
1111
## Implementation
1212

1313
```python
14-
from configparser import ConfigParser
1514
from pathlib import Path
1615
from confkit import Config
1716
from confkit.data_types import BaseDataType
1817

19-
# Configure parser + file
20-
parser = ConfigParser()
21-
Config.set_parser(parser)
18+
# Configure config file (parser is automatically detected from extension)
2219
Config.set_file(Path("config.ini"))
2320

2421
class UpperString(BaseDataType[str]):

docs/usage.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@ This page explains how to work with confkit and how the documentation is generat
99
## Descriptor Quickstart
1010

1111
```python
12-
from configparser import ConfigParser
1312
from pathlib import Path
1413
from confkit import Config
1514

16-
# 1. Configure confkit parser/file (normally app bootstrap)
17-
parser = ConfigParser()
18-
Config.set_parser(parser)
15+
# 1. Configure confkit file (parser is auto-detected)
1916
Config.set_file(Path("config.ini"))
2017

2118
# 2. Define your (class)variables with their default values
@@ -36,14 +33,11 @@ print(AppConfig.port)
3633
4. Use via `Config(CustomType(default_value))`
3734

3835
```python
39-
from configparser import ConfigParser
4036
from pathlib import Path
4137
from confkit import Config
4238
from confkit.data_types import BaseDataType
4339

44-
# 1. Configure confkit parser/file (normally app bootstrap)
45-
parser = ConfigParser()
46-
Config.set_parser(parser)
40+
# 1. Configure confkit file (parser is auto-detected)
4741
Config.set_file(Path("config.ini"))
4842

4943
# 2. Define the custom converter, with a convert method (from str -> your_type)

examples/argparse_example.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616
from confkit.data_types import List
1717

1818
# Setup a standard confkit config file (unrelated to argparse defaults file)
19-
parser_ini = ConfigParser()
2019
ini_path = Path("config.ini")
2120
Config.write_on_edit = False
22-
Config.set_parser(parser_ini)
2321
Config.set_file(ini_path)
2422

2523
class AppConfig:

examples/basic.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
from confkit import Config
1717

1818
# Set up the parser and file
19-
parser = ConfigParser()
20-
Config.set_parser(parser)
2119
Config.set_file(Path("config.ini"))
2220

2321
# Enable automatic writing when config values are changed (this is the default)

examples/custom_data_type.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
from confkit import Config
2121
from confkit.data_types import BaseDataType
2222

23-
parser = ConfigParser()
24-
Config.set_parser(parser)
2523
Config.set_file(Path("config.ini"))
2624

2725
class UpperString(BaseDataType[str]):

examples/data_types.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
from confkit import Config
1717
from confkit.data_types import Binary, Boolean, Float, Hex, Integer, Octal, String
1818

19-
parser = ConfigParser()
20-
Config.set_parser(parser)
2119
Config.set_file(Path("config.ini"))
2220

2321

examples/decorators.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55

66
from confkit.config import Config
77

8-
parser = ConfigParser()
9-
Config.set_parser(parser)
108
Config.set_file(Path("config.ini"))
119

1210

examples/enums.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
from confkit.data_types import IntFlag as ConfigIntFlag
2121
from confkit.data_types import Optional, StrEnum as ConfigStrEnum
2222

23-
parser = ConfigParser()
24-
Config.set_parser(parser)
2523
Config.set_file(Path("config.ini"))
2624

2725

examples/file_change_event.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
from confkit import Config
1212

1313
# Set up the parser and file
14-
parser = ConfigParser()
15-
Config.set_parser(parser)
1614
Config.set_file(Path("config.ini"))
1715

1816
# Enable automatic writing when config values are changed (this is the default)

0 commit comments

Comments
 (0)