Quick start

Install pygarble using Installation before running these examples. Detectors operate on Python strings; decode bytes before calling them. No training or fit() step is needed.

Screen and redact sensitive text

from pygarble.screening import Scanner

scanner = Scanner(max_input_length=100_000)
text = "mail jane@example.com, key AKIAIOSFODNN7EXAMPLE, damn"
report = scanner.scan(text)
assert report.kinds() == ("aws_access_key_id", "email", "profanity")
assert report.flagged
assert scanner.redact("mail jane@example.com").text == "mail [EMAIL]"
assert not scanner.scan("qxzjkwpv bnmqwer zzxqv").flagged

This scanner runs secrets, PII and profanity checks. It does not check gibberish. Findings omit matched text and use Python character offsets with an exclusive end. Reuse the scanner across inputs; scan_batch accepts a sequence and iter_scan processes an iterable lazily.

Native rules need no optional dependencies. See Standalone screening and optional backends to select phone-number, identifier or secret-scanning backends, and Python examples for batches and category configuration.

printf 'mail jane@example.com\n' | python -m pygarble.screening scan
printf 'mail jane@example.com\n' | python -m pygarble.screening redact

scan emits one JSON report per document without source text and exits 1 when a document is flagged. redact prints transformed text and exits 0 on success. Both exit 2 on an error. See Command-line interface for document limits and the distinction from the original line-oriented commands.

Check English gibberish separately

from pygarble.gibberish import EnsembleDetector

detector = EnsembleDetector()
assert detector.predict("Hello world") is False
assert detector.predict("asdfghjkl") is True
assert detector.predict("नमस्ते दुनिया") is True

Hindi being flagged is expected: the default checks target English. A negative result does not establish meaning, correct grammar, or language identity.

Process a batch

from pygarble.gibberish import EnsembleDetector

detector = EnsembleDetector()
texts = ["Hello world", "qxzjkwpv"]
assert detector.predict(texts) == [False, True]
scores = detector.score(texts)
assert scores == detector.predict_proba(texts)
assert all(0.0 <= score <= 1.0 for score in scores)

A list input returns a list in the same order; a string returns a single result. Scores are heuristics, not probabilities. Start with serial execution for short texts and measure before enabling threads.

Choose what to detect

from pygarble.gibberish import EnsembleDetector, GarbleDetector, Strategy

corruption = EnsembleDetector(profile="corruption")
assert corruption.predict("नमस्ते दुनिया") is False
assert corruption.predict("hello\x00world") is True

local = GarbleDetector(Strategy.LOCAL_ANOMALY)
assert local.predict("Please review qxzjkwpvm before delivery.") is True

keyboard = GarbleDetector(
    Strategy.KEYBOARD_ADJACENCY, keyboard_layout="azerty"
)
assert keyboard.predict("azerty") is True

Use english_extended to add local anomalies, repetition, and pattern matching to the default profile. It can flag more valid text. The opt-in english_fusion profile combines word lookup, likelihood ratio and cross parsing with Fisher voting against a synthetic English null. See Choosing strategies for choosing checks and Detection Strategies for the complete settings catalog.

Use the command line

The pygarble console script checks one text per line from files or stdin and exits with status 1 when any line is flagged, so it drops into shell pipelines. See Command-line interface for scores, JSON output and threshold calibration.

$ printf 'hello world\nasdfghjkl\n' | pygarble check
clean        hello world
garbled      asdfghjkl

Inspect a decision

from pygarble.gibberish import EnsembleDetector

result = EnsembleDetector().analyze("hello\x00world")
assert result.garbled is True
assert result.status == "garbled"
for signal in result.signals:
    print(signal.strategy, signal.score, signal.applicable, signal.reason)

empty = EnsembleDetector().analyze("")
assert empty.garbled is False
assert empty.status == "insufficient_evidence"

Required fields need a separate empty-input check. For JSON output and spans, see Python examples. For thresholds, voting, limits, and errors, see API Reference.

Keep an existing combined integration

from pygarble import Scanner

scanner = Scanner()
assert scanner.scan("qxzjkwpv bnmqwer zzxqv").flagged
assert scanner.scan("mail jane@example.com").flagged

Existing imports retain their behavior. This scanner includes gibberish by default. See Combined screening and redaction for its configuration and Upgrading for adopting the new module paths.