Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Creation API

btpc.creation

Create v1, v2, and hybrid torrent metainfo from filesystem payloads.

CancellationToken

class CancellationToken()

Request cooperative cancellation of creation or verification.

The same token may be passed to one or more operations. Calling cancel is thread-safe; active operations stop at a core cancellation checkpoint and raise CancelledError.

Examples:

>>> from btpc import CancellationToken
>>> token = CancellationToken()
>>> token.cancel()
>>> token.cancelled
True

cancel

cancel() -> None

Request cancellation.

cancelled

cancelled: bool

Return whether cancellation was requested.

CreateMetrics

class CreateMetrics(scan_ms: float, hash_ms: float, serialize_ms: float)

Record elapsed time for creation phases.

Attributes:

  • scan_ms: Filesystem traversal time in milliseconds.
  • hash_ms: Payload hashing time in milliseconds.
  • serialize_ms: Canonical metainfo serialization time in milliseconds.

scan_ms

scan_ms: float

hash_ms

hash_ms: float

serialize_ms

serialize_ms: float

CreateOptions

class CreateOptions(mode: TorrentMode = TorrentMode.V1, piece_length: int | None = None, threads: int | None = None, trackers: Sequence[Sequence[str]] = (), web_seeds: Sequence[str] = (), nodes: Sequence[tuple[str, int]] = (), private: bool | None = None, source: str | None = None, comment: str | None = None, created_by: str | None = None, omit_created_by: bool = False, creation_date: int | None = None)

Configure deterministic torrent creation.

Tracker tiers, web seeds, and nodes are copied into immutable tuples when options are constructed. Later changes to caller-owned lists have no effect.

Attributes:

  • mode: Protocol representation to create. The default is TorrentMode.V1.
  • piece_length: Explicit piece length in bytes. None selects the core’s deterministic automatic policy; v2 and hybrid values must satisfy BEP 52 constraints.
  • threads: Maximum hashing worker count. None lets the core choose from available parallelism.
  • trackers: Tracker tiers as a sequence of URL-string sequences. Text is encoded as strict UTF-8 at the native boundary.
  • web_seeds: Web seed URLs encoded as strict UTF-8.
  • nodes: DHT bootstrap nodes as (host, port) pairs.
  • private: Optional private flag stored in the info dictionary. Changing it changes the info hash.
  • source: Optional source string stored in the info dictionary. Changing it changes the info hash.
  • comment: Optional top-level comment. Changing it does not change the info hash.
  • created_by: Explicit top-level creator text. When omitted, BTPC writes btpc/<version> unless omit_created_by is true.
  • omit_created_by: Suppress the default creator field. It cannot be combined with an explicit created_by value.
  • creation_date: Unix timestamp stored at the top level. Set a fixed value, commonly 0, for reproducible output.

Examples:

>>> from btpc import CreateOptions, TorrentMode
>>> options = CreateOptions(
...     mode=TorrentMode.HYBRID,
...     piece_length=16_384,
...     creation_date=0,
...     threads=1,
... )
>>> options.mode is TorrentMode.HYBRID
True

mode

mode: TorrentMode

piece_length

piece_length: int | None

threads

threads: int | None

trackers

trackers: Sequence[Sequence[str]]

web_seeds

web_seeds: Sequence[str]

nodes

nodes: Sequence[tuple[str, int]]

private

private: bool | None

source

source: str | None

comment

comment: str | None

created_by

created_by: str | None

omit_created_by

omit_created_by: bool

creation_date

creation_date: int | None

CreateResult

class CreateResult

Expose generated metainfo, hashes, and metrics without eager copies.

metainfo

metainfo: Metainfo

Return cached metainfo for inspection, editing, magnets, or verification.

The generated metainfo is parsed once on first access without copying it through Python bytes or reading the payload again.

Examples:

>>> from pathlib import Path
>>> from tempfile import TemporaryDirectory
>>> from btpc import create_bytes
>>> with TemporaryDirectory() as directory:
...     payload = Path(directory) / "hello.txt"
...     _ = payload.write_bytes(b"hello torrent\n")
...     result = create_bytes(payload)
...     assert result.metainfo.verify(payload).is_valid
...     assert result.metainfo is result.metainfo

