Python API Reference

This page documents the public Python API for EZPI.

Core Functions

ezpi.add_rfc822(repo, content, domain=None, env=None)[source]

Add an RFC822 message to the repository.

This is the main entry point for adding email messages to a public-inbox repository. The message can be provided as raw bytes or as an email.message.Message object.

The function automatically:

  • Adds Date header if missing

  • Generates Message-Id if missing

  • Fixes charset for non-ASCII content

  • Extracts author info from the From header

Args:

repo: Path to the bare git repository. content: The email message as bytes or a Message object. domain: Optional domain for generating the Message-Id if missing. env: Optional git environment variables for the commit.

Raises:

ValueError: If the message is missing required From or Subject headers. FileNotFoundError: If the repository path is invalid. RuntimeError: If the git commit operation fails.

Example:

# From bytes
ezpi.add_rfc822('/path/to/repo.git', email_bytes)

# From Message object
msg = email.message.EmailMessage()
msg['From'] = 'sender@example.com'
msg['Subject'] = 'Test'
msg.set_content('Hello')
ezpi.add_rfc822('/path/to/repo.git', msg)
Parameters:
Return type:

None

ezpi.add_plaintext(repo, content, subject, authorname, authoremail, domain=None)[source]

Add plaintext content to the repository as an RFC822 message.

This is a convenience wrapper that creates a minimal RFC822 message from plaintext content and adds it to the repository.

Args:

repo: Path to the bare git repository. content: The plaintext message body. subject: The email subject line. authorname: Display name for the From header. authoremail: Email address for the From header. domain: Optional domain for generating the Message-Id.

Raises:

FileNotFoundError: If the repository path is invalid. RuntimeError: If the git commit operation fails.

Example:

ezpi.add_plaintext(
    '/path/to/repo.git',
    content='Hello, world!',
    subject='Greeting',
    authorname='John Doe',
    authoremail='john@example.com',
)
Parameters:
  • repo (str)

  • content (str)

  • subject (str)

  • authorname (str)

  • authoremail (str)

  • domain (str | None)

Return type:

None

v2 Format Functions

ezpi.add_rfc822_v2(v2path, content, domain=None, env=None, auto_epoch='size')[source]

Add an RFC822 message to a public-inbox v2 format repository.

This function manages the v2 inbox structure, creating it if necessary and handling epoch rotation based on the specified mode.

Args:

v2path: Path to the v2 inbox directory. content: The email message as bytes or a Message object. domain: Optional domain for generating the Message-Id if missing. env: Optional git environment variables. auto_epoch: Epoch rotation mode - ‘size’ (default) or ‘annual’.

Raises:

ValueError: If the message is missing required headers. RuntimeError: If any git operation fails or lock cannot be acquired.

Example:

ezpi.add_rfc822_v2('/path/to/inbox', email_bytes)
ezpi.add_rfc822_v2('/path/to/inbox', msg, auto_epoch='annual')
Parameters:
Return type:

None

ezpi.init_v2_inbox(v2path)[source]

Initialize a new public-inbox v2 format inbox.

Creates the v2 directory structure including: - inbox.lock file for global locking - git/ directory for epoch repositories - git/0.git as the first epoch - all.git/ as read-only endpoint with alternates

Args:

v2path: Path where the v2 inbox should be created.

Returns:

Path to the first epoch repository (git/0.git).

Raises:

RuntimeError: If any git operation fails. FileExistsError: If v2path already exists.

Parameters:

v2path (str)

Return type:

str

ezpi.init_epoch(v2path, epoch)[source]

Create a new epoch repository in a v2 inbox.

Creates a bare git repository at v2path/git/{epoch}.git and updates the alternates file in all.git to include the new epoch.

Args:

v2path: Path to the v2 inbox directory. epoch: Epoch number (0-based integer).

Returns:

Path to the newly created epoch repository.

Raises:

RuntimeError: If git init fails.

Parameters:
Return type:

str

ezpi.get_latest_epoch(v2path)[source]

Find the highest numbered epoch in a v2 inbox.

Args:

v2path: Path to the v2 inbox directory.

Returns:

Tuple of (epoch_number, epoch_path).

Raises:

FileNotFoundError: If no epochs exist.

Parameters:

v2path (str)

Return type:

tuple[int, str]

ezpi.get_epoch_size(epoch_path)[source]

Calculate the total size of a git epoch repository.

Sums the size of pack files and loose objects.

Args:

epoch_path: Path to the epoch bare git repository.

Returns:

Total size in bytes.

Parameters:

epoch_path (str)

Return type:

int

ezpi.should_rotate_epoch(epoch_path, mode)[source]

Check if a new epoch should be created.

Args:

epoch_path: Path to the current epoch repository. mode: Rotation mode - ‘size’ or ‘annual’.

Returns:

True if a new epoch should be created.

Parameters:
Return type:

bool

Utility Functions

ezpi.run_hook(repo)[source]

Run the post-commit hook if it exists and is executable.

Args:

repo: Path to the bare git repository.

Parameters:

repo (str)

Return type:

None

ezpi.clean_header(hdrval)[source]

Decode and clean an email header value.

Handles RFC2047 encoded headers (e.g., =?utf-8?q?…?=) and normalizes whitespace. Invalid encodings are handled gracefully with replacement.

Args:

hdrval: The raw header value to decode.

Returns:

The decoded and cleaned header value as a string.

Parameters:

hdrval (str)

Return type:

str

Low-Level Functions

These functions are primarily for internal use but are documented for advanced users.

ezpi.git_write_commit(repo, env, c_msg, body, dest='m')[source]

Create a git commit containing a single file with the given content.

This is a low-level function that creates git objects (blob, tree, commit). Uses pygit2 when available, otherwise falls back to git subprocess commands. The commit is made to refs/heads/master.

Args:

repo: Path to the bare git repository. env: Environment variables for the git commit (GIT_AUTHOR_*, GIT_COMMITTER_*). c_msg: The commit message (typically the email subject). body: The file content to store (typically the serialized email). dest: Filename for the blob in the tree (default: ‘m’).

Raises:

FileNotFoundError: If the repository path is invalid. RuntimeError: If any git operation fails or lock cannot be acquired.

Parameters:
Return type:

None

ezpi.git_run_command(gitdir, args, stdin=None, env=None)[source]

Run a git command and return its output.

Args:

gitdir: Path to the git repository (sets GIT_DIR environment variable). args: List of arguments to pass to git (without ‘git’ itself). stdin: Optional bytes to send to the command’s stdin. env: Optional environment variables to set for the command.

Returns:

A tuple of (return_code, stdout_bytes, stderr_bytes).

Parameters:
Return type:

tuple[int, bytes, bytes]

ezpi.check_valid_repo(repo)[source]

Verify that a path is a valid bare git repository.

Args:

repo: Path to the repository to check.

Raises:

FileNotFoundError: If the path doesn’t exist or isn’t a valid bare git repo.

Parameters:

repo (str)

Return type:

None

Constants

ezpi.DEFAULT_NAME

Default author name used when none is provided: 'EZ PI'

ezpi.DEFAULT_ADDR

Default author email used when none is provided: 'ezpi@localhost'

ezpi.DEFAULT_SUBJ

Default subject used when none is provided: 'EZPI commit'

ezpi.V2_SIZE_THRESHOLD

Size threshold for epoch rotation in bytes (1GB): 1073741824

ezpi.PI_HEAD

Git ref used for commits: 'refs/heads/master'