Skip to content

Make multi-line values opt-in, add merged, define repeated keys - #41

Merged
ViralBShah merged 2 commits into
masterfrom
before-0.6.0
Nov 14, 2026
Merged

ViralBShah merged 2 commits into
masterfrom
before-0.6.0

Conversation

@ViralBShah

@ViralBShah ViralBShah commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

Settles three things before 0.6.0 is registered, since changing them afterwards would be breaking.

Multi-line values are opt-in

  • New option multiline_values, false by default. When it is off, every line stands on its own and leading whitespace is ignored, as in 0.5. An indented line is a separate entry, or malformed if it has no = or :.
  • With multiline_values=true, a line indented more than the line that started an entry continues its value, as before.
  • With the option off, write throws an ArgumentError naming the key and section for a value that contains a newline, because it could not be read back. The check runs before anything is written, so write(filename, ini) leaves an existing file alone. REPL display, print, string and interpolation never throw. Only write checks.
  • With multiline_values=true, a round trip keeps the lines of a value but not the whitespace around each line, trailing blank lines, or lines that start with # or ;. The docs now say so, and a test pins it down.
  • The breaking change "a line indented more than the previous entry is now a continuation" is gone from the upgrade guide, because the default now matches 0.5.

merged(ini)

  • Returns a new OrderedDict{String,String}: the defaults, then each section's keys in section order, with a later section overriding an earlier one. Each key keeps the position where it first appeared.
  • Named merged rather than flatten, which would clash with Base.Iterators.flatten. merged is not defined in Base, Core or the standard libraries checked.
  • Later sections win, in the order Circuitscape 4 walked the sections of Python's ConfigParser. I checked the repeated-section case against Python 3's configparser with strict=False. Python also lowercases keys, and Python 2 strips ; comments, so for Python files use lowercase_keys=true and inline_comment_prefixes=(";",) to get the same keys.

Repeated keys and sections

  • Within a section, the last value wins and the key keeps its first position. This was already the behaviour; it is now documented and tested.
  • A repeated section header adds to the earlier section, which keeps its position. Sections are ordered by their first header, so in merged a later section wins even over a line further down the file in a repeated, earlier section.
  • Never an error, with or without strict. strict only concerns malformed lines, so Circuitscape can use strict=true and still override a key by appending a line. There is no option to reject duplicates; if one is added later, it should be separate from strict.

Docstrings (module, Inifile, read, write, set, merged) and the README are updated. The 0.6 upgrade guide lists write's new ArgumentError. The test suite grows from 247 to 292 tests, covering every combination of strict and multiline_values for repeated keys.

Review

An independent review found that print and string threw for multi-line values, that the docs overstated the multi-line round trip, and that the merged docstring overstated equivalence with Python. Those are fixed in ad7119f. Two suggestions are left out of this PR:

  • Keys or section names containing newlines, = or : are still written out broken, as in 0.5. That could be a follow-up.
  • Checking every value against all of the reader's rules, not just newlines, would make write throw for things like trailing spaces, which INI files normally drop.

🤖 Generated with Claude Code

multiline_values is a new Inifile option, false by default. When it is
off, every line stands on its own and leading whitespace is ignored, as
in IniFile 0.5, so indentation no longer changes the meaning of a file
by default. write throws an ArgumentError naming the key and section for
a value that contains a newline, since it could not be read back. The
check runs before anything is written, so write(filename, ini) does not
empty an existing file. Display does not throw.

merged(ini) returns an OrderedDict{String,String} with the defaults and
then each section's keys, in section order, where a later section
overrides an earlier one. Sections are ordered by their first header,
and a repeated header adds to the earlier section, as in Python 2's
ConfigParser.

Repeated keys and sections are now documented and tested: within a
section the last value wins and the key keeps its first position, and a
repeated section header adds to the earlier section. They are never an
error, with or without strict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (39183d4) to head (ad7119f).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master       #41   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         1           
  Lines          146       172   +26     
=========================================
+ Hits           146       172   +26     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- print, string and interpolation give the file contents without the
  multi-line check, so logging an Inifile never throws. Only write
  checks.
- write(filename, ini) delegates to write(io, ini) after its check.
- Say what a multi-line value loses in a round trip: surrounding
  whitespace on each line, trailing blank lines, and lines starting with
  # or ;. Add a test that pins this down.
- List write's new ArgumentError in the 0.6 upgrade guide.
- Drop the claim that merged matches Python's ConfigParser, which also
  lowercases keys and strips inline comments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ViralBShah
ViralBShah merged commit 5cfc04c into master Nov 14, 2026
6 checks passed
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.

1 participant