Skip to main content

argparse for mail-style headers

Project description

Project Status: Active — The project has reached a stable, usable state and is being actively developed. CI Status https://codecov.io/gh/jwodder/headerparser/branch/master/graph/badge.svg https://img.shields.io/pypi/pyversions/headerparser.svg MIT License

GitHub | PyPI | Documentation | Issues | Changelog

headerparser parses key-value pairs in the style of RFC 822 (e-mail) headers and converts them into case-insensitive dictionaries with the trailing message body (if any) attached. Fields can be converted to other types, marked required, or given default values using an API based on the standard library’s argparse module. (Everyone loves argparse, right?) Low-level functions for just scanning header fields (breaking them into sequences of key-value pairs without any further processing) are also included.

The Format

RFC 822-style headers are header fields that follow the general format of e-mail headers as specified by RFC 822 and friends: each field is a line of the form “Name: Value”, with long values continued onto multiple lines (“folded”) by indenting the extra lines. A blank line marks the end of the header section and the beginning of the message body.

This basic grammar has been used by numerous textual formats besides e-mail, including but not limited to:

  • HTTP request & response headers

  • Usenet messages

  • most Python packaging metadata files

  • Debian packaging control files

  • META-INF/MANIFEST.MF files in Java JARs

  • a subset of the YAML serialization format

— all of which this package can parse.

Installation

headerparser requires Python 3.7 or higher. Just use pip for Python 3 (You have pip, right?) to install headerparser:

python3 -m pip install headerparser

Examples

Define a parser:

>>> import headerparser
>>> parser = headerparser.HeaderParser()
>>> parser.add_field('Name', required=True)
>>> parser.add_field('Type', choices=['example', 'demonstration', 'prototype'], default='example')
>>> parser.add_field('Public', type=headerparser.BOOL, default=False)
>>> parser.add_field('Tag', multiple=True)
>>> parser.add_field('Data')

Parse some headers and inspect the results:

>>> msg = parser.parse('''\
... Name: Sample Input
... Public: yes
... tag: doctest, examples,
...   whatever
... TAG: README
...
... Wait, why I am using a body instead of the "Data" field?
... ''')
>>> sorted(msg.keys())
['Name', 'Public', 'Tag', 'Type']
>>> msg['Name']
'Sample Input'
>>> msg['Public']
True
>>> msg['Tag']
['doctest, examples,\n  whatever', 'README']
>>> msg['TYPE']
'example'
>>> msg['Data']
Traceback (most recent call last):
    ...
KeyError: 'data'
>>> msg.body
'Wait, why I am using a body instead of the "Data" field?\n'

Fail to parse headers that don’t meet your requirements:

>>> parser.parse('Type: demonstration')
Traceback (most recent call last):
    ...
headerparser.errors.MissingFieldError: Required header field 'Name' is not present
>>> parser.parse('Name: Bad type\nType: other')
Traceback (most recent call last):
    ...
headerparser.errors.InvalidChoiceError: 'other' is not a valid choice for 'Type'
>>> parser.parse('Name: unknown field\nField: Value')
Traceback (most recent call last):
    ...
headerparser.errors.UnknownFieldError: Unknown header field 'Field'

Allow fields you didn’t even think of:

>>> parser.add_additional()
>>> msg = parser.parse('Name: unknown field\nField: Value')
>>> msg['Field']
'Value'

Just split some headers into names & values and worry about validity later:

>>> for field in headerparser.scan('''\
... Name: Scanner Sample
... Unknown headers: no problem
... Unparsed-Boolean: yes
... CaSe-SeNsItIvE-rEsUlTs: true
... Whitespace around colons:optional
... Whitespace around colons  :  I already said it's optional.
...   That means you have the _option_ to use as much as you want!
...
... And there's a body, too, I guess.
... '''): print(field)
('Name', 'Scanner Sample')
('Unknown headers', 'no problem')
('Unparsed-Boolean', 'yes')
('CaSe-SeNsItIvE-rEsUlTs', 'true')
('Whitespace around colons', 'optional')
('Whitespace around colons', "I already said it's optional.\n  That means you have the _option_ to use as much as you want!")
(None, "And there's a body, too, I guess.\n")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

headerparser-0.5.1.tar.gz (34.3 kB view details)

Uploaded Source

Built Distribution

headerparser-0.5.1-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

Details for the file headerparser-0.5.1.tar.gz.

File metadata

  • Download URL: headerparser-0.5.1.tar.gz
  • Upload date:
  • Size: 34.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.5

File hashes

Hashes for headerparser-0.5.1.tar.gz
Algorithm Hash digest
SHA256 f4ca75b801b4d810cde2a278f5f07c9733e4d88e51085032fd909f5655df3ef3
MD5 80af18cec02e880a42a443c6c148d399
BLAKE2b-256 7868b40bf24e5da6eea11baeb8c718b925c27d5f40e5c17fd71df83c52530d3d

See more details on using hashes here.

File details

Details for the file headerparser-0.5.1-py3-none-any.whl.

File metadata

File hashes

Hashes for headerparser-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9e7b0cc3a7debd2fbd6d613bd561601e3e588496e95c0c6ee65419c2a68838c5
MD5 44568d203ac17ab72cd2a46848963da7
BLAKE2b-256 4b497463cb87839856d41314ac84f4e256e9781611a812688257f031e0f1a6d0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page