Skip to content

Parser

Nzb

Bases: Base

Represents a complete NZB file.

Example:
from nzb import Nzb

text = '''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE nzb PUBLIC "-//newzBin//DTD NZB 1.1//EN" "http://www.newzbin.com/DTD/nzb/nzb-1.1.dtd">
<nzb xmlns="http://www.newzbin.com/DTD/2003/nzb">
    <head>
        <meta type="title">Big Buck Bunny - S01E01.mkv</meta>
        <meta type="password">secret</meta>
        <meta type="tag">HD</meta>
        <meta type="category">TV</meta>
    </head>
    <file poster="John &lt;nzb@nowhere.example&gt;" date="1706440708" subject="[1/1] - &quot;Big Buck Bunny - S01E01.mkv&quot; yEnc (1/2) 1478616">
        <groups>
            <group>alt.binaries.boneless</group>
        </groups>
        <segments>
            <segment bytes="739067" number="1">9cacde4c986547369becbf97003fb2c5-9483514693959@example</segment>
            <segment bytes="739549" number="2">70a3a038ce324e618e2751e063d6a036-7285710986748@example</segment>
        </segments>
    </file>
</nzb>
'''

nzb = Nzb.from_str(text)

print(f"{nzb.file.name} ({nzb.meta.category}) was posted by {nzb.file.poster} on {nzb.file.posted_at}.")
print(f"Number of files: {len(nzb.files)}")
print(f"Total size in bytes: {nzb.size}")

file cached property

file: File

The main content file (episode, movie, etc) in the NZB. This is determined by finding the largest file in the NZB and may not always be accurate.

filenames cached property

filenames: tuple[str, ...]

Tuple of unique file names across all the files in the NZB. May return an empty tuple if it fails to extract the name for every file.

files instance-attribute

files: tuple[File, ...]

File objects representing the files included in the NZB.

groups cached property

groups: tuple[str, ...]

Tuple of unique groups across all the files in the NZB.

meta class-attribute instance-attribute

meta: Meta = Meta()

Optional creator-definable metadata for the contents of the NZB.

par2_files cached property

par2_files: tuple[File, ...]

Tuple of par2 files in the NZB.

par2_percentage cached property

par2_percentage: float

Percentage of the size of all the .par2 files relative to the total size.

par2_size cached property

par2_size: int

Total size of all the .par2 files.

posters cached property

posters: tuple[str, ...]

Tuple of unique posters across all the files in the NZB.

size cached property

size: int

Total size of all the files in the NZB.

from_file classmethod

from_file(nzb: StrPath) -> Nzb

Parse the given file into an Nzb. Handles both regular and gzipped NZB files.

Parameters:

Name Type Description Default
nzb str | PathLike[str]

Path to the NZB file.

required

Returns:

Type Description
Nzb

Object representing the parsed NZB file.

Raises:

Type Description
FileNotFoundError

Raised if the specified file doesn't exist.

InvalidNzbError

Raised if the NZB is invalid.

Source code in src/nzb/_core.py
@classmethod
def from_file(cls, nzb: StrPath, /) -> Nzb:
    """
    Parse the given file into an [`Nzb`][nzb.Nzb].
    Handles both regular and gzipped NZB files.

    Parameters
    ----------
    nzb : str | PathLike[str]
        Path to the NZB file.

    Returns
    -------
    Nzb
        Object representing the parsed NZB file.

    Raises
    ------
    FileNotFoundError
        Raised if the specified file doesn't exist.

    InvalidNzbError
        Raised if the NZB is invalid.

    """
    return cls.from_str(read_nzb_file(nzb))

from_json classmethod

from_json(json: str) -> Nzb

Deserialize the given JSON string into an Nzb.

Parameters:

Name Type Description Default
json str

JSON string representing the NZB.

required

Returns:

Type Description
Nzb

Object representing the parsed NZB file.

Raises:

Type Description
InvalidNzbError

Raised if the NZB is invalid.

