Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# the repo. Unless a later match takes precedence,
# @global-owner1 and @global-owner2 will be requested for
# review when someone opens a pull request.
* @washingtonpost/news-engineering
* @washingtonpost/news-engineering @WashPost/data-reporting

# Order is important; the last matching pattern takes the most
# precedence. When someone opens a pull request that only
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/_python-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
python-version: "3.11"

- name: Install Zig
run: python -m pip install ziglang==0.11.0 wheel
run: python -m pip install ziglang==0.15.2 wheel

- name: Build wheels
run: python python/make_wheels.py ${{ matrix.architecture }}-${{ matrix.os }}
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@v4
- uses: goto-bus-stop/setup-zig@v1
with:
version: 0.11.0
version: 0.15.2
- name: Get output paths
uses: kanga333/variable-mapper@master
id: map
Expand All @@ -36,21 +36,25 @@ jobs:
"linux-gnu": {
"libExt": "so",
"libName": "libfastfec",
"libDir": "lib",
"exeExt": ""
},
"macos": {
"libExt": "dylib",
"libName": "libfastfec",
"libDir": "lib",
"exeExt": ""
},
"windows": {
"libExt": "dll",
"libName": "fastfec",
"libDir": "bin",
"exeExt": ".exe"
},
"wasm": {
"libExt": "wasm",
"libName": "fastfec",
"libDir": "bin",
"exeExt": ""
}
}
Expand All @@ -66,10 +70,10 @@ jobs:
run: zip -j fastfec-${{ matrix.os }}-${{ matrix.architecture }}-${{ inputs.version }}.zip zig-out/bin/fastfec${{ steps.map.outputs.exeExt }}
- name: Move output library
if: matrix.os != 'wasm'
run: mv zig-out/lib/${{ steps.map.outputs.libName }}.${{ steps.map.outputs.libExt }} libfastfec-${{ matrix.os }}-${{ matrix.architecture }}-${{ inputs.version }}.${{ steps.map.outputs.libExt }}
run: mv zig-out/${{ steps.map.outputs.libDir }}/${{ steps.map.outputs.libName }}.${{ steps.map.outputs.libExt }} libfastfec-${{ matrix.os }}-${{ matrix.architecture }}-${{ inputs.version }}.${{ steps.map.outputs.libExt }}
- name: Move output library (wasm)
if: matrix.os == 'wasm'
run: mv zig-out/lib/${{ steps.map.outputs.libName }}.${{ steps.map.outputs.libExt }} libfastfec-${{ inputs.version }}.${{ steps.map.outputs.libExt }}
run: mv zig-out/${{ steps.map.outputs.libDir }}/${{ steps.map.outputs.libName }}.${{ steps.map.outputs.libExt }} libfastfec-${{ inputs.version }}.${{ steps.map.outputs.libExt }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
if: matrix.os != 'wasm'
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
- uses: actions/checkout@v4
- uses: goto-bus-stop/setup-zig@v1
with:
version: 0.11.0
version: 0.15.2
- name: Run zig test
run: zig build test

Expand All @@ -17,9 +17,12 @@ jobs:
timeout-minutes: 5
strategy:
matrix:
python-version: [3.8]
python-version: [3.11]
steps:
- uses: actions/checkout@v4
- uses: goto-bus-stop/setup-zig@v1
with:
version: 0.15.2
- name: Setup Python
uses: actions/setup-python@v4
with:
Expand Down
15 changes: 7 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
files: \.py$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
rev: v5.0.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/pycqa/isort
rev: 5.10.1
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
args: ["--profile", "black", --line-length=120]
args: ["--profile", "black", "--line-length=120"]

# black
- repo: https://github.com/ambv/black
rev: 21.9b0
- repo: https://github.com/psf/black
rev: 24.10.0
hooks:
- id: black
args: # arguments to configure black
- --line-length=120
language_version: python3.9

# flake8
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
- repo: https://github.com/PyCQA/flake8
rev: 7.1.1
hooks:
- id: flake8
args: # arguments to configure flake8
Expand Down
105 changes: 105 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# AGENTS.md

## What this repo is

FastFEC is a C parser for raw `.fec` filings. It has:

- a CLI binary (`fastfec`) that writes parsed CSV files
- a shared C library (`libfastfec`)
- a Python wrapper package in `python/` that loads the shared library

## Repo structure

- `src/`: C source code for parser, CLI, writer, and bundled PCRE
- `build.zig`: Zig build script for CLI, shared lib, and C tests
- `scripts/`: mapping generation scripts (`generate_mappings.py`)
- `python/src/fastfec/`: Python wrapper (`ctypes` client + utils)
- `python/tests/`: Python tests + fixture `.fec` files

## macOS setup

1. Install Zig:

```sh
brew install zig
```

2. Verify:

```sh
zig version
```

## Build (C CLI + shared lib)

From repo root:

```sh
zig build
```

Outputs:

- `zig-out/bin/fastfec`
- `zig-out/lib/libfastfec.dylib`

## Run CLI

Parse a local filing:

```sh
./zig-out/bin/fastfec -x -s python/tests/fixtures/13360.fec /private/tmp/fastfec_out 13360
```

Notes:

- `-x` disables stdin and forces file input mode
- output files are written under `{output_dir}/{filing_id}/`

## Run C tests

```sh
zig build test
```

## Makefile shortcuts

From repo root:

```sh
make help
```

Main targets:

- `make build`: build CLI + shared library
- `make c-test`: run C tests
- `make cli-smoke`: parse fixture filing and write CSV output to `/private/tmp/fastfec_make_smoke`
- `make py-setup`: create `python/.venv`
- `make py-install`: install Python dev dependencies
- `make py-test`: run Python tests (`tox -e py`)
- `make all`: run full verification (`build`, `c-test`, `cli-smoke`, `py-test`)

## Python interface setup

From repo root:

```sh
python3 -m venv python/.venv
source python/.venv/bin/activate
cd python
pip install -r requirements-dev.txt
```

## Run Python tests

```sh
source python/.venv/bin/activate
cd python
tox -e py
```

## Dependency notes

- The Python package depends on `ziglang==0.15.2` for wheel/build workflows.
- Requires Zig >= 0.15.0 (build.zig uses the 0.15 `root_module` API).
47 changes: 47 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
SHELL := /bin/zsh

ZIG ?= zig

VENV := python/.venv
FIXTURE := python/tests/fixtures/13360.fec
SMOKE_OUT := /private/tmp/fastfec_make_smoke

.PHONY: help all check-zig build c-test cli-smoke py-setup py-install py-test

help:
@echo "Targets:"
@echo " make build - Build CLI + shared lib"
@echo " make c-test - Run C tests"
@echo " make cli-smoke - Parse fixture with CLI"
@echo " make py-setup - Create python/.venv"
@echo " make py-install - Install python dev deps"
@echo " make py-test - Run Python tox tests"
@echo " make all - Run full verification"

check-zig:
@command -v $(ZIG) >/dev/null 2>&1 || (echo "Zig not found. Install with: brew install zig" && exit 1)
@$(ZIG) version

build: check-zig
$(ZIG) build

c-test: check-zig
$(ZIG) build test

cli-smoke: build
mkdir -p $(SMOKE_OUT)
./zig-out/bin/fastfec -x -s $(FIXTURE) $(SMOKE_OUT) 13360
@test -d $(SMOKE_OUT)/13360
@echo "Smoke output files:"
@find $(SMOKE_OUT)/13360 -maxdepth 1 -type f | head -n 10

py-setup:
@test -d $(VENV) || python3 -m venv $(VENV)

py-install: py-setup
source $(VENV)/bin/activate && cd python && pip install -r requirements-dev.txt

py-test: py-install
source $(VENV)/bin/activate && cd python && tox -e py

all: build c-test cli-smoke py-test
Loading
Loading