Skip to content

API Reference

This content is for v0.5.0. Switch to the latest version for up-to-date documentation.

This page is the concise reference for the public Python surface you import. For the mental model behind these types, see Concepts.


import paxman
from paxman.capabilities import (
Country,
Currency,
Date,
Email,
IP,
ISBN,
Money,
Phone,
SIUnit,
URL,
)
from paxman.core.domain import Resolution
from paxman.core.errors import (
PaxmanError,
CapabilityError,
ContractError,
MultipleMentionsError,
RecognitionError,
ValidationError,
)

Paxman has no runtime dependencies. import paxman is side-effect free — nothing runs until you register and call canonicalize().


Registration tells the engine which capabilities exist. It must complete from one thread before the first canonicalize() call; afterwards the registry freezes and reads are safe from any thread.

FunctionSignatureWhat it does
paxman.register_all_shipped()() -> tuple[str, ...]Registers every capability shipped in this release. Idempotent by name. Returns the names newly registered by this call.
paxman.register_capability(cap)(cap: Capability) -> NoneRegisters one capability instance, e.g. Email(). Fails if the name already exists or the registry is frozen.
paxman.register_grammar(name, cls)(capability_name: str, grammar_cls: type[Grammar]) -> NoneRegisters a community grammar (see Extending). Must happen before the first call.
paxman.register_rule(name, cls)(capability_name: str, rule_cls: type[Rule]) -> NoneRegisters a community rule. Must happen before the first call.
# Quick exploration — everything
paxman.register_all_shipped()
# Explicit — only what you depend on
paxman.register_capability(Email())
paxman.register_capability(Date())

The sole entry point.

def canonicalize(text: str, contract: CapabilityContract) -> ExecutionResult
ParameterTypeDescription
textstrRaw input. One presumed mention per call (see Segmentation).
contractCapabilityContractCreated via SomeCapability.create_contract(...). Carries capability_name so no separate name argument is needed.

Returns ExecutionResult — always, for every domain outcome including missing or invalid input. Domain outcomes are statuses, not exceptions.

Raises

ExceptionCause
CapabilityErrorNo capability matches contract.capability_name
ContractErrorMalformed contract (unknown pinned_rules, unknown output_format, unknown semantics, missing required feature)
MultipleMentionsErrorTwo or more non-overlapping mentions resolved to different values — caller must split first
RecognitionErrorGrammar raised or returned a malformed match (rule, original_error)
ValidationErrorRule raised inside matches()/normalize() (rule, original_error)

MISSING / INVALID / AMBIGUOUS do not raise — they are ExecutionResult.status values (see Execution Result and Candidates & Ambiguity).


Batch scan — one ScanContext substrate pass, per-capability Mention records.

def scan(text: str, contracts: Sequence[CapabilityContract]) -> ScanResult
ParameterTypeDescription
textstrInput text to scan (may contain many mentions).
contractsSequence[CapabilityContract]One contract per capability to scan; each carries its suppress_common_words and other flags.

Returns ScanResult — per-capability mentions dict sharing one substrate.

Raises

ExceptionCause
TypeErrortext is not str or contracts is not a Sequence
CapabilityErrorA contract names an unregistered capability

The scan shares one ScanContext (word spans and lazy views) across all contracts, so querying many capabilities costs one substrate build. Suppression (suppress_common_words) is honored per-contract: a Country contract with suppress_common_words=True drops word-bounded hits like to → TO (Tonga) via COMMON_WORDS (67), while the same text scanned with False keeps them. For the honest F1 path on prose, scan() is the preferred successor to MultipleMentionsError on canonicalize() — see docs/user/migration.md and docs/recipes/segmentation.md.

import paxman
from paxman.capabilities.Country import Country
from paxman.core.errors import MultipleMentionsError
paxman.register_all_shipped()
contract = Country.create_contract()
# Prose with embedded values — the new honest path:
try:
result = paxman.canonicalize("Ship to United States please", contract)
except MultipleMentionsError:
# scan() shares one ScanContext substrate across all contracts in the batch
mentions = paxman.scan("Ship to United States please", [contract])
# mentions.mentions["country"] == [
# Mention(span=(5, 7), grammar="alpha2_recognition", notation=...),
# Mention(span=(8, 21), grammar="name_recognition", notation=...),
# ]
for m in mentions.mentions["country"]:
print(m.span, m.grammar, m.notation)