Source code in src/nzb/_core.py
@classmethod
def from_json(cls, json: str, /) -> Nzb:
    """
    Deserialize the given JSON string into an [`Nzb`][nzb.Nzb].

    Parameters
    ----------
    json : str
        JSON string representing the NZB.

    Returns
    -------
    Nzb
        Object representing the parsed NZB file.

    Raises
    ------
    InvalidNzbError
        Raised if the NZB is invalid.

    """
    return msgspec.json.decode(json, type=cls)

from_str classmethod

from_str(nzb: str) -> Self

Parse the given string into an Nzb.

Parameters:

Name Type Description Default
nzb str

NZB string.

required

Returns:

Type Description
Nzb

Object representing the parsed NZB file.

Raises:

Type Description
InvalidNzbError

Raised if the NZB is invalid.

Source code in src/nzb/_core.py
@classmethod
def from_str(cls, nzb: str, /) -> Self:
    """
    Parse the given string into an [`Nzb`][nzb.Nzb].

    Parameters
    ----------
    nzb : str
        NZB string.

    Returns
    -------
    Nzb
        Object representing the parsed NZB file.

    Raises
    ------
    InvalidNzbError
        Raised if the NZB is invalid.

    """
    nzbdict = nzb_to_dict(nzb)
    meta = parse_metadata(nzbdict)
    files = parse_files(nzbdict)

    return cls(meta=meta, files=files)

has_extension

has_extension(ext: str) -> bool

Check if any file in the NZB has the specified extension.

This method ensures consistent extension comparison by normalizing the extension (removing any leading dot) and handling case-folding.

Parameters:

Name Type Description Default
ext str

Extension to check for, with or without a leading dot (e.g., .txt or txt).

required

Returns:

Type Description
bool

True if any file in the NZB has the specified extension, False otherwise.

