0
# Tomli-W
1
2
A lil' TOML writer for Python that serializes Python data structures to TOML (Tom's Obvious, Minimal Language) format. It serves as a write-only counterpart to the Tomli TOML parser, providing functionality to serialize Python dictionaries and other data structures into valid TOML format. The library is fully compatible with TOML v1.0.0 specification and supports customizable indentation for array content.
3
4
## Package Information
5
6
- **Package Name**: tomli-w
7
- **Language**: Python
8
- **Installation**: `pip install tomli-w`
9
- **Requirements**: Python >=3.9
10
11
## Core Imports
12
13
```python
14
import tomli_w
15
```
16
17
Import specific functions:
18
19
```python
20
from tomli_w import dumps, dump
21
```
22
23
## Basic Usage
24
25
```python
26
import tomli_w
27
28
# Create a Python dictionary
29
doc = {"table": {"nested": {}, "val3": 3}, "val2": 2, "val1": 1}
30
31
# Convert to TOML string
32
toml_string = tomli_w.dumps(doc)
33
print(toml_string)
34
# Output:
35
# val2 = 2
36
# val1 = 1
37
#
38
# [table]
39
# val3 = 3
40
#
41
# [table.nested]
42
43
# Write to file
44
with open("config.toml", "wb") as f:
45
tomli_w.dump(doc, f)
46
```
47
48
### Custom Indentation
49
50
```python
51
import tomli_w
52
53
doc = {"fruits": ["orange", "kiwi", "papaya"]}
54
55
# Use custom indentation for arrays
56
toml_string = tomli_w.dumps(doc, indent=2)
57
print(toml_string)
58
# Output:
59
# fruits = [
60
# "orange",
61
# "kiwi",
62
# "papaya",
63
# ]
64
```
65
66
### Multi-line Strings
67
68
```python
69
import tomli_w
70
71
doc = {"message": "Line 1\nLine 2\nLine 3"}
72
73
# Enable multi-line string literals
74
toml_string = tomli_w.dumps(doc, multiline_strings=True)
75
print(toml_string)
76
# Output:
77
# message = """
78
# Line 1
79
# Line 2
80
# Line 3
81
# """
82
```
83
84
## Capabilities
85
86
### String Serialization
87
88
Converts Python objects to TOML formatted strings.
89
90
```python { .api }
91
def dumps(
92
obj: Mapping[str, Any],
93
/,
94
*,
95
multiline_strings: bool = False,
96
indent: int = 4
97
) -> str:
98
"""
99
Serialize a Python mapping to a TOML string.
100
101
Args:
102
obj: The Python object to serialize (must be a mapping/dictionary)
103
multiline_strings: Whether to allow multi-line string literals (default: False)
104
indent: Indentation width for array content (default: 4, must be non-negative)
105
106
Returns:
107
str: TOML-formatted string
108
109
Raises:
110
ValueError: If indent is negative or time objects have timezone info
111
TypeError: If obj contains unsupported types or invalid mapping keys
112
"""
113
```
114
115
### File Writing
116
117
Writes Python objects directly to TOML files.
118
119
```python { .api }
120
def dump(
121
obj: Mapping[str, Any],
122
fp: IO[bytes],
123
/,
124
*,
125
multiline_strings: bool = False,
126
indent: int = 4,
127
) -> None:
128
"""
129
Write a Python mapping to a TOML file.
130
131
Args:
132
obj: The Python object to serialize (must be a mapping/dictionary)
133
fp: File-like object opened in binary write mode
134
multiline_strings: Whether to allow multi-line string literals (default: False)
135
indent: Indentation width for array content (default: 4, must be non-negative)
136
137
Returns:
138
None
139
140
Raises:
141
ValueError: If indent is negative or time objects have timezone info
142
TypeError: If obj contains unsupported types or invalid mapping keys
143
"""
144
```
145
146
### Package Metadata
147
148
```python { .api }
149
__version__ = "1.2.0"
150
__all__ = ("dumps", "dump")
151
```
152
153
## Supported Data Types
154
155
The library supports the following Python types for TOML serialization:
156
157
### Basic Types
158
- `str` - TOML strings (basic strings with escaping)
159
- `int` - TOML integers
160
- `float` - TOML floats
161
- `bool` - TOML booleans (`True` → `true`, `False` → `false`)
162
163
### Numeric Types
164
- `decimal.Decimal` - TOML floats with proper precision handling
165
- `Decimal("inf")` → `inf`
166
- `Decimal("-inf")` → `-inf`
167
- `Decimal("nan")` → `nan`
168
169
### Date/Time Types
170
- `datetime.date` - TOML local dates (ISO 8601 format)
171
- `datetime.datetime` - TOML local datetimes (ISO 8601 format)
172
- `datetime.time` - TOML local times (ISO 8601 format, must not have timezone info)
173
174
### Container Types
175
- `list` - TOML arrays (with customizable indentation)
176
- `tuple` - TOML arrays (treated same as list)
177
- `dict` and other `Mapping` types - TOML tables or inline tables
178
179
### Type Constraints and Behavior
180
181
- **Time objects with timezone**: Will raise `ValueError`
182
- **Unsupported types**: Will raise `TypeError`
183
- **Invalid mapping keys**: Non-string keys will raise `TypeError`
184
- **Array formatting**: Arrays are formatted with trailing commas and customizable indentation
185
- **Inline tables**: Small mappings may be formatted as inline tables based on length heuristics
186
- **String escaping**: Automatic escaping of special characters in strings
187
- **Order preservation**: Dictionary insertion order is preserved in output
188
189
## Configuration Options
190
191
### multiline_strings Parameter
192
193
Controls how strings containing newlines are formatted:
194
195
- `False` (default): Preserves exact newline byte sequences using escape sequences
196
- `True`: Uses TOML multi-line string literals (may not preserve exact newline bytes)
197
198
```python
199
# Default behavior (preserves newline bytes)
200
tomli_w.dumps({"s": "line1\r\nline2"})
201
# s = "line1\r\nline2"
202
203
# Multi-line strings enabled
204
tomli_w.dumps({"s": "line1\r\nline2"}, multiline_strings=True)
205
# s = """
206
# line1
207
# line2
208
# """
209
```
210
211
### indent Parameter
212
213
Controls indentation width for array content (must be non-negative integer):
214
215
```python
216
data = {"items": ["a", "b", "c"]}
217
218
# Default indent=4
219
tomli_w.dumps(data)
220
# items = [
221
# "a",
222
# "b",
223
# "c",
224
# ]
225
226
# Custom indent=2
227
tomli_w.dumps(data, indent=2)
228
# items = [
229
# "a",
230
# "b",
231
# "c",
232
# ]
233
```
234
235
## Error Handling
236
237
The library raises specific exceptions for error conditions:
238
239
### ValueError
240
- Negative indent values: `ValueError("Indent width must be non-negative")`
241
- Time objects with timezone info: `ValueError("TOML does not support offset times")`
242
243
### TypeError
244
- Unsupported data types: `TypeError("Object of type 'X' is not TOML serializable")`
245
- Invalid mapping keys: `TypeError("Invalid mapping key 'X' of type 'Y'. A string is required.")`
246
247
## TOML Compliance and Limitations
248
249
- **TOML v1.0.0 compatible**: Produces valid TOML output for supported input types
250
- **No comments support**: Cannot write TOML comments (TOML comments are read-only)
251
- **No document sorting**: Respects input dictionary order, does not sort keys
252
- **Output validation**: No guarantee of validity for edge cases with custom types
253
- **Lossless round-trips**: Default string handling preserves exact byte sequences
254
- **Bare key optimization**: Simple keys are written without quotes when possible
255
256
For output validation, parse the result with a TOML parser like `tomli`:
257
258
```python
259
import tomli
260
import tomli_w
261
262
data = {"key": "value"}
263
toml_string = tomli_w.dumps(data)
264
265
# Validate output
266
try:
267
tomli.loads(toml_string)
268
print("Valid TOML")
269
except tomli.TOMLDecodeError:
270
print("Invalid TOML")
271
```