RedactionPolicy#

class scikitplot.cleanprompt.RedactionPolicy(kinds=None, allow=(), tag_style=TagStyle(prefix='[', suffix=']', separator='-', uppercase_kind=True, style='placeholder', surrogates=None), overlap=OverlapStrategy.LONGEST_WINS, limits=Limits(max_input_chars=1000000, max_spans=100000, max_entries=50000, max_literal_terms=10000, max_literal_length=4096), case_insensitive=False, min_confidence=0.0, preserve_placeholders=True)[source]#

Complete, declarative configuration for a redaction pass.

Parameters:
kindstuple of str, optional

Categories to detect, naming entries of the pattern library. None means “every pattern enabled by default”.

tag_styleTagStyle, optional

Placeholder grammar. Defaults to DEFAULT_TAG_STYLE.

overlapOverlapStrategy, default=OverlapStrategy.LONGEST_WINS

Arbitration rule for overlapping detections.

limitsLimits, optional

Hard bounds. Defaults to DEFAULT_LIMITS.

case_insensitivebool, default=False

Whether two surfaces that differ only in case share one label.

min_confidencefloat, default=0.0

Detections below this confidence are discarded before resolution.

allowtuple of str, default=()

Surfaces that must never be redacted, compared exactly against a detection’s own text. An allowlist is the necessary complement to a denylist: without it the only way to stop a false positive is to disable the whole pattern, which silently removes cover for everything else that pattern would have caught.

preserve_placeholdersbool, default=True

Whether text already matching the placeholder grammar is protected from re-detection, making redaction idempotent.

Raises:
PolicyError

If kinds is empty, contains a non-string or a duplicate, or if min_confidence is outside [0.0, 1.0].

Parameters:

Notes

User notes. case_insensitive=True is the right choice for names that appear in mixed case (“Acme” and “ACME” become one label). Leave it off for identifiers where case is meaningful, such as API keys.

Developer notes. preserve_placeholders is what gives invariant I7. Before detection runs, the engine finds every substring matching the active placeholder grammar and treats those ranges as reserved; detectors may still report spans there, but resolution drops them. Without this, feeding an already-redacted text back through the pipeline lets a detector tag the inside of a placeholder and destroy it — which is the reproduced upstream defect CP-006.

Examples

>>> policy = DEFAULT_POLICY.evolve(case_insensitive=True)
>>> policy.case_insensitive
True
>>> policy is DEFAULT_POLICY
False
>>> len(policy.fingerprint)
16
allow: tuple[str, ...] = ()#
as_dict()[source]#

Return a JSON-safe dictionary of this policy.

Returns:
dict

Field names to JSON-safe values, with kinds sorted so that two policies differing only in the order they were written produce the same rendering.

Return type:

dict[str, Any]

case_insensitive: bool = False#
evolve(**changes)[source]#

Return a copy of this policy with changes applied.

Parameters:
**changes

Field names to new values. kinds accepts any iterable of strings and is normalised to a tuple.

Returns:
RedactionPolicy

A new, validated policy. This policy is unchanged.

Raises:
PolicyError

If a name is not a field of this class, or the result is invalid.

Parameters:

changes (Any)

Return type:

RedactionPolicy

Examples

>>> DEFAULT_POLICY.evolve(kinds=["EMAIL"]).kinds
('EMAIL',)
property fingerprint: str#

Stable 16-character digest of this policy.

Notes

Developer notes. Computed from canonical JSON with sorted keys, so it is identical across processes, platforms and Python versions. hash is unsuitable: PYTHONHASHSEED randomises string hashing per process, so a hash-derived fingerprint would fail to match a vault written by an earlier run.

Type:

str

kinds: tuple[str, ...] | None = None#
limits: Limits = Limits(max_input_chars=1000000, max_spans=100000, max_entries=50000, max_literal_terms=10000, max_literal_length=4096)[source]#
min_confidence: float = 0.0#
overlap: OverlapStrategy = 'LONGEST_WINS'[source]#
preserve_placeholders: bool = True#
selected_kinds(available)[source]#

Resolve kinds against the kinds a registry offers.

Parameters:
availableiterable of str

Kinds the registry can provide.

Returns:
frozenset of str

The kinds to run.

Raises:
PolicyError

If a requested kind is not available. The message lists what is.

Parameters:

available (Iterable[str])

Return type:

frozenset[str]

Notes

Developer notes. Requesting an unknown kind raises rather than being ignored. A silently dropped category is a redaction that did not happen, and the caller would have no way to notice before transmitting.

tag_style: TagStyle = TagStyle(prefix='[', suffix=']', separator='-', uppercase_kind=True, style='placeholder', surrogates=None)[source]#