```
Source code in src/nzb/_core.py
def has_extension(self, ext: str, /) -> bool:
    """
    Check if any file in the NZB has the specified extension.

    This method ensures consistent extension comparison
    by normalizing the extension (removing any leading dot)
    and handling case-folding.

    Parameters
    ----------
    ext : str
        Extension to check for, with or without a leading dot (e.g., `.txt` or `txt`).

    Returns
    -------
    bool
        `True` if any file in the NZB has the specified extension, `False` otherwise.
    ```

    """
    return any(f.has_extension(ext) for f in self.files)

has_par2

has_par2() -> bool

Return True if there's at least one .par2 file in the NZB, False otherwise.

Source code in src/nzb/_core.py
def has_par2(self) -> bool:
    """
    Return `True` if there's at least one `.par2` file in the NZB, `False` otherwise.
    """
    return any(file.is_par2() for file in self.files)

has_rar

has_rar() -> bool

Return True if any file in the NZB is a .rar file, False otherwise.

Source code in src/nzb/_core.py
def has_rar(self) -> bool:
    """
    Return `True` if any file in the NZB is a `.rar` file, `False` otherwise.
    """
    return any(file.is_rar() for file in self.files)

is_obfuscated

is_obfuscated() -> bool

Return True if any file in the NZB is obfuscated, False otherwise.

Source code in src/nzb/_core.py
def is_obfuscated(self) -> bool:
    """
    Return `True` if any file in the NZB is obfuscated, `False` otherwise.
    """
    return any(file.is_obfuscated() for file in self.files)

is_rar

is_rar() -> bool

Return True if all files in the NZB are .rar files, False otherwise.

Source code in src/nzb/_core.py
def is_rar(self) -> bool:
    """
    Return `True` if all files in the NZB are `.rar` files, `False` otherwise.
    """
    return all(file.is_rar() for file in self.files)

to_json

to_json(*, pretty: bool = False) -> str

Serialize the Nzb object into a JSON string.

Parameters:

Name Type Description Default
pretty bool

Whether to pretty format the JSON string.

False

Returns:

Type Description
str

JSON string representing the NZB.

Source code in src/nzb/_core.py
def to_json(self, *, pretty: bool = False) -> str:
    """
    Serialize the [`Nzb`][nzb.Nzb] object into a JSON string.

    Parameters
    ----------
    pretty : bool, optional
        Whether to pretty format the JSON string.

    Returns
    -------
    str
        JSON string representing the NZB.

    """
    jsonified = msgspec.json.encode(self).decode()

    if pretty:
        return msgspec.json.format(jsonified)

    return jsonified

Meta

Bases: Base

Optional creator-definable metadata for the contents of the NZB.

category class-attribute instance-attribute

category: str | None = None

Category.

passwords class-attribute instance-attribute

passwords: tuple[str, ...] = ()

Password(s).

tags class-attribute instance-attribute

tags: tuple[str, ...] = ()

Tag(s).

title class-attribute instance-attribute

title: str | None = None

Title.

File

Bases: Base

Represents a complete file, consisting of segments that make up a file.

extension cached property

extension: str | None

Extension of the file without the leading dot extracted from the File.name. May return None if it fails to extract the extension.

groups instance-attribute

groups: tuple[str, ...]

Groups that reference the file.

name cached property

name: str | None

Complete name of the file with it's extension extracted from the subject. May return None if it fails to extract the name.

posted_at instance-attribute

posted_at: datetime

The date and time when the file was posted, in UTC.

poster instance-attribute

poster: str

The poster of the file.

segments instance-attribute

segments: tuple[Segment, ...]

Segments that make up the file.

size cached property

size: int

Size of the file calculated from the sum of segment sizes.

stem cached property

stem: str | None

Base name of the file without it's extension extracted from the File.name. May return None if it fails to extract the stem.

subject instance-attribute

subject: str

The subject of the file.

has_extension

has_extension(ext: str) -> bool

Check if the file has the specified extension.

This method ensures consistent extension comparison by normalizing the extension (removing any leading dot) and handling case-folding.

Parameters:

Name Type Description Default
ext str

Extension to check for, with or without a leading dot (e.g., .txt or txt).

required

Returns:

Type Description
bool

True if the file has the specified extension, False otherwise.

Examples:

>>> file.has_extension('.TXT')  # True for 'file.txt'
True
>>> file.has_extension('txt')   # Also True for 'file.txt'
True
Source code in src/nzb/_models.py
def has_extension(self, ext: str, /) -> bool:
    """
    Check if the file has the specified extension.

    This method ensures consistent extension comparison
    by normalizing the extension (removing any leading dot)
    and handling case-folding.

    Parameters
    ----------
    ext : str
        Extension to check for, with or without a leading dot (e.g., `.txt` or `txt`).

    Returns
    -------
    bool
        `True` if the file has the specified extension, `False` otherwise.

    Examples
    --------
    ```python
    >>> file.has_extension('.TXT')  # True for 'file.txt'
    True
    >>> file.has_extension('txt')   # Also True for 'file.txt'
    True
    ```

    """
    if not self.extension:
        return False
    return self.extension.casefold() == ext.casefold().removeprefix(".")

is_obfuscated

is_obfuscated() -> bool

Return True if the file is obfuscated, False otherwise.

Source code in src/nzb/_models.py
def is_obfuscated(self) -> bool:
    """
    Return `True` if the file is obfuscated, `False` otherwise.
    """
    return stem_is_obfuscated(self.stem)

is_par2

is_par2() -> bool

Return True if the file is a .par2 file, False otherwise.

Source code in src/nzb/_models.py
def is_par2(self) -> bool:
    """
    Return `True` if the file is a `.par2` file, `False` otherwise.
    """
    return name_is_par2(self.name)

is_rar

is_rar() -> bool

Return True if the file is a .rar file, False otherwise.

Source code in src/nzb/_models.py
def is_rar(self) -> bool:
    """
    Return `True` if the file is a `.rar` file, `False` otherwise.
    """
    return name_is_rar(self.name)

Segment

Bases: Base

One part segment of a file.

message_id instance-attribute

message_id: str

Message ID of the segment.

number instance-attribute

number: int

Number of the segment.

size instance-attribute

size: int

Size of the segment.