Skip to content

Commit e62850b

Browse files
Update README and CHANGELOG for v0.1.0 release
README updates: - Change status to 'v0.1.0 Released - Production ready' - Update all imports to use public API (from ini import ...) - Add File I/O section with parse_file/write_file examples - Add Multiline Values section with clear examples - Add Known Limitations section documenting indented keys behavior - Explain tab-indented keys (Git config) workaround - Update Python compatibility matrix CHANGELOG v0.1.0: - Comprehensive release notes with all features - 46 tests across 5 suites documented - Python configparser compatibility matrix - Known limitations clearly stated - Technical details (LOC, architecture, tooling) Documentation now clearly explains the indented keys design decision and provides workarounds for users who need that functionality. Co-Authored-By: Warp <agent@warp.dev>
1 parent f473551 commit e62850b

File tree

2 files changed

+142
-33
lines changed

2 files changed

+142
-33
lines changed

CHANGELOG.md

Lines changed: 79 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,85 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
### Project Setup
11-
- Initial repository structure
12-
- pixi configuration with test/benchmark/pre-commit tasks
13-
- MIT License
14-
- Documentation framework (README, CHANGELOG, WARP.md)
15-
- GitHub Actions workflows for CI/CD
16-
17-
## [0.1.0] - TBD
18-
19-
**Status:** 🚧 In Development
20-
21-
### Planned Features
22-
- Basic INI parsing (sections, key=value pairs)
23-
- INI writer functionality
24-
- Support for # and ; comments
25-
- Multiline value handling
26-
- Core test suite
27-
- Python configparser basic compatibility
10+
## [0.1.0] - 2026-01-13
11+
12+
**Status:** ✅ Production Ready
13+
14+
First production release of mojo-ini! A native Mojo INI file parser and writer with Python `configparser` compatibility.
15+
16+
### Added
17+
18+
#### Core Functionality
19+
- **Lexer** (364 LOC): Complete tokenization with 7 token types (EOF, NEWLINE, COMMENT, SECTION, KEY, VALUE, EQUALS)
20+
- **Parser** (171 LOC): Builds `Dict[String, Dict[String, String]]` from tokens
21+
- **Writer** (142 LOC): Serializes Dict structures to INI format
22+
- **Public API** (`__init__.mojo`): Clean imports `from ini import parse, to_ini, parse_file, write_file`
23+
24+
#### INI Features
25+
- Section headers: `[section_name]`
26+
- Key-value pairs with `=` or `:` separators
27+
- Comments: `#` (hash) and `;` (semicolon) styles
28+
- Inline comments after values
29+
- **Multiline values**: Indented continuation lines (Python configparser compatible)
30+
- Empty values and empty sections
31+
- Special characters in values (URLs, paths, emails, Unicode)
32+
- Default section (empty string key) for keys before any `[section]`
33+
34+
#### File I/O
35+
- `parse_file(path)`: Read and parse INI files
36+
- `write_file(path, data)`: Write Dict structures to INI files
37+
38+
#### Testing
39+
- **46 tests** across 5 test suites (100% passing)
40+
- Lexer tests (9 tests): Token generation and position tracking
41+
- Parser tests (10 tests): Structure building, edge cases, errors
42+
- Writer tests (9 tests): Formatting, roundtrip validation
43+
- Fixture tests (7 tests): Real-world INI files (sample, git, mypy, windows, multiline, edge cases)
44+
- Error tests (11 tests): Malformed input, Unicode, stress tests (10K char lines, 100+ sections)
45+
46+
#### Examples
47+
- `examples/read_example.mojo`: Basic parsing demonstration
48+
- `examples/write_example.mojo`: INI generation demonstration
49+
- `examples/file_io_example.mojo`: File reading/writing with modifications
50+
51+
#### Documentation
52+
- Comprehensive README with Quick Start, usage examples, limitations
53+
- `WARP.md`: Development guidelines and architecture documentation
54+
- Python comparison benchmarks (70-108 µs parse, 8-12 µs write)
55+
56+
### Python configparser Compatibility
57+
58+
**Compatible:**
59+
- Basic key=value syntax
60+
- `[Section]` headers
61+
- `# comments` and `; comments`
62+
- Multiline values (indented continuations)
63+
- Inline comments
64+
- Empty values
65+
- Special characters in values
66+
67+
🚧 **Planned for v0.2.0:**
68+
- `[DEFAULT]` section with value inheritance
69+
- Value interpolation `%(var)s`
70+
- `ConfigParser` class API
71+
- Type converters (`getint`, `getboolean`, `getfloat`)
72+
- Case-insensitive mode
73+
74+
### Known Limitations
75+
76+
**Indented keys NOT supported** (by design, matches Python `configparser`):
77+
- Lines starting with whitespace are treated as multiline value continuations
78+
- Tab-indented keys (Git config style) require removing leading tabs
79+
- Workaround: Keep all keys at column 0, or use TOML/YAML for nested structures
80+
81+
### Technical Details
82+
83+
- **Language**: Pure Mojo (zero Python dependencies at runtime)
84+
- **LOC**: 1,426 total (733 source, 628 tests, 65 examples)
85+
- **Architecture**: Three-stage pipeline (Lexer → Parser → Writer)
86+
- **Error Handling**: Clear error messages with line numbers and context
87+
- **Package Manager**: pixi for reproducible builds
88+
- **Pre-commit**: TOML/YAML/JSON validation, whitespace/EOF checks
2889

