Skip to main content

euspinolia

CI PyPI Python License: MIT

A small, educational CSV/table library with its engine in Zig and a thin ctypes layer in Python. It parses a CSV into typed columns, reduces, filters and groups them, and writes them back out — faster than pandas for most of that, with no dependencies and a shared library that links nothing, not even libc.

The name comes from Euspinolia, the genus of the velvet ant known as the "panda ant".

>>> import euspinolia
>>> df = euspinolia.read_csv("people.csv")
>>> df
        name  age  score      city
0        ada   36   91.5    London
1      grace   45   88.0  New York
2  Doe, John   29  73.25     Paris

[3 rows x 4 columns]
>>> df["age"].to_list()
[36, 45, 29]
>>> df[df["age"] > 30]
    name  age  score      city
0    ada   36   91.5    London
1  grace   45   88.0  New York

[2 rows x 4 columns]
>>> df.groupby("city").agg({"score": "mean"})
       city  score
0    London   91.5
1  New York   88.0
2     Paris  73.25

[3 rows x 2 columns]

Install

pip install euspinolia

Wheels are published for Linux (x86_64, aarch64), macOS (x86_64, arm64) and Windows (x64, arm64), for any Python 3.9 or newer. On anything else, pip builds from source; that needs no Zig install either, since the build pulls it from the ziglang package.

To work from a checkout instead, see docs/development.md.

What it does

import euspinolia

df = euspinolia.read_csv("people.csv")   # parse a file
df = euspinolia.parse_csv(csv_text)      # parse text already in memory

df.shape          # (3, 4) — (rows, columns)
df.columns        # ('name', 'age', 'score', 'city')
df.dtypes         # (string, int, float, string)
df.head(2)        # the first two rows as tuples

column = df["age"]   # by name; df[1] works too
column[0]            # 36 — read straight out of the Zig buffer
column.to_list()     # [36, 45, 29]

column.sum()      # 110 — exact, reduced in Zig
column.mean()     # 36.666666666666664
column.min()      # 29
column.max()      # 45

df[df["age"] > 30]                          # a new DataFrame with the matching rows
df[(df["age"] > 30) & (df["score"] < 90)]   # conditions chain with &
df.filter("city", "==", "Paris")            # the same thing, as a call

df.groupby("city").agg({"score": "mean", "age": "max"})   # one row per city
df.groupby("city").sum()                                  # every numeric column
df.groupby("city").count()                                # rows per group

df.to_csv("out.csv")   # write it back out; reads back as the same frame
df.to_csv()            # or as a string

with euspinolia.read_csv("people.csv") as df:
    ...   # Zig-side memory freed on the way out; df.close() does the same

Every column has one type — int, float or string — inferred from its values. Reductions keep that type, so an integer column sums exactly. A filtered or grouped frame owns its own memory and outlives its source. Errors are ordinary Python exceptions: FileNotFoundError, ParseError, TypeError for text where a number was needed, OverflowError for a sum that leaves 64 bits.

The full reference is in docs/api.md.

Performance

500,000 rows, 5 columns, 18 MB; best of five on one laptop, against pandas 3.0 and the standard csv module:

euspinolia pandas csv module + Python
read + parse 114 ms 183 ms 335 ms
write back out (to_csv) 63 ms 478 ms 294 ms
sum an int column 0.2 ms 0.2 ms 10.1 ms
filter, keeping half the rows 10.5 ms 8.7 ms 13.8 ms
groupby (5 groups), mean 7.5 ms 23.6 ms 47.8 ms

Parsing, writing and grouping are ahead of pandas; reductions are a wash, as native code against native code should be; filtering is the one loss, because the result copies its strings rather than sharing them. What each number means, and how to run the benchmark yourself, is in docs/benchmarks.md.

How it works

[Python]  df = euspinolia.read_csv("data.csv")
              │  ctypes call
              ▼
[Zig]     CSV scanner → type inference → one typed array per column
              │
              ├─▶ sum / mean / min / max   → one value
              ├─▶ filter, groupby          → a new frame
              └─▶ to_csv                   → bytes
              │  opaque handle + borrowed column pointers
              ▼
[Python]  DataFrame / Column wrap the handle; df["age"][0] reads the
          Zig buffer through ctypes, no copy

Columns are struct-of-arrays: int and float are flat []i64 / []f64, strings are one packed byte buffer plus offsets. A filter or an aggregate walks one contiguous array; a groupby hashes each key into a dense group id and folds into a flat accumulator; Python reads numeric columns in place. Module by module: docs/internals.md.

Scope

This is a teaching project, and the scope was fixed at the start: one delimiter, one header row, three column types, and the operations above. Multi-index, date/time types, NaN semantics, join/merge and pivot tables are out, on purpose. The goal is not a real table engine but a subset that genuinely works, is fast for real reasons, and can be read end to end in an afternoon — about 3,000 lines of Zig, tests included, and 900 of Python.

Documentation

  • API reference — every function, method, argument and exception
  • Internals — the Zig side, module by module, and the ABI
  • Benchmarks — the numbers above, what they measure and why they come out that way
  • Development — building, testing, cross-compiling wheels, releasing
  • Changelog

License

MIT.

Metadata

Release files for euspinolia 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for euspinolia 0.1.0
File Size Uploaded
euspinolia-0.1.0.tar.gz 58.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for euspinolia 0.1.0
File
euspinolia-0.1.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
euspinolia-0.1.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
euspinolia-0.1.0-py3-none-manylinux2014_x86_64.musllinux_1_1_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64, Linux musl 1.1+ x86-64 Details
euspinolia-0.1.0-py3-none-manylinux2014_aarch64.musllinux_1_1_aarch64.whl Python 3 none Linux musl 1.1+ ARM64, Linux glibc 2.17+ ARM64 Details
euspinolia-0.1.0-py3-none-macosx_11_0_x86_64.whl Python 3 none macOS 11.0+ x86-64 Details
euspinolia-0.1.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 1.1 MB

Release files / euspinolia-0.1.0.tar.gz

Download URL euspinolia-0.1.0.tar.gz
Size 58.2 kB
Tags Source
SHA-256 checksum
How to use checksums
30766288013ebaecbc2e36ceb3134d267f6df9d956c247e487adebc552cbb1db
BLAKE2b-256 checksum
How to use checksums
18104553833894fda97df9a528d827417b745719fee9432c71c77aa0e160e98e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / euspinolia-0.1.0-py3-none-win_arm64.whl

Download URL euspinolia-0.1.0-py3-none-win_arm64.whl
Size 173.2 kB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
368c6672116a0583ba4177db11d2e3a4cdc94e9a7ddca948a17ddc737199e5b9
BLAKE2b-256 checksum
How to use checksums
2be86ba02cd2b5d5dbd0c8ceff0d9551827c50219ab0ea3ec0e012807772d20b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / euspinolia-0.1.0-py3-none-win_amd64.whl

Download URL euspinolia-0.1.0-py3-none-win_amd64.whl
Size 211.3 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
96a8b2c78cf3abdc98c2abc245360b309f140341c741cdb3b42d53046a4c5960
BLAKE2b-256 checksum
How to use checksums
540f43620fc4034e34791548a860dfdd9c3154b800f8412b5bd6cee74826579b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / euspinolia-0.1.0-py3-none-manylinux2014_x86_64.musllinux_1_1_x86_64.whl

Download URL euspinolia-0.1.0-py3-none-manylinux2014_x86_64.musllinux_1_1_x86_64.whl
Size 153.9 kB
Tags Linux glibc 2.17+ x86-64 Linux musl 1.1+ x86-64 Python 3
SHA-256 checksum
How to use checksums
47e1694c7c987068b5ce11a021227f993c26e05279084a2d3d0140ce9cf00533
BLAKE2b-256 checksum
How to use checksums
e198f1ab5986d52d57c3af26d5d7d954e1879b2c58f80280d4aab2553bbefad5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / euspinolia-0.1.0-py3-none-manylinux2014_aarch64.musllinux_1_1_aarch64.whl

Download URL euspinolia-0.1.0-py3-none-manylinux2014_aarch64.musllinux_1_1_aarch64.whl
Size 156.1 kB
Tags Linux glibc 2.17+ ARM64 Linux musl 1.1+ ARM64 Python 3
SHA-256 checksum
How to use checksums
b5cf84bbb324f36370b5606de694026790b2e301376e4afc988b14df17a4c1a6
BLAKE2b-256 checksum
How to use checksums
0c5348ae9d1111c85369230598e43cd37486a31e2d4e3bd06ee0dd533227987f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / euspinolia-0.1.0-py3-none-macosx_11_0_x86_64.whl

Download URL euspinolia-0.1.0-py3-none-macosx_11_0_x86_64.whl
Size 157.0 kB
Tags Python 3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
f34254278e10d89e662ecd80d5992abeb94029464b3a9018d22542c4d7155c67
BLAKE2b-256 checksum
How to use checksums
92d9ebac5127d32d39dc379e977ba6930f873158ed1559171a5c53a1cedb68c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / euspinolia-0.1.0-py3-none-macosx_11_0_arm64.whl

Download URL euspinolia-0.1.0-py3-none-macosx_11_0_arm64.whl
Size 141.7 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ef2686d33826f346eca1be4c14ae141b35dd8d234ff1330b0232f90c2b7f86b3
BLAKE2b-256 checksum
How to use checksums
497c915802f3dc82b07edbb3cd5e62f0484c3f3255e4200251841098d6ecb687
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

8 release files

0.1.1

8 release files

This release

0.1.0 This release

7 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page