bytes

bytes: bytes

Return generated metainfo bytes, copied on first request.

mode

mode: TorrentMode

Return the created protocol mode.

info_hash_v1

info_hash_v1: HashValue | None

Return the cached v1 info hash when applicable.

info_hash_v2

info_hash_v2: HashValue | None

Return the cached v2 info hash when applicable.

file_count

file_count: int

Return payload file count.

payload_bytes

payload_bytes: int

Return total payload bytes.

piece_count

piece_count: int

Return created piece count.

piece_length

piece_length: int

Return selected piece length.

piece_length_policy

piece_length_policy: str | None

Return automatic policy identifier for automatic selection.

metrics

metrics: CreateMetrics

Return cached phase timing metrics.

create

create(path: str | PathLike[str], destination: str | PathLike[str], *, options: CreateOptions | None = None, overwrite: bool = False, durable: bool = False, progress: Callable[[int, int, int], None] | None = None, cancellation: CancellationToken | None = None) -> CreateResult

Create canonical metainfo and atomically write a torrent file.

The destination is written through a temporary file and renamed into place. Existing files are rejected unless overwrite is true. With durable enabled, BTPC also requests file and parent-directory synchronization before returning.

Args:

  • path: Payload file or directory to traverse deterministically.
  • destination: Torrent file to create atomically.
  • options: Creation settings. None uses :class:CreateOptions defaults.
  • overwrite: Replace an existing destination when true.
  • durable: Request durable file and directory synchronization.
  • progress: Optional callback receiving ``(completed_bytes, total_bytes, completed_pieces)`. Callback exceptions propagate unchanged.
  • cancellation: Cooperative cancellation token.

Returns:

  • **The same result data returned by :**func:create_bytes.

Raises:

  • PathError: If payload or destination I/O fails, including a disallowed overwrite.
  • MetainfoError: If options or payload structure violate protocol rules.
  • CancelledError: If cancellation is requested.
  • Exception: Any exception raised by progress.

Examples:

>>> from pathlib import Path
>>> from tempfile import TemporaryDirectory
>>> from btpc import CreateOptions, create
>>> with TemporaryDirectory() as directory:
...     root = Path(directory)
...     payload = root / "hello.txt"
...     destination = root / "hello.torrent"
...     _ = payload.write_bytes(b"hello torrent\n")
...     result = create(
...         payload,
...         destination,
...         options=CreateOptions(creation_date=0, threads=1),
...     )
...     assert destination.read_bytes() == result.bytes

create_bytes

create_bytes(path: str | PathLike[str], *, options: CreateOptions | None = None, progress: Callable[[int, int, int], None] | None = None, cancellation: CancellationToken | None = None) -> CreateResult

Create canonical metainfo without writing a torrent file.

Args:

  • path: Payload file or directory to traverse deterministically.
  • options: Creation settings. None uses :class:CreateOptions defaults.
  • progress: Optional callback receiving ``(completed_bytes, total_bytes, completed_pieces)`. Exceptions raised by the callback propagate to the caller and stop creation.
  • cancellation: Cooperative cancellation token checked during traversal and hashing.

Returns:

The immutable result, including generated bytes, applicable info hashes, selected piece length, and phase metrics.

Raises:

  • PathError: If the payload cannot be traversed or read.
  • MetainfoError: If options or payload structure violate protocol rules.
  • CancelledError: If cancellation is requested.
  • Exception: Any exception raised by progress.

Examples:

>>> from pathlib import Path
>>> from tempfile import TemporaryDirectory
>>> from btpc import CreateOptions, create_bytes
>>> with TemporaryDirectory() as directory:
...     payload = Path(directory) / "hello.txt"
...     _ = payload.write_bytes(b"hello torrent\n")
...     result = create_bytes(
...         payload,
...         options=CreateOptions(creation_date=0, threads=1),
...     )
...     assert result.file_count == 1