Skip to main content
Thanks for your interest in contributing! Whether you’re fixing a typo, adding a new format adapter, improving error messages, or writing tests — every contribution helps make annotation conversion less painful for everyone.

Getting Started

1

Clone the repository

git clone https://github.com/strickvl/panlabel.git
cd panlabel
2

Build the project

cargo build
3

Run the tests

cargo test
If all tests pass, you’re ready to go!

Codebase Structure

Understanding where to make changes:
What you’re changingWhere to look
CLI behavior, command args, auto-detectionsrc/lib.rs
COCO format adaptersrc/ir/io_coco_json.rs
CVAT format adaptersrc/ir/io_cvat_xml.rs
Label Studio format adaptersrc/ir/io_label_studio_json.rs
TFOD format adaptersrc/ir/io_tfod_csv.rs
YOLO format adaptersrc/ir/io_yolo.rs
Pascal VOC format adaptersrc/ir/io_voc_xml.rs
Lossiness and conversion policysrc/conversion/mod.rs
Stable conversion issue codessrc/conversion/report.rs
CLI integration teststests/cli.rs
Format roundtrip teststests/*_roundtrip.rs

Module Organization

  • src/lib.rs: Library entry point with CLI command dispatch
  • src/main.rs: Thin CLI wrapper that calls into the library
  • src/ir/: Intermediate Representation module (model, bbox, converters)
  • src/conversion/: Conversion lossiness analysis and stable report issue codes
  • src/inspect/: Dataset inspection/statistics logic
  • src/validation/: Dataset validation logic
  • tests/: Integration and property-based tests
  • docs/: User and contributor documentation
  • benches/: Criterion benchmarks
  • fuzz/: Cargo-fuzz targets for parser fuzzing
  • scripts/: Utility scripts (dataset generator)

Testing Approach

Panlabel uses three types of tests:

1. Unit Tests

Located within source files using #[cfg(test)]:
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bbox_validation() {
        // Test implementation
    }
}
Run with:
cargo test

2. Integration Tests

Located in tests/ directory, testing CLI behavior and format roundtrips:
# All integration tests
cargo test --test cli

# Format-specific roundtrip tests
cargo test --test proptest_coco
cargo test --test proptest_yolo
cargo test --test proptest_voc
cargo test --test proptest_label_studio
cargo test --test proptest_cvat
cargo test --test proptest_tfod
cargo test --test proptest_cross_format

3. Property-Based Tests

Using proptest for roundtrip and idempotency checks:
# Run with default case count (256)
cargo test --test proptest_ir_json

# Deeper exploration with more cases
PROPTEST_CASES=1000 cargo test --test proptest_ir_json
Always add tests for new behavior. If it’s not tested, it can silently break.

Fuzzing

Panlabel includes fuzz targets for all parsers. Fuzzing requires nightly Rust and cargo-fuzz:
# Install cargo-fuzz
cargo install cargo-fuzz

# Run fuzz targets
cargo +nightly fuzz run coco_json_parse
cargo +nightly fuzz run voc_xml_parse
cargo +nightly fuzz run cvat_xml_parse
cargo +nightly fuzz run tfod_csv_parse
cargo +nightly fuzz run label_studio_json_parse
cargo +nightly fuzz run ir_json_parse
cargo +nightly fuzz run yolo_label_line_parse
Seed corpora are tracked under fuzz/corpus/<target>/.
The fuzz/Cargo.toml enables panlabel’s fuzzing feature so parser entrypoints are available to fuzz targets.

Benchmarks

Performance benchmarks use Criterion:
# Run all benchmarks
cargo bench

# Smoke test (quick validation)
cargo bench -- --test

Generating Synthetic Test Data

For testing with larger datasets, use the included generator:
# Install dependencies
pip install numpy
# or: uv pip install numpy

# Generate a dataset
python scripts/dataset_generator.py \
  --num_images 1000 \
  --annotations_per_image 10 \
  --output_dir ./assets
The generator creates realistic COCO and TFOD datasets with deterministic seeding (seed 42) for reproducibility.

Adding a New Format

1

Create the format adapter

Add a new file in src/ir/ following the naming convention io_<format>_<extension>.rs:
// src/ir/io_myformat_json.rs
use crate::ir::Dataset;
use anyhow::Result;

pub fn read_myformat(path: &Path) -> Result<Dataset> {
    // Implementation
}

pub fn write_myformat(dataset: &Dataset, path: &Path) -> Result<()> {
    // Implementation
}
2

Add conversion analysis

Update src/conversion/mod.rs to analyze lossiness for your format:
fn analyze_to_myformat(dataset: &Dataset, report: &mut ConversionReport) {
    // Check what information is lost
    // Add warnings for data that will be dropped
}
3

Add format to CLI

Update src/lib.rs to register the new format in the CLI.
4

Write tests

Create roundtrip tests in tests/:
// tests/myformat_roundtrip.rs
#[test]
fn myformat_roundtrip() {
    // Test implementation
}
5

Update documentation

Add format documentation to:
  • docs/formats.md (format specification)
  • docs/conversion.md (lossiness information)
  • README.md (format table)

Contribution Workflow

1

Fork and create a branch

git checkout -b feature/my-new-feature
2

Make your changes

Follow the coding style and run formatters:
cargo fmt
cargo clippy
3

Add tests

Ensure your changes are covered by tests:
cargo test
4

Update documentation

If your change affects user-visible behavior, update the relevant docs:
Behavior changeUpdate
CLI flags or commandsdocs/cli.md and README.md examples
Format read/write behaviordocs/formats.md
Task or use-case supportdocs/tasks.md
Lossiness, report schema, or issue codesdocs/conversion.md
5

Commit and push

git add .
git commit -m "Add feature: brief description"
git push origin feature/my-new-feature
Commit messages in this repo are short and imperative (e.g., “Add basic CLI test”, “Update README”). Avoid prefixes unless needed.
6

Open a pull request

PRs should include:
  • Clear description of changes
  • Test commands run
  • Any user-facing changes noted
  • Link to related issue (for larger changes)

What Contributions Are Welcome?

Here are some areas where help is especially welcome:

New Format Adapters

Support for additional annotation formats like:
  • Labelbox
  • Supervisely
  • VGG Image Annotator (VIA)
  • Custom enterprise formats

Better Error Messages

If a Panlabel error confused you, that’s a bug worth fixing. Clear, actionable error messages help everyone.

Test Coverage

Especially:
  • Edge cases in existing formats
  • Roundtrip tests for complex scenarios
  • Property-based tests for invariants

Documentation Improvements

  • Clearer explanations
  • Better examples
  • Typo fixes
  • Use case tutorials
For larger changes (new formats, IR schema changes), please open an issue first so we can discuss the approach before you invest time writing code.

Coding Style & Conventions

  • Follow rustfmt defaults (4-space indentation, standard Rust formatting)
  • Run cargo fmt and cargo clippy before opening a PR
  • Naming conventions:
    • snake_case for functions/modules/tests
    • CamelCase for types
    • SCREAMING_SNAKE_CASE for constants
  • Keep CLI glue in src/main.rs; put core behavior in src/lib.rs or its modules

Development Commands

# Build debug version
cargo build

# Build optimized release version
cargo build --release

# Run the CLI
cargo run

# Run with arguments
cargo run -- convert -f coco -t yolo -i input.json -o output/

# Fast type checking
cargo check

# Format code
cargo fmt

# Lint
cargo clippy

# All tests (unit + integration + proptests)
cargo test

# CLI integration tests only
cargo test --test cli

# Run a single test by name
cargo test test_name

# Build and view docs
cargo doc --open

Guidelines

  • Don’t claim unsupported capabilities: Current scope is detection bounding boxes only (not segmentation, pose/keypoints, OBB, or classification-only)
  • Prefer small, concrete examples that match tested behavior
  • Write tests for new behavior — if it’s not tested, it can silently break
  • Keep generated assets out of git; only commit code and fixtures meant to be versioned
  • Never add anything under design/ to git history (it is gitignored for a reason)

Getting Help

Need help with your contribution?
  • Check existing issues and PRs for similar work
  • Open an issue to discuss your idea
  • Review the existing code for patterns and conventions
  • Read through the test suite for examples
We appreciate all contributions, no matter how small! 🙏