2990
---
3091

README.md

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ Parse and write INI configuration files in native Mojo with zero Python dependen
1717
-**Comprehensive Tests** - Full test coverage
1818
-**Zero Dependencies** - Pure Mojo implementation
1919

20-
**Status**: 🚧 **In Development** - v0.1.0 coming soon
20+
**Status**: **v0.1.0 Released** - Production ready
2121

2222
## Quick Start
2323

2424
**Parsing INI Files:**
2525

2626
```mojo
27-
from ini.parser import parse
27+
from ini import parse
2828
2929
var config = parse("""
3030
[Database]
@@ -46,7 +46,7 @@ print(config["Server"]["debug"]) # true
4646
**Writing INI Files:**
4747

4848
```mojo
49-
from ini.writer import to_ini
49+
from ini import to_ini
5050
5151
var data = Dict[String, Dict[String, String]]()
5252
data["App"] = Dict[String, String]()
@@ -93,7 +93,7 @@ cp -r mojo-ini/src/ini your-project/lib/ini
9393
### Basic Parsing
9494

9595
```mojo
96-
from ini.parser import parse
96+
from ini import parse
9797
9898
var config = parse("""
9999
[DEFAULT]
@@ -110,33 +110,52 @@ print(config["API"]["timeout"]) # 30
110110

111111
### File I/O
112112

113-
> ⚠️ **Coming in v0.1.0** - File I/O convenience functions not yet implemented. Use Mojo's built-in file operations for now:
114-
115113
```mojo
116-
from ini.parser import parse
117-
from ini.writer import to_ini
114+
from ini import parse_file, write_file
118115
119116
# Read from file
120-
with open("config.ini", "r") as f:
121-
var content = f.read()
122-
var config = parse(content)
117+
var config = parse_file("config.ini")
123118
124119
# Modify
125120
config["Server"]["port"] = "8080"
126121
127122
# Write back
128-
with open("config.ini", "w") as f:
129-
f.write(to_ini(config))
123+
write_file("config.ini", config)
130124
```
131125

126+
See `examples/file_io_example.mojo` for a complete example.
127+
128+
### Multiline Values
129+
130+
Indented lines are treated as continuations (Python configparser behavior):
131+
132+
```mojo
133+
from ini import parse
134+
135+
var config = parse("""
136+
[Database]
137+
connection_string = postgresql://host:5432/db
138+
?sslmode=require
139+
&timeout=10
140+
""")
141+
142+
# Result: connection_string contains all three lines with newlines
143+
print(config["Database"]["connection_string"])
144+
# postgresql://host:5432/db
145+
# ?sslmode=require
146+
# &timeout=10
147+
```
148+
149+
**Important:** Lines starting with whitespace are ALWAYS treated as continuations, not as new keys. This matches Python `configparser` behavior.
150+
132151
### Python configparser Compatibility
133152

134153
> ⚠️ **Coming in v0.2.0** - ConfigParser API with type converters planned for future release.
135154
136155
For now, all values are strings. Manual conversion:
137156

138157
```mojo
139-
from ini.parser import parse
158+
from ini import parse
140159
141160
var config = parse("...")
142161
@@ -161,6 +180,35 @@ var timeout = float64(config["API"]["timeout"]) # Float64
161180
- Type conversion helpers (getint, getboolean, etc.)
162181
- Case-insensitive section/key names (optional)
163182

183+
## Known Limitations
184+
185+
### Indented Keys Not Supported
186+
187+
**By design**, keys with leading whitespace are treated as multiline value continuations:
188+
189+
```ini
190+
# ❌ This does NOT create a key named "indented_key"
191+
[Section]
192+
key1 = value1
193+
indented_key = value2 # This becomes part of key1's value!
194+
```
195+
196+
This matches Python `configparser` behavior. If you need indented keys, consider:
197+
- **TOML**: Native support for nested tables ([mojo-toml](https://github.com/databooth/mojo-toml))
198+
- **YAML**: Indentation-based structure
199+
- **Remove indentation**: Keep all keys at column 0
200+
201+
### Tab-Indented Keys (Git Config Style)
202+
203+
Git config files use tabs before keys, which mojo-ini treats as continuations. To use Git configs:
204+
205+
```bash
206+
# Convert tabs to standard format
207+
sed 's/^\t//' .git/config > config.ini
208+
```
209+
210+
Or manually remove leading tabs from keys.
211+
164212
## Python Compatibility
165213

166214
mojo-ini aims for high compatibility with Python's `configparser`:
@@ -173,7 +221,7 @@ mojo-ini aims for high compatibility with Python's `configparser`:
173221
| Multiline values |||
174222
| Inline comments |||
175223
| Value interpolation || 🚧 Planned |
176-
| Type converters || |
224+
|| Type converters || 🚧 Planned |
177225
| Case insensitive || 🚧 Planned |
178226

179227
## Development

0 commit comments

Comments
 (0)