Skip to main content

choppa

Python port of the Java segment SRX sentence segmenter by Jarek Lipski, shipped with the multi-language segment.srx segmentation rules crafted by the LanguageTool team.

In a nutshell, it splits text into sentences (but it is rule-based, so you can chop anything textual). It is the same segmentation engine and the same rules LanguageTool uses — in pure Python.

  • Identical output. SrxTextIterator is byte-identical to the Java original: verified on ~136,000 segments across seven real-world corpora (Ukrainian news from three sources, three English novels — zero differences) and on 848 test cases ported from LanguageTool's 24 language test suites. See Performance and verification.
  • Fast. An 11 MB corpus segments in ~5 s vs ~30 s for the Java CLI (Apple M1); about 25x faster than choppa 0.9.
  • Streaming. Text can be read incrementally from a file object with a fixed-size buffer, so multi-GB corpora do not need to fit in memory.

Quick Start

pip install choppa-srx

(The import name is choppa; the bare choppa name on PyPI belongs to an unrelated project.)

Command line:

echo "Жоден сучасний електронний прилад не обходиться без мікрочипів. \
Мікрочіп, інакше кажучи, мікросхема - це набір електронних схем." | choppa -l uk_two

Python:

from choppa import SrxDocument, SrxTextIterator

document = SrxDocument(ruleset="choppa/data/srx/languagetool_segment.srx")

text = "This is a sentence. And this is another one. Prof. Smith disagrees."
for sentence in SrxTextIterator(document, "en_two", text):
    print(sentence)

The language key is matched against the SRX language maps. For the bundled LanguageTool rules use <code>_two (paragraphs end at two line breaks) or <code>_one (every line break ends a paragraph): uk_two, en_two, de_one, ...

Streaming a large file:

with open("big_corpus.txt", encoding="utf-8") as reader:
    for sentence in SrxTextIterator(document, "uk_two", reader, buffer_length=1024 * 1024):
        ...

Compatibility with the Java original

