Skip to main content

Typed CSVs via header-embedded types and validators

Project description

typedcsv

PyPI version Python versions License

Typed CSVs via header-embedded types (sigils or :type) plus optional header-embedded validationstdlib-only, Python 3.10+.

Default extensions (by convention):

  • .tcsv for comma-separated typed CSV
  • .ttsv for 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:datetime becomes 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=value pairs inside [ ... ].
  • required and unique are flag-only validators (no =).
  • re= uses Python re.fullmatch.
  • in= uses | as separator.
  • Unknown validator keys raise an error.

Missing values (nullable by default)

  • An empty cell ("") is missing.
  • For str columns, missing stays "".
  • For non-str columns, missing becomes None.
  • Missing values skip validation.
  • required (sigil ! or validator) rejects missing values.
  • unique ignores 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 cell
  • booltrue / false
  • datetimeisoformat()
  • floatrepr(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 standard csv.writer
  • typedcsv.DictWriter(f, fieldnames, ...) → writes typed dict rows with canonical formatting

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typedcsv_lib-0.2.0.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typedcsv_lib-0.2.0-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file typedcsv_lib-0.2.0.tar.gz.

File metadata

  • Download URL: typedcsv_lib-0.2.0.tar.gz
  • Upload date:
  • Size: 13.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for typedcsv_lib-0.2.0.tar.gz
Algorithm Hash digest
SHA256 139dbfd36f64b26845d2e738dd5890cae09c76a6ed793807e0cb6ebcabee450d
MD5 2da11beb00340e1f5c12c91ddc47d77c
BLAKE2b-256 8fb04de1ddd8e290c0f4063be0bfbe04d3550a3b4c2c5bfe538f29894c505359

See more details on using hashes here.

File details

Details for the file typedcsv_lib-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: typedcsv_lib-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 10.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for typedcsv_lib-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a2384b1d79c6a57a3e53ff3172a5ea7896d42985732c9f5b0c5575373f289b33
MD5 6d65be53f1b161a1061f68999f87ce68
BLAKE2b-256 bee6bb6563193479f17826a7ccce09fbd77943911ddae925a252ea19f8079427

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page