Skip to content

Separate built-in parsers from msgspec optional dependency; fix MsgspecParser type handling and conflict detection#54

Merged
HEROgold merged 2 commits intonested-levelsfrom
copilot/sub-pr-52-again
Mar 2, 2026
Merged

Separate built-in parsers from msgspec optional dependency; fix MsgspecParser type handling and conflict detection#54
HEROgold merged 2 commits intonested-levelsfrom
copilot/sub-pr-52-again

Conversation

Copy link
Contributor

Copilot AI commented Mar 2, 2026

confkit.ext.parsers unconditionally imported msgspec at module load time, breaking INI-only usage without the optional extra. MsgspecParser._parse_value also corrupted string values like "001"1 (int), and scalar-vs-section path conflicts were silently dropped on writes.

Parser module split

  • New confkit/parsers.py holds ConfkitParser (Protocol), IniParser, EnvParser — zero optional deps
  • confkit/ext/parsers.py now contains only MsgspecParser; still raises ImportError immediately without msgspec
  • config.py and all tests/examples updated to import built-in parsers from confkit.parsers
from confkit.parsers import IniParser, EnvParser, ConfkitParser  # no msgspec needed
from confkit.ext.parsers import MsgspecParser  # requires msgspec extra

MsgspecParser type handling (replaces _parse_value)

Config._set now passes BaseDataType objects directly to parsers instead of converting to str first. MsgspecParser.set stores native Python types when str(native) == str(data_type) (standard types), and the custom string representation when they differ (e.g. Hex(10)"0xa", not 10). This preserves round-trip correctness without guessing types from strings.

IniParser.set handles % escaping internally (moved from Config._sanitize_str).

Scalar conflict detection

_navigate_to_section(create=True) now raises ConfigPathConflictError when the final path element is already a scalar — previously only intermediate elements triggered this, silently dropping writes.

Other fixes

  • test_msgspecparser_no_msgspec.py: uses match=re.escape(expected_msg) in pytest.raises
  • .github/copilot-instructions.md: corrected Parser facade reference → ConfkitParser protocol in parsers.py
  • examples/nested_config.py: removed deprecated set_parser(IniParser()) call (auto-detected from .ini extension)

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…ict detection

Co-authored-by: HEROgold <21345384+HEROgold@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for nested configuration Separate built-in parsers from msgspec optional dependency; fix MsgspecParser type handling and conflict detection Mar 2, 2026
@HEROgold HEROgold marked this pull request as ready for review March 2, 2026 18:45
Copilot AI review requested due to automatic review settings March 2, 2026 18:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restructures confkit’s parser modules to avoid importing the optional msgspec dependency for INI/.env-only usage, and refines MsgspecParser write behavior (type preservation + stricter path conflict detection).

Changes:

  • Moved built-in parsers (ConfkitParser, IniParser, EnvParser) into a new zero-optional-deps module: confkit.parsers.
  • Updated Config + tests/examples to import built-in parsers from confkit.parsers and only import MsgspecParser from confkit.ext.parsers when needed.
  • Updated MsgspecParser.set() to store native Python types when safe, and raise on scalar-vs-section conflicts even at the final path element.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/test_two_instances.py Update import path for IniParser to confkit.parsers.
tests/test_pydantic_models.py Update import path for IniParser to confkit.parsers.
tests/test_nested_config.py Split imports: MsgspecParser from confkit.ext.parsers, IniParser from confkit.parsers.
tests/test_multiple_configurations.py Update import path for IniParser to confkit.parsers.
tests/test_msgspecparser_no_msgspec.py Tighten ImportError assertion using re.escape() for exact message matching.
tests/test_metaclass.py Update import path for IniParser to confkit.parsers.
tests/test_env_parser.py Update import path for EnvParser to confkit.parsers.
tests/test_config_detect_parser.py Split imports: MsgspecParser from confkit.ext.parsers, IniParser from confkit.parsers.
tests/test_config_decorators.py Update import path for IniParser to confkit.parsers.
tests/test_config_classvars.py Update import path for IniParser to confkit.parsers.
tests/test_config.py Update import path for IniParser to confkit.parsers.
src/confkit/parsers.py New module for built-in parsers/protocol without optional dependencies; adds % escaping to IniParser.set().
src/confkit/ext/parsers.py Now msgspec-only; improves _navigate_to_section conflict detection and stores native vs stringified BaseDataType values in set().
src/confkit/config.py Switch built-in parser imports to confkit.parsers; change _set() to pass values directly to parsers (no longer pre-sanitizing to str).
examples/nested_config.py Remove deprecated set_parser(IniParser()) usage; rely on auto-detection from .ini.
.github/copilot-instructions.md Docs update to reflect ConfkitParser protocol and built-in parser module locations.

@HEROgold HEROgold merged commit e0a2255 into nested-levels Mar 2, 2026
4 checks passed
HEROgold added a commit that referenced this pull request Mar 2, 2026
* 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>
@HEROgold HEROgold deleted the copilot/sub-pr-52-again branch March 2, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants