# Path: hotness/exceptions/patcher_exception.py
# class PatcherException(BaseHotnessException):
#     """
#     Class representing patcher exception.
#     This exception is raised by patcher
#     when it encounters error.
# 
#     Attributes:
#         message: Error message.
#     """
# 
#     def __init__(self, message: str) -> None:
#         """
#         Class constructor.
#         """
#         self.message = message
#         super(PatcherException, self).__init__(self.message)
# 
# Path: hotness/domain/package.py
# class Package:
#     """
#     Internal representation of package object.
# 
#     Attributes:
#         name (str): Name of the package
#         version (str): Latest version of the package
#         distro (str): Distribution assigned
#     """
# 
#     def __init__(self, name: str, version: str, distro: str) -> None:
#         """
#         Class constructor
#         """
#         self.name = name
#         self.version = version
#         self.distro = distro
# 
#     def to_dict(self) -> dict:
#         """
#         Convert object to dictionary.
# 
#         Return:
#             Dictionary created from package object.
#         """
#         return {"name": self.name, "version": self.version, "distro": self.distro}
# 
#     @classmethod
#     def from_dict(cls, package_dict: dict) -> object:
#         """
#         Convert dictionary to object.
# 
#         Params:
#             package_dict: Dictionary to create package from.
# 
#         Return:
#             Package object.
#         """
#         package = Package(
#             name=package_dict["name"],
#             version=package_dict["version"],
#             distro=package_dict["distro"],
#         )
#         return package
# 
#     def __eq__(self, other: object) -> bool:
#         """
#         Compare method for package object.
# 
#         Params:
#             other: object to compare with
# 
#         Return:
#             Compare result.
#         """
#         return self.to_dict() == other.to_dict()  # type: ignore
# 
# Path: hotness/patchers/patcher.py
# class Patcher:
#     """
#     Abstract class for patchers used by the-new-hotness to submit a patch.
#     This class must be inherited by every external patcher.
#     """
# 
#     def submit_patch(self, package: Package, patch: str, opts: dict) -> dict:
#         """
#         Submit patch method that should be implemented by every child class.
# 
#         It should submit patch for package to external system and
#         return dictionary containing additional info.
# 
#         In case of any issue that would prevent submitting the patch, method should
#         raise an exception.
# 
#         Params:
#             package: Package to attach patch for
#             patch: Patch to attach
#             opts: Optional arguments specific for the external patcher system
#         """
#         raise NotImplementedError


import logging
import os
import bugzilla  # type: ignore
from tempfile import TemporaryDirectory
from hotness.exceptions import PatcherException
from hotness.domain.package import Package
from .patcher import Patcher
            raise PatcherException("Authentication info not provided! Provide API key.")
        self.bugzilla.bug_autorefresh = True

    def submit_patch(self, package: Package, patch: str, opts: dict) -> dict:
        """
        This method is inherited from `hotness.patchers.Patcher`.

        It attaches file to existing ticket in bugzilla.

        Params:
            package: Package to create notification for
            patch: Patch to attach, it needs to be converted to file first
            opts: Additional options for bugzilla. Example:
                {
                    "bz_id": 100, # Bugzilla ticket id, if provided the
                                  # new message will be added as new comment to this ticket
                    "patch_filename": "patch" # Name of the file, that should be attached
                }

        Returns:
            Dictionary containing ticket bugzilla id
            Example:
            {
                "bz_id": 100
            }
        """
        output = {}
        bug_id = opts.get("bz_id", 0)
        filename = opts.get("patch_filename", "")
        if bug_id == 0 or not filename:

# Path: hotness/exceptions/patcher_exception.py
# class PatcherException(BaseHotnessException):
#     """
#     Class representing patcher exception.
#     This exception is raised by patcher
#     when it encounters error.
# 
#     Attributes:
#         message: Error message.
#     """
# 
#     def __init__(self, message: str) -> None:
#         """
#         Class constructor.
#         """
#         self.message = message
#         super(PatcherException, self).__init__(self.message)
# 
# Path: hotness/domain/package.py
# class Package:
#     """
#     Internal representation of package object.
# 
#     Attributes:
#         name (str): Name of the package
#         version (str): Latest version of the package
#         distro (str): Distribution assigned
#     """
# 
#     def __init__(self, name: str, version: str, distro: str) -> None:
#         """
#         Class constructor
#         """
#         self.name = name
#         self.version = version
#         self.distro = distro
# 
#     def to_dict(self) -> dict:
#         """
#         Convert object to dictionary.
# 
#         Return:
#             Dictionary created from package object.
#         """
#         return {"name": self.name, "version": self.version, "distro": self.distro}
# 
#     @classmethod
#     def from_dict(cls, package_dict: dict) -> object:
#         """
#         Convert dictionary to object.
# 
#         Params:
#             package_dict: Dictionary to create package from.
# 
#         Return:
#             Package object.
#         """
#         package = Package(
#             name=package_dict["name"],
#             version=package_dict["version"],
#             distro=package_dict["distro"],
#         )
#         return package
# 
#     def __eq__(self, other: object) -> bool:
#         """
#         Compare method for package object.
# 
#         Params:
#             other: object to compare with
# 
#         Return:
#             Compare result.
#         """
#         return self.to_dict() == other.to_dict()  # type: ignore
# 
# Path: hotness/patchers/patcher.py
# class Patcher:
#     """
#     Abstract class for patchers used by the-new-hotness to submit a patch.
#     This class must be inherited by every external patcher.
#     """
# 
#     def submit_patch(self, package: Package, patch: str, opts: dict) -> dict:
#         """
#         Submit patch method that should be implemented by every child class.
# 
#         It should submit patch for package to external system and
#         return dictionary containing additional info.
# 
#         In case of any issue that would prevent submitting the patch, method should
#         raise an exception.
# 
#         Params:
#             package: Package to attach patch for
#             patch: Patch to attach
#             opts: Optional arguments specific for the external patcher system
#         """
#         raise NotImplementedError


# Path: hotness/patchers/bugzilla.py
import logging
import os
import bugzilla  # type: ignore
from tempfile import TemporaryDirectory
from hotness.exceptions import PatcherException
from hotness.domain.package import Package
from .patcher import Patcher

            raise PatcherException("Authentication info not provided! Provide API key.")
        self.bugzilla.bug_autorefresh = True

    def submit_patch(self, package: Package, patch: str, opts: dict) -> dict:
        """
        This method is inherited from `hotness.patchers.Patcher`.

        It attaches file to existing ticket in bugzilla.

        Params:
            package: Package to create notification for
            patch: Patch to attach, it needs to be converted to file first
            opts: Additional options for bugzilla. Example:
                {
                    "bz_id": 100, # Bugzilla ticket id, if provided the
                                  # new message will be added as new comment to this ticket
                    "patch_filename": "patch" # Name of the file, that should be attached
                }

        Returns:
            Dictionary containing ticket bugzilla id
            Example:
            {
                "bz_id": 100
            }
        """
        output = {}
        bug_id = opts.get("bz_id", 0)
        filename = opts.get("patch_filename", "")
        if bug_id == 0 or not filename:

            raise PatcherException(