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.1.tar.gz (128.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.1-py3-none-any.whl (56.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for icfpy-1.2.1.tar.gz
Algorithm Hash digest
SHA256 aa466e2e77594ecc177d60d8517436bbcde9025b07b249477fd6ce3378f67043
MD5 94610a31d63bec3387f8932169c73a35
BLAKE2b-256 89736506366235389d169533a50fa2e231e11df8c0269845ca0649ea2f8dd47b

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for icfpy-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6e1d3c715a442bbdc08307ab9b9afc7c29b6e0a4699cd45c6b5cdc3b8300ad7a
MD5 5eb94033f51428c75aa1fccf55219990
BLAKE2b-256 d4cad86a3f9574abca1f8a265140ec0cb9f5a8ab8254cc20075e1fe2b44cec10

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.2.1 This release

2 files

1.2.0

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