See Segmentation for when to use scan() vs caller-owned split-then-canonicalize.


Contracts — SomeCapability.create_contract()

Section titled “Contracts — SomeCapability.create_contract()”

Every capability exposes a keyword-only factory. Common parameters come first, capability-specific ones after.

contract = Email.create_contract(
# common — every capability
excluded_rules=(), # Sequence[str]
pinned_rules=None, # Sequence[str] | None — when not None, only these run
year=None, # int | None — only rules with publication_year <= year
output_format=None, # str | None — None / "default" / default / offered, else ContractError
extra_grammars=(), # tuple[str, ...] — opt-in community grammars
suppress_common_words=False, # bool — suppress word-bounded short-code hits in COMMON_WORDS (67)
# capability-specific — varies by capability
include_obfuscated=False, # example: Email only
)

The contract is a frozen dataclass — construct it, pass it, inspect it, but do not mutate it. See Contracts for the full common-plus-specific table.

output_format policy (identical for every capability)

Section titled “output_format policy (identical for every capability)”
  • None, "default", and the capability’s DEFAULT_OUTPUT_FORMAT all resolve to the default.
  • Any value in OFFERED_OUTPUT_FORMATS resolves to itself.
  • Anything else raises ContractError immediately. Validation never consults output_format.

Current defaults and offered alternatives:

CapabilityDefault (DEFAULT_OUTPUT_FORMAT)Offered (OFFERED_OUTPUT_FORMATS)
Countryalpha2alpha3, numeric, name
Currencycode(none — single format)
DateISOUS
Emailemail(none)
IPip(none)
ISBNisbn13hyphenated
Moneycode_amountcompact
Phonee164rfc3966, split
SI Unitsymbol(none)
URLurl(none)
BICbicgrouped, bic11
Coordinatesdecimaliso6709, geo_uri, geojson_pair, dms, dm
Elementsymbolname
IBANelectronicpaper
ISSNhyphenatedcompact, urn
Languagebcp47alpha2, alpha3, alpha3-bib, name
MacAddresscolonhyphen, bare, cisco, eui64
ORCIDorciduri, compact
Timezoneiana(none — single format)
UtcOffsetextendedbasic

The set of capabilities — and their offered formats — grows over time. Treat this table as the current release, not a closed list.

Capability-specific flag summary (current release)

Section titled “Capability-specific flag summary (current release)”
CapabilityFlagTypeDefaultPurpose
Emailinclude_obfuscatedboolFalseuser at domain dot com
Emailinclude_localhostboolTrueadmin@localhost
Countryinclude_localizedboolFalseCLDR multilingual names
Countryinclude_historicalboolFalseDeprecated names
Currencydefault_currencystr | NoneNoneResolve shared bare symbol ($) to this alpha-3 code
IPinclude_ipv6boolTrueIPv6
ISBNinclude_isbn10boolTrueLegacy ISBN-10
ISBNinclude_range_validationboolFalseRegistrant-range provenance
Moneydollar_sign_currencystr | NoneNoneResolve bare $ amount to this alpha-3 code
Moneyprecisionstr"strict"strict / truncate / round for over-precision amounts
Phonedefault_countrystr | NoneNoneInterpret national numbers as if in this alpha-2 country
SI Unitallow_split_word_prefixesboolFalsekilo gram → kg
SI Unitallow_multi_solidusboolFalsekg/m/s preserved
Datetwo_digit_base_yearint | NoneNoneBase for 2-digit year expansion
Timezoneinclude_systemvboolFalseValidate SystemV zones (EST5EDT and kin)
commonsuppress_common_wordsboolFalsesuppress word-bounded short-code hits in COMMON_WORDS (67)

Validation: default_currency / dollar_sign_currency must be uppercase alpha-3; default_country must be uppercase alpha-2; precision must be one of the three values — otherwise ContractError at construction time.