The port replicates java.util.regex.Matcher semantics on top of the regex package:

  • find() advancement (zero-width matches advance by one character, adjacent matches are not skipped);
  • exception-rule matching with transparent bounds (pattern.match(text, pos) sees lookbehind context before pos, exactly like Java's useTransparentBounds(true) + lookingAt());
  • Java-only constructs in the rules are translated: \h/\v become \p{H}/\p{V} (added to regex on our request), the (?U) flag (Java's UNICODE_CHARACTER_CLASS) is dropped because Python patterns are Unicode-aware by default, and Java character-class intersections like [\p{L}&&[^rwn]] are compiled in the regex module's V1 mode;
  • rules are compiled without MULTILINE, like in Java, so ^ only matches at the start of the text. If you want ^-anchored rules to fire at every line start (pre-1.0 choppa behavior, arguably nicer for texts with headings), opt in with SrxDocument(pattern_flags=regex.M) — the analog of segment 2.0.4's defaultPatternFlags option.

Two algorithms are provided:

  • SrxTextIterator — the "ultimate" algorithm from the original library and the one LanguageTool uses: finds break-rule matches, then applies merged exception patterns at each candidate break. Supports streaming. Use this one.
  • AccurateSrxTextIterator — the legacy "accurate" algorithm (all rules matched over the whole text, in memory), kept for completeness. It incorporates the 2022 overlapping-exception fix from upstream.

Only the SRX 2.0 format and the SAX reader are implemented (the same parser configuration LanguageTool uses). Schema validation via xmlschema is available with SrxDocument(validate_ruleset=...) or choppa --validate.

Performance and verification

Segmentation output was compared byte-for-byte against the Java original (segment-2.0.3, ultimate algorithm, the bundled LanguageTool segment.srx, identical results under JDK 17 and JDK 24) on real-world corpora. choppa = SrxTextIterator, Apple M1, Python 3.12, regex 2026.6.28. Java times include ~1 s of JVM startup and rule parsing, so the engine gap on large inputs is what matters:

corpus language size segments Java choppa output
Militarny news, 100k paragraphs uk_two 11.3 MB 43,569 29.6 s 4.6 s identical
uanews.dp.ua, 5k articles uk_two 12.5 MB 64,063 21.3 s 9.0 s identical
Liga.net news, 197 articles uk_two 0.4 MB 2,647 1.1 s 0.2 s identical
Pride and Prejudice (Gutenberg) en_two 0.8 MB 6,720 1.0 s 0.7 s identical
Moby-Dick (Gutenberg) en_two 1.3 MB 10,188 1.1 s 1.0 s identical
Sherlock Holmes (Gutenberg) en_two 0.6 MB 6,875 0.8 s 1.2 s identical

In total: ~136,000 segments, zero differences.

To reproduce with your own corpus (LF line endings — Java does not normalize CRLF, so make both sides read the same bytes):

# Java ground truth (CLI zip from github.com/loomchild/segment/releases)
segment-2.0.3/bin/segment -a ultimate -s choppa/data/srx/languagetool_segment.srx \
    -l uk_two -r -i corpus.txt -o java.txt -e $'\x01'

# choppa: benchmark + byte-level diff
python scripts/benchmark.py corpus.txt --language uk_two --java java.txt

Segmentation rules

choppa/data/srx/languagetool_segment.srx is an unmodified LanguageTool segment.srx snapshot — see choppa/data/srx/PROVENANCE.md for the exact upstream commit and refresh instructions. You can also pass any SRX 2.0 file of your own via SrxDocument(ruleset=...) or choppa --srx.

Documentation

  • API contract — public API, parameters, streaming semantics, error behavior, stability guarantees
  • Design decisions — how Java Matcher semantics map onto Python, the rule translator, ^/MULTILINE, finitization, the two algorithms, and the testing philosophy
  • Project heritage — SRX, segment, LanguageTool, and the 2022–2026 story of this port
  • Performance and verification — the benchmark table above, with reproduction steps

Development

git clone https://github.com/lang-uk/choppa && cd choppa
pip install -e .[test]
pytest tests/            # includes 848 LanguageTool cases for 24 languages

scripts/benchmark.py benchmarks segmentation and byte-diffs the output against the Java segment CLI; scripts/extract_lt_tests.py regenerates the LanguageTool test fixtures from a LanguageTool checkout.

Copyrights and kudos

  • Python port: Dmytro Chaplynskyi, lang-uk project
  • Original Java implementation and the pure-Python matcher approach: Jarek Lipski
  • CLI and packaging contributions: Volodymyr Kyrylov
  • Segmentation rules: Daniel Naber, Jaume Ortolà, Andriy Rysin et al — the LanguageTool team
  • Special thanks to Andriy Rysin, the driving force behind the Ukrainian language in LanguageTool, and to Matthew Barnett for adding \p{H}/\p{V} to the regex package

The port is MIT-licensed, same as the original segment library. The bundled segment.srx is distributed under LanguageTool's LGPL-2.1.

Metadata

Release files for choppa-srx 1.0.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 choppa-srx 1.0.0
File Size Uploaded
choppa_srx-1.0.0.tar.gz 102.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for choppa-srx 1.0.0
File Interpreter ABI Platform
choppa_srx-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 164.6 kB

Release files / choppa_srx-1.0.0.tar.gz

Download URL choppa_srx-1.0.0.tar.gz
Size 102.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d4f01e95cb8fdf6d1c2ca65ed53bbdad570851ff10d7b38eb3947b6ab2968b2b
BLAKE2b-256 checksum
How to use checksums
07ae80ab29d4ee74ccb3aa783d0b73b858d0525ca3d5e49afaa0e3a6f527f083
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Jul 4, 2026.

Transparency log

Release files / choppa_srx-1.0.0-py3-none-any.whl

Download URL choppa_srx-1.0.0-py3-none-any.whl
Size 62.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f4d5071ed726b0fdee51600a13d5ca33d40bf21cf4afb37be169274b0b7d2ea4
BLAKE2b-256 checksum
How to use checksums
c28252fab4795a66261721651bf8ef4593653a259dc739391d60bf7f581b431f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Jul 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 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