Skip to content

Meta Editor

NZBMetaEditor

NZBMetaEditor(nzb: str, encoding: str = 'utf-8')

Initialize the NZBMetaEditor instance.

Parameters:

Name Type Description Default
nzb str

NZB content as a string.

required
encoding str

Encoding of the NZB content, defaults to utf-8.

'utf-8'

Raises:

Type Description
InvalidNZBError

Raised if the input is not valid XML. However, being valid XML doesn't guarantee it's a correctly structured NZB.

Source code in src/nzb/_core.py
@validate_call
def __init__(self, nzb: str, encoding: str = "utf-8") -> None:
    """
    Initialize the NZBMetaEditor instance.

    Parameters
    ----------
    nzb : str
        NZB content as a string.
    encoding : str, optional
        Encoding of the NZB content, defaults to `utf-8`.

    Raises
    ------
    InvalidNZBError
        Raised if the input is not valid XML.
        However, being valid XML doesn't guarantee it's a correctly structured NZB.
    """
    self.__nzb = nzb
    self.__encoding = encoding
    try:
        self.__nzbdict = xmltodict_parse(self.__nzb, encoding=self.__encoding)
    except ExpatError as error:
        raise InvalidNZBError(error.args[0])

append

append(*, title: str | None = None, passwords: CollectionOf[str] | str | None = None, tags: CollectionOf[str] | str | None = None, category: str | None = None) -> Self

Append metadata fields to the existing metadata in the NZB.

Parameters:

Name Type Description Default
title str

The title metadata field.

None
passwords CollectionOf[str] | str

Password(s) for the NZB file.

None
tags CollectionOf[str] | str

Tag(s) associated with the NZB file.

None
category str

Category of the NZB file.

None

Returns:

Type Description
Self

Returns itself.

Source code in src/nzb/_core.py
@validate_call
def append(
    self,
    *,
    title: str | None = None,
    passwords: CollectionOf[str] | str | None = None,
    tags: CollectionOf[str] | str | None = None,
    category: str | None = None,
) -> Self:
    """
    Append metadata fields to the existing metadata in the NZB.

    Parameters
    ----------
    title : str, optional
        The title metadata field.
    passwords : CollectionOf[str] | str, optional
        Password(s) for the NZB file.
    tags : CollectionOf[str] | str, optional
        Tag(s) associated with the NZB file.
    category : str, optional
        Category of the NZB file.

    Returns
    -------
    Self
        Returns itself.
    """

    meta = self.__get_meta()

    if meta is None:
        self.set(title=title, passwords=passwords, tags=tags, category=category)

    elif isinstance(meta, dict):
        new_meta = [meta]
        new_meta.extend(construct_meta_fields(title=title, passwords=passwords, tags=tags, category=category))
        self.__nzbdict["nzb"]["head"]["meta"] = new_meta

    else:
        meta.extend(construct_meta_fields(title=title, passwords=passwords, tags=tags, category=category))
        self.__nzbdict["nzb"]["head"]["meta"] = meta

    return self

clear

clear() -> Self

Clear all metadata fields from the NZB.

Returns:

Type Description
Self

Returns itself.

Source code in src/nzb/_core.py
def clear(self) -> Self:
    """
    Clear all metadata fields from the NZB.

    Returns
    -------
    Self
        Returns itself.
    """
    try:
        del self.__nzbdict["nzb"]["head"]
    except KeyError:  # pragma: no cover
        pass

    return self

from_file classmethod

from_file(nzb: StrPath, encoding: str = 'utf-8') -> Self

Create an NZBMetaEditor instance from an NZB file path.

Parameters:

Name Type Description Default
nzb StrPath

File path to the NZB.

required
encoding str

Encoding of the NZB, defaults to utf-8.

'utf-8'

Returns:

Type Description
Self

Returns itself.

Source code in src/nzb/_core.py
@classmethod
@validate_call
def from_file(cls, nzb: StrPath, encoding: str = "utf-8") -> Self:
    """
    Create an NZBMetaEditor instance from an NZB file path.

    Parameters
    ----------
    nzb : StrPath
        File path to the NZB.
    encoding : str, optional
        Encoding of the NZB, defaults to `utf-8`.

    Returns
    -------
    Self
        Returns itself.
    """
    data = Path(nzb).expanduser().resolve().read_text(encoding=encoding)
    instance = cls(data, encoding)
    setattr(instance, "__nzb_file", nzb)
    return instance

remove

remove(key: Literal['title', 'password', 'tag', 'category'] | str) -> Self

Remove a metadata field from the NZB. If the same field is present multiple times, this will remove them all.

Parameters:

Name Type Description Default
key Literal['title', 'password', 'tag', 'category'] | str