@dataclass(frozen=True)
class ExecutionResult:
status: Resolution # MISSING | INVALID | SUCCESS | AMBIGUOUS
canonicalized_value: str | None # str on SUCCESS, None otherwise
candidates: tuple[Candidate, ...] # all validated evidence, deduplicated
contract: CapabilityContract # the contract you passed in
version_stamp: VersionStamp # .paxman_version
span: tuple[int, int] | None # [start, end) of resolved value on SUCCESS, else None
suppressed_count: int = 0 # hits dropped by suppress_common_words (ADR-0009 §16, #122)
suppressed_spans: tuple[tuple[int, int], ...] = () # [start, end) of each suppressed hit
@dataclass(frozen=True)
class Candidate:
value: str
recognition_rule: str # grammar name, e.g. "standard_recognition"
validation_rule: str # rule name, e.g. "Section 3.4.1-addr-spec"
span: tuple[int, int] | None # half-open [start, end) in the input
provenance: tuple[
Provenance, ...
] # one or more authority citations (read-only property)
@dataclass(frozen=True)
class Provenance:
authority: str # "IETF", "ISO", "BIPM", "WHATWG", "CLDR", ...
specification_name: str # "RFC 5322", "ISO 3166-1", ...
kind: str # "specification" / "standard" / ...
reference_url: str
version: str | None
lifecycle: str # "active" / "deprecated" / ...
publication_year: int
@dataclass(frozen=True)
class VersionStamp:
paxman_version: str
recognition_revision: str # kernel recognition revision (default "0")
class Resolution(Enum):
MISSING = "missing"
INVALID = "invalid"
SUCCESS = "success"
AMBIGUOUS = "ambiguous"

Reading the result (see also Execution Result):

from paxman.core.domain import Resolution
if result.status == Resolution.SUCCESS:
value = result.canonicalized_value # str, span is set
else:
# MISSING / INVALID / AMBIGUOUS — no single value, span is None
# inspect result.candidates and their provenance/spans
...

span semantics: on SUCCESS it is the span of the single resolved value; on AMBIGUOUS use each candidate.span; on MISSING/INVALID it is None and candidates is empty.

suppressed_count / suppressed_spans: populated whenever suppress_common_words=True suppression fires, on any status (ADR-0009 §16, A0 #122) — 0/() when the flag is off or nothing was suppressed. Spans are in sorted positional order. A whole-input suppressible hit is never suppressed (A0 exemption), so canonicalize("to", Country suppress on) → SUCCESS "TO" with 0/(), while canonicalize("in/", …) → MISSING with suppressed_count == 1, suppressed_spans == ((0, 2),).


All exceptions inherit from PaxmanError. See Errors for handling patterns.

ExceptionSignal typeTypical cause
CapabilityErrorsetupUnknown capability, duplicate name, registry already frozen
ContractErrorsetupBad pinned_rules, bad output_format, unknown semantics, missing required feature, bad default_currency/default_country/precision
MultipleMentionsErrorusageTwo separate mentions with different values in one call — split first
RecognitionErrorinternal bugGrammar raised or returned a bad span/raw_text. Fields: rule, original_error (None on structural failure)
ValidationErrorinternal bugRule raised inside matches()/normalize(). Fields: rule, original_error

Statuses vs exceptions: statuses are domain answers returned inside ExecutionResult; exceptions mean the call was not valid to attempt. Catch exceptions at setup and at the outer edge of a batch loop; branch on statuses in normal flow.


Quick lookup — choose the right capability

Section titled “Quick lookup — choose the right capability”
Kind of text you haveCapability to useFactory
Email addressesEmailEmail.create_contract(...)
DatesDateDate.create_contract(...)
Country codes or namesCountryCountry.create_contract(...)
Currency codes / symbols / names (no amount)CurrencyCurrency.create_contract(...)
IP addressesIPIP.create_contract(...)
ISBNsISBNISBN.create_contract(...)
Money amounts with currencyMoneyMoney.create_contract(...)
Phone numbersPhonePhone.create_contract(...)
SI unit expressionsSI UnitSIUnit.create_contract(...)
Absolute URLs / IRIsURLURL.create_contract(...)
Business identifier codesBICBIC.create_contract(...)
WGS 84 coordinatesCoordinatesCoordinates.create_contract(...)
Chemical elementsElementElement.create_contract(...)
Bank account numbersIBANIBAN.create_contract(...)
Serial identifiersISSNISSN.create_contract(...)
Language identifiersLanguageLanguage.create_contract(...)
MAC addressesMacAddressMacAddress.create_contract(...)
Researcher identifiersORCIDORCID.create_contract(...)
Time zone identifiersTimezoneTimezone.create_contract(...)
UTC offset valuesUtcOffsetUtcOffset.create_contract(...)

New capabilities appear in minor releases — check paxman.capabilities for the current set. Each per-capability guide under Capabilities details its recognized forms, output formats, contract flags, and provenance.