-
Notifications
You must be signed in to change notification settings - Fork 1
Description
A parser will be defined via a class decorated with @parsable. Header fields will be mapped to attributes of the class, with non-trivial mappings defined via field declarations of the form fieldname: Annotation = Field(...).
-
Alternative idea: Replace
Fieldwithtyping.Annotatedà la Pydantic 2.0. -
Fieldconstructs anattr.Attributewith headerparser-specific parameters stored in the attribute metadata under a "headerparser" key -
@parsablecompiles the class's parsing metadata into aParserSpecinstance that is then saved as a class variable, which is then used by the actualparse*()functions. -
@parsablecan be passed the following arguments:name_decoder— what the v1 parser calls the "normalizer"; defaults tolambda s: re.sub(r'[^\w_]', "_", s.lower())scanner_options: dict[str, Any]**kwargs— passed toattr.define
-
Field— For defining nontrivialmultiple=Falsefields- Takes the following arguments:
aliasdecoder— A callable that takes a header name (str) and a value- For fields with aliases, this is passed the actual field name, not the alias, as that's what pydantic does with validators.
**kwargs— passed toattr.field
- Takes the following arguments:
-
MultiField: For definingmultiple=Truefields- Takes the same arguments as
Field, except thatdecoderis passed a header name and a list of values
- Takes the same arguments as
-
ExtraFields: For defining an attribute to store additional fields withmultiple=Falseon- Takes the following arguments:
decoder— a callable that is passed a list of(name, value)pairs with unique names**kwargs— passed toattr.field
- Extra fields are allowed in the parsed input iff this or
MultiExtraFieldsis present - A class cannot have more than one
ExtraFieldsorMultiExtraFields
- Takes the following arguments:
-
MultiExtraFields: For defining an attribute to store additional fields withmultiple=Trueon- Takes the following arguments:
decoder— a callable that is passed a list of(name, value)pairs in which the names need not be unique**kwargs— passed toattr.field
- Takes the following arguments:
-
BodyField: For defining the attribute on which the body will be stored- Takes the following arguments:
decoder— a callable that takes just a value**kwargs— passed toattr.field
- A body is allowed iff such a
BodyFieldis present in the class - A class cannot have more than one
BodyField
- Takes the following arguments:
-
Functions:
parse(klass: Type[L], data: Union[Iterable[str], str, Scanner]) -> Lparse_stanzas(klass: Type[L], data: Union[Iterable[str], str, Scanner]) -> Iterator[L]parse_stream(klass: Type[L], fields: Iterable[Tuple[Optional[str], str]]) -> L- There's no point in trying to merge this and
parse_stanzas_stream()into the non-stream versions, as either way this function or an equivalent will be needed for the others to call
- There's no point in trying to merge this and
parse_stanzas_stream(klass: Type[L], fields: Iterable[Iterable[Tuple[str, str]]]) -> Iterator[L]- There is no
parse_next_stanza(); to get this effect, the user should scan the stanza themselves usingScannerand pass the results toparse_stream()- Or should
parse_next_stanza()exist but only take aScanner?
- Or should
make_parsable(…)— wrapsattr.make_class()is_parsable(Any) -> bool- Something (
get_scanner()?) for taking a parsable and returning aScannerinitialized with its scanner options?- The function would also need to take the data to initialize the Scanner with — unless I give Scanner a
feed()method
- The function would also need to take the data to initialize the Scanner with — unless I give Scanner a
-
There is a
ParserMixin(?) mixin class that implements equivalents of all of theparse*()functions as classmethods that get theklassfromcls -
Supply a premade set of decoders for parsing bools, timestamps, etc.?
-
Supply higher-order functions for converting single-argument functions to
(name, value)decoders, converting(name, value)decoders to(name, [value])decoders, and converting single-argument functions to(name, [value])decoders -
Supply one or more equivalents of attrs'
pipe()et alii? -
Add an option for just discarding all extra/unknown fields?