Custom Parsers¶
Register a custom parser when an annotation needs domain-specific conversion.
A parser receives one raw CLI string and returns the Python value passed to your command.
from dataclasses import dataclass
from interfacy import Interfacy
@dataclass(frozen=True)
class Port:
value: int
def parse_port(raw: str) -> Port:
port = int(raw)
if not 1 <= port <= 65535:
raise ValueError("port must be between 1 and 65535")
return Port(port)
def serve(port: Port) -> str:
return f"serving on {port.value}"
parser = Interfacy(print_result=True)
parser.add_type_parser(Port, parse_port)
parser.run(serve)
$ python app.py 8080
serving on 8080
Registry access¶
add_type_parser() is the usual API. If you need lower-level control, the active StrToTypeParser registry is available through parser.type_parser.
parser = Interfacy()
parser.add_type_parser(Port, parse_port)
Parser errors¶
Raise ValueError or another clear exception from the parser when input is invalid. Interfacy reports the parsing failure through the active backend.
def parse_percent(raw: str) -> float:
value = float(raw.rstrip("%"))
if not 0 <= value <= 100:
raise ValueError("percent must be between 0 and 100")
return value / 100
Custom parser vs model expansion¶
A registered parser for a class means “parse this value as a scalar.” That takes precedence over model expansion.
With a custom parser, the CLI accepts one scalar value:
$ python app.py 127.0.0.1:8000
With model expansion, the CLI accepts structured flags:
$ python app.py --server.host 127.0.0.1 --server.port 8000