The metadata field to remove.

required

Returns:

Type Description
Self

Returns itself.

Source code in src/nzb/_core.py
@validate_call
def remove(self, key: Literal["title", "password", "tag", "category"] | str) -> Self:
    """
    Remove a metadata field from the NZB.
    If the same field is present multiple times, this will remove them all.

    Parameters
    ----------
    key : Literal["title", "password", "tag", "category"] | str, optional
        The metadata field to remove.

    Returns
    -------
    Self
        Returns itself.
    """

    meta = self.__get_meta()

    if meta is None:
        return self

    elif isinstance(meta, dict):
        if key == meta["@type"]:
            return self.clear()
        else:
            return self
    else:
        new_meta = [row for row in meta if row["@type"] != key]
        self.__nzbdict["nzb"]["head"]["meta"] = new_meta
        return self

save

save(filename: StrPath | None = None, overwrite: bool = False) -> Path

Save the edited NZB to a file.

Parameters:

Name Type Description Default
filename StrPath

Destination path for saving the NZB. If not provided, uses the original file path if available. This will also create the path if it doesn't exist already.

None
overwrite bool

Whether to overwrite the file if it exists, defaults to False.

False

Returns:

Type Description
Path

The path to the saved file.

Raises:

Type Description
FileNotFoundError

If no filename is specified and the original file path is unknown.

FileExistsError

If the file exists and overwrite is False.

Source code in src/nzb/_core.py
@validate_call
def save(self, filename: StrPath | None = None, overwrite: bool = False) -> Path:
    """
    Save the edited NZB to a file.

    Parameters
    ----------
    filename : StrPath, optional
        Destination path for saving the NZB.
        If not provided, uses the original file path if available.
        This will also create the path if it doesn't exist already.
    overwrite : bool, optional
        Whether to overwrite the file if it exists, defaults to `False`.

    Returns
    -------
    Path
        The path to the saved file.

    Raises
    ------
    FileNotFoundError
        If no filename is specified and the original file path is unknown.
    FileExistsError
        If the file exists and overwrite is `False`.
    """

    filename_from_self: Path | None = getattr(self, "__nzb_file", None)

    if filename is None:
        if filename_from_self is None:
            raise FileNotFoundError("No filename specified!")
        else:
            if overwrite:
                outfile = filename_from_self
            else:
                raise FileExistsError(filename_from_self)
    else:
        outfile = Path(filename).resolve()

    outfile.parent.mkdir(parents=True, exist_ok=True)
    unparsed = xmltodict_unparse(self.__nzbdict, encoding=self.__encoding, pretty=True, indent="    ")

    if doctype := parse_doctype(self.__nzb):
        # see: https://github.com/martinblech/xmltodict/issues/351
        nzb = unparsed.splitlines(keepends=True)
        nzb.insert(1, f"{doctype}\n")
        with open(outfile, "w", encoding=self.__encoding) as f:
            f.writelines(nzb)
    else:
        outfile.write_text(unparsed, encoding=self.__encoding)

    return outfile

set

set(*, title: str | None = None, passwords: CollectionOf[str] | str | None = None, tags: CollectionOf[str] | str | None = None, category: str | None = None) -> Self

Set metadata fields in the NZB. This will also remove all existing metadata fields.

Parameters:

Name Type Description Default
title str

The title metadata field.

None
passwords CollectionOf[str] | str

Password(s) for the NZB file.

None
tags CollectionOf[str] | str

Tag(s) associated with the NZB file.

None
category str

Category of the NZB file.

None

Returns:

Type Description
Self

Returns itself.

Source code in src/nzb/_core.py
@validate_call
def set(
    self,
    *,
    title: str | None = None,
    passwords: CollectionOf[str] | str | None = None,
    tags: CollectionOf[str] | str | None = None,
    category: str | None = None,
) -> Self:
    """
    Set metadata fields in the NZB.
    This will also remove all existing metadata fields.

    Parameters
    ----------
    title : str, optional
        The title metadata field.
    passwords : CollectionOf[str] | str, optional
        Password(s) for the NZB file.
    tags : CollectionOf[str] | str, optional
        Tag(s) associated with the NZB file.
    category : str, optional
        Category of the NZB file.

    Returns
    -------
    Self
        Returns itself.
    """

    if title is None and passwords is None and tags is None and category is None:
        return self

    nzb = OrderedDict(self.__nzbdict["nzb"])

    nzb["head"] = {}
    nzb["head"]["meta"] = construct_meta_fields(title=title, passwords=passwords, tags=tags, category=category)
    nzb.move_to_end("file")
    self.__nzbdict["nzb"] = nzb
    return self