typedcsv
Typed CSVs via header-embedded types (sigils or :type) plus optional header-embedded validation — stdlib-only, Python 3.10+.
Default extensions (by convention):
.tcsvfor comma-separated typed CSV.ttsvfor tab-separated typed TSV
The core lives in a single module and is copy-pasteable into projects.
pip install typedcsv-lib
Header typing
Declare types using either suffix sigils or explicit :type (not both on the same column).
| Type | Sigil (suffix) | Explicit |
|---|---|---|
int |
# |
:int |
float |
% |
:float |
bool |
? |
:bool |
datetime |
@ |
:datetime |
str |
$ |
:str |
Untyped columns default to str.
Optional constraint sigils (suffix, after the type sigil):
| Constraint | Sigil |
|---|---|
| required | ! |
| unique | + |
Order is flexible, but the recommended style is: type + optional unique + optional required.
Examples:
id#+(unique int)email$!(required str)slug$+!(unique + required str)
Logical column names are the header names with the type marker removed:
age#becomes key"age"created:datetimebecomes key"created"
Validators
Add an optional validator clause after the type marker:
age# [min=0 max=120]
ratio% [min=0 max=1]
status$ [in=OPEN|CLOSED|PENDING]
code$ [re=^[A-Z]{3}\d{2}$]
created@ [min=2020-01-01T00:00:00 max=2030-12-31T23:59:59]
email:str [required unique]
Notes:
- Validators are space-separated
key=valuepairs inside[ ... ]. requiredanduniqueare flag-only validators (no=).re=uses Pythonre.fullmatch.in=uses|as separator.- Unknown validator keys raise an error.
Missing values (nullable by default)
- An empty cell (
"") is missing. - For
strcolumns, missing stays"". - For non-
strcolumns, missing becomesNone. - Missing values skip validation.
required(sigil!or validator) rejects missing values.uniqueignores missing values (multiple empty cells are allowed).
Reading
import typedcsv
with open("data.tcsv", newline="") as f:
for row in typedcsv.DictReader(f):
print(row)
Example CSV:
id#,name$,active?,created@
1,Alice,true,2021-05-01T12:30:00
2,Bob,false,
Produces:
{'id': 1, 'name': 'Alice', 'active': True, 'created': datetime(2021, 5, 1, 12, 30)}
{'id': 2, 'name': 'Bob', 'active': False, 'created': None}
Writing (canonical formatting)
None→ empty cellbool→true/falsedatetime→isoformat()float→repr(f)- Header preserved exactly as provided to
DictWriter(fieldnames=...)
import typedcsv
from datetime import datetime
rows = [
{"id": 1, "name": "Alice", "active": True, "created": datetime(2021, 5, 1, 12, 30)},
{"id": 2, "name": "Bob", "active": False, "created": None},
]
with open("out.tcsv", "w", newline="") as f:
w = typedcsv.DictWriter(f, fieldnames=["id#", "name$", "active?", "created@"])
w.writeheader()
w.writerows(rows)
More examples
Validators with quoted values
name$ [in="Alice Smith"|Bob]
Regex validation (fullmatch)
code$ [re=^[A-Z]{3}\d{2}$]
ABC12
Type inference for untyped columns
import typedcsv
import io
data = "a,b\n1,true\n2,false\n"
rows = list(typedcsv.DictReader(io.StringIO(data), infer_types=True))
Errors
Parsing/validation failures raise TypedCSVError with context:
row(1-based; header row is 1)col(0-based)column(logical name)header(raw header cell)value(raw cell)reason(short message)
API reference (csv-compatible)
typedcsv mirrors Python's csv module API and is designed to be a drop-in replacement where you want typed rows.
typedcsv.reader(f, ...)→ yields typed list rows (header consumed)typedcsv.DictReader(f, ...)→ yields typed dict rows keyed by logical names (header consumed)typedcsv.writer(f, ...)→ returns a standardcsv.writertypedcsv.DictWriter(f, fieldnames, ...)→ writes typed dict rows with canonical formatting
Metadata
Release files for typedcsv-lib 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| typedcsv_lib-0.2.0.tar.gz | 13.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| typedcsv_lib-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.2 kB
Release files / typedcsv_lib-0.2.0.tar.gz
| Download URL | typedcsv_lib-0.2.0.tar.gz |
|---|---|
| Size | 13.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
139dbfd36f64b26845d2e738dd5890cae09c76a6ed793807e0cb6ebcabee450d
|
|
BLAKE2b-256 checksum How to use checksums |
8fb04de1ddd8e290c0f4063be0bfbe04d3550a3b4c2c5bfe538f29894c505359
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Release files / typedcsv_lib-0.2.0-py3-none-any.whl
| Download URL | typedcsv_lib-0.2.0-py3-none-any.whl |
|---|---|
| Size | 10.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a2384b1d79c6a57a3e53ff3172a5ea7896d42985732c9f5b0c5575373f289b33
|
|
BLAKE2b-256 checksum How to use checksums |
bee6bb6563193479f17826a7ccce09fbd77943911ddae925a252ea19f8079427
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|