Skip to main content

icfpy

PyPI Python versions License: MIT

A pure-Python library to parse, validate, build in-memory, write, and convert Indent Comma Format (ICF) files, plus generate ICX companion index files.

  • Implements the ICF language specification v1.1 — schema annotations (!indexes / !defaults / !constraints / !expressions), row !overrides, primary objects, defaults + overrides resolution, and multiline value rows — while staying fully backward compatible with v1.0 documents.
  • Implements the ICX index specification v1.2 — auto-harvested Tags, per-record Summary providers, @sourcebytes, join_tags/split_tags helpers — plus the resolved export icfpy.write_resolved(...) that bakes defaults/overrides into plain ICF output.
  • Python 3.9+, zero runtime dependencies (standard library only).
  • JSON output is hand-rolled — no third-party JSON/CSV/XML library.
  • A faithful behavioral port of the Java library icfj.

What is ICF?

ICF is a compact, hierarchical, schema-driven data format that combines the compactness of CSV, the readability of YAML, and the hierarchy of JSON/XML. A document declares its schema once (@schema), optionally carries user metadata (@metadata) and shared reference data (@masters), then stores records positionally (@data / @record) as comma-separated rows. See the ICF and ICX specifications for the full format definition.

Install

pip install icfpy

For development from a checkout (with the dev tools):

pip install -e ".[dev]"

Quickstart

import icfpy

# 1. Parse ICF text (or a file path) and navigate the data.
doc = icfpy.parse(open("invoice.icf", encoding="utf-8").read())
data = doc.to_icf_node()
city = data.path("indexdata").path("masterindex").path("Project").path("Location").as_text()

# `path(...)` never raises — absent fields yield IcfMissing, so chains are safe.
missing = data.path("nope").path("still_nope").as_text()   # -> ""

# 2. Validate (never raises on content problems).
result = icfpy.validate(icf_text)
if not result.is_valid:
    for err in result.errors:
        print(err)        # e.g. "ERROR (line 7) [FIELD_COUNT_MISMATCH] ..."

# 3. Build a node from scratch and write it back to ICF text.
root = icfpy.IcfNode.object()
root.put_object("vendor").put("id", "V001").put("email", "v@example.com")
root.put_array("items").add_object().put("sku", "A1").put("qty", 100)
icf = icfpy.write(root)   # infers a schema; object -> one record, array -> many

# 4. Generate the ICX companion index and serialize it.
source = icfpy.parse(icf)
icx_doc = icfpy.generate_icx(source, "invoice.icf", icf)   # populates Line/Offset/Size/Checksum
icx_text = icfpy.write(icx_doc)

Facade API

Function Description
icfpy.parse(text_or_path) Parse; raises IcfParseError on error-level diagnostics.
icfpy.parse_lenient(text) Best-effort parse; never raises on content errors.
icfpy.validate(text_or_path) Returns a ValidationResult (errors + warnings).
icfpy.is_valid(text_or_path) True when there are no error-level diagnostics.
icfpy.write(doc_or_node[, path]) Serialize to ICF text; optionally write a UTF-8 file.
icfpy.write_with_checksum(doc_or_node[, path]) Like write, but injects a computed @checksum (spec §19, honoring @hashmethod).
icfpy.write_resolved(doc[, path]) Write with Phase-5 resolution baked in: defaults/overrides inlined, all annotations dropped.
icfpy.generate_icx(source[, name[, text], summary_provider=, tag_provider=]) Build the ICX v1.2 index as an IcfDocument (auto-harvested Tags, optional Summary).
icfpy.join_tags(tags) / icfpy.split_tags(cell) Join / split ICX Tags cells (+-separated, escape-aware).

See DOCUMENTATION.md for the complete public API and CLAUDE.md for the spec gotchas that shape the implementation.

Development

pip install -e .[dev]
pytest              # run the test suite (includes four round-trip fixtures)
ruff check .        # lint
ruff format --check .
mypy src/icfpy      # type-check

License

Copyright (c) 2026 Edison Williams. The ICF/ICX specifications are licensed under CC BY 4.0. The icfpy library is licensed under MIT License.

Download files

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

Source Distribution

icfpy-1.2.0.tar.gz (127.7 kB view details)

Uploaded Source

Built Distribution

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

icfpy-1.2.0-py3-none-any.whl (56.4 kB view details)

Uploaded Python 3

File details

Details for the file icfpy-1.2.0.tar.gz.

File metadata

  • Download URL: icfpy-1.2.0.tar.gz
  • Upload date:
  • Size: 127.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for icfpy-1.2.0.tar.gz
Algorithm Hash digest
SHA256 a04485643f948247c58de70cec816dbd26293320834f89968d6fda12f7fea198
MD5 623ab5b80990c7726ab29a1c20b2f59c
BLAKE2b-256 6d1dc602099317d00e4dc0149d0e8482455c6e1e6db608e277bfd99d554e149d

See more details on using hashes here.

File details

Details for the file icfpy-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: icfpy-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 56.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for icfpy-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6c6f5ae012b27e2dd3c97eb8398d329a3dbb2c18bd29103ab2fe9ed5cf5daa38
MD5 5d32f98a57f4ae1acc8b2a8a9ae05dc6
BLAKE2b-256 f673851827ce70d46c1ab6c4df39b57a60dadc73bb356147b053087a745e0ecf

See more details on using hashes here.

Release history Release notifications | RSS feed

1.2.1

2 files

This release

1.2.0 This release

2 files

1.0.0

2 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