:py:mod:`hookspec`
==================

.. py:module:: conda.plugins.hookspec

.. autoapi-nested-parse::

   Pluggy hook specifications ("hookspecs") to register conda plugins.

   Each hookspec defined in :class:`~conda.plugins.hookspec.CondaSpecs` contains
   an example of how to use it.



Classes
-------

.. autoapisummary::

   conda.plugins.hookspec.CondaSpecs




Attributes
----------

.. autoapisummary::

   conda.plugins.hookspec.spec_name
   conda.plugins.hookspec._hookspec
   conda.plugins.hookspec.hookimpl


.. py:data:: spec_name
   :value: 'conda'

   Name used for organizing conda hook specifications

.. py:data:: _hookspec

   The conda plugin hook specifications, to be used by developers

.. py:data:: hookimpl

   Decorator used to mark plugin hook implementations

.. py:class:: CondaSpecs


   The conda plugin hookspecs, to be used by developers.

   .. py:method:: conda_solvers() -> collections.abc.Iterable[conda.plugins.types.CondaSolver]

      Register solvers in conda.

      **Example:**

      .. code-block:: python

          import logging

          from conda import plugins
          from conda.core import solve

          log = logging.getLogger(__name__)


          class VerboseSolver(solve.Solver):
              def solve_final_state(self, *args, **kwargs):
                  log.info("My verbose solver!")
                  return super().solve_final_state(*args, **kwargs)


          @plugins.hookimpl
          def conda_solvers():
              yield plugins.CondaSolver(
                  name="verbose-classic",
                  backend=VerboseSolver,
              )

      :return: An iterable of solver entries.


   .. py:method:: conda_subcommands() -> collections.abc.Iterable[conda.plugins.types.CondaSubcommand]

      Register external subcommands in conda.

      **Example:**

      .. code-block:: python

          from conda import plugins


          def example_command(args):
              print("This is an example command!")


          @plugins.hookimpl
          def conda_subcommands():
              yield plugins.CondaSubcommand(
                  name="example",
                  summary="example command",
                  action=example_command,
              )

      :return: An iterable of subcommand entries.


   .. py:method:: conda_virtual_packages() -> collections.abc.Iterable[conda.plugins.types.CondaVirtualPackage]

      Register virtual packages in Conda.

      **Example:**

      .. code-block:: python

          from conda import plugins


          @plugins.hookimpl
          def conda_virtual_packages():
              yield plugins.CondaVirtualPackage(
                  name="my_custom_os",
                  version="1.2.3",
                  build="x86_64",
              )

      :return: An iterable of virtual package entries.


   .. py:method:: conda_pre_commands() -> collections.abc.Iterable[conda.plugins.types.CondaPreCommand]

      Register pre-command functions in conda.

      **Example:**

      .. code-block:: python

         from conda import plugins


         def example_pre_command(command):
             print("pre-command action")


         @plugins.hookimpl
         def conda_pre_commands():
             yield plugins.CondaPreCommand(
                 name="example-pre-command",
                 action=example_pre_command,
                 run_for={"install", "create"},
             )


   .. py:method:: conda_post_commands() -> collections.abc.Iterable[conda.plugins.types.CondaPostCommand]

      Register post-command functions in conda.

      **Example:**

      .. code-block:: python

         from conda import plugins


         def example_post_command(command):
             print("post-command action")


         @plugins.hookimpl
         def conda_post_commands():
             yield plugins.CondaPostCommand(
                 name="example-post-command",
                 action=example_post_command,
                 run_for={"install", "create"},
             )


   .. py:method:: conda_auth_handlers() -> collections.abc.Iterable[conda.plugins.types.CondaAuthHandler]

      Register a conda auth handler derived from the requests API.

      This plugin hook allows attaching requests auth handler subclasses,
      e.g. when authenticating requests against individual channels hosted
      at HTTP/HTTPS services.

      **Example:**

      .. code-block:: python

          import os
          from conda import plugins
          from requests.auth import AuthBase


          class EnvironmentHeaderAuth(AuthBase):
              def __init__(self, *args, **kwargs):
                  self.username = os.environ["EXAMPLE_CONDA_AUTH_USERNAME"]
                  self.password = os.environ["EXAMPLE_CONDA_AUTH_PASSWORD"]

              def __call__(self, request):
                  request.headers["X-Username"] = self.username
                  request.headers["X-Password"] = self.password
                  return request


          @plugins.hookimpl
          def conda_auth_handlers():
              yield plugins.CondaAuthHandler(
                  name="environment-header-auth",
                  handler=EnvironmentHeaderAuth,
              )


   .. py:method:: conda_health_checks() -> collections.abc.Iterable[conda.plugins.types.CondaHealthCheck]

      Register health checks for conda doctor.

      This plugin hook allows you to add more "health checks" to conda doctor
      that you can write to diagnose problems in your conda environment.
      Check out the health checks already shipped with conda for inspiration.

      **Example:**

      .. code-block:: python

          from conda import plugins


          def example_health_check(prefix: str, verbose: bool):
              print("This is an example health check!")


          @plugins.hookimpl
          def conda_health_checks():
              yield plugins.CondaHealthCheck(
                  name="example-health-check",
                  action=example_health_check,
              )


   .. py:method:: conda_pre_solves() -> collections.abc.Iterable[conda.plugins.types.CondaPreSolve]

      Register pre-solve functions in conda that are used in the
      general solver API, before the solver processes the package specs in
      search of a solution.

      **Example:**

      .. code-block:: python

         from conda import plugins
         from conda.models.match_spec import MatchSpec


         def example_pre_solve(
             specs_to_add: frozenset[MatchSpec],
             specs_to_remove: frozenset[MatchSpec],
         ):
             print(f"Adding {len(specs_to_add)} packages")
             print(f"Removing {len(specs_to_remove)} packages")


         @plugins.hookimpl
         def conda_pre_solves():
             yield plugins.CondaPreSolve(
                 name="example-pre-solve",
                 action=example_pre_solve,
             )


   .. py:method:: conda_post_solves() -> collections.abc.Iterable[conda.plugins.types.CondaPostSolve]

      Register post-solve functions in conda that are used in the
      general solver API, after the solver has provided the package
      records to add or remove from the conda environment.

      **Example:**

      .. code-block:: python

         from conda import plugins
         from conda.models.records import PackageRecord


         def example_post_solve(
             repodata_fn: str,
             unlink_precs: tuple[PackageRecord, ...],
             link_precs: tuple[PackageRecord, ...],
         ):
             print(f"Uninstalling {len(unlink_precs)} packages")
             print(f"Installing {len(link_precs)} packages")


         @plugins.hookimpl
         def conda_post_solves():
             yield plugins.CondaPostSolve(
                 name="example-post-solve",
                 action=example_post_solve,
             )


   .. py:method:: conda_settings() -> collections.abc.Iterable[conda.plugins.types.CondaSetting]

      Register new setting

      The example below defines a simple string type parameter

      **Example:**

      .. code-block:: python

         from conda import plugins
         from conda.common.configuration import PrimitiveParameter, SequenceParameter


         @plugins.hookimpl
         def conda_settings():
             yield plugins.CondaSetting(
                 name="example_option",
                 description="This is an example option",
                 parameter=PrimitiveParameter("default_value", element_type=str),
                 aliases=("example_option_alias",),
             )


   .. py:method:: conda_reporter_backends() -> collections.abc.Iterable[conda.plugins.types.CondaReporterBackend]

      Register new reporter backend

      The example below defines a reporter backend that uses the ``pprint`` module in Python.

      **Example:**

      .. code-block:: python

         from pprint import pformat

         from conda import plugins
         from conda.plugins.types import (
             CondaReporterBackend,
             ReporterRendererBase,
             ProgressBarBase,
         )


         class PprintReporterRenderer(ReporterRendererBase):
             "Implementation of the ReporterRendererBase"

             def detail_view(self, data):
                 return pformat(data)

             def envs_list(self, data):
                 formatted_data = pformat(data)
                 return f"Environments: {formatted_data}"

             def progress_bar(self, description, io_context_manager) -> ProgressBarBase:
                 "Returns our custom progress bar implementation"
                 return PprintProgressBar(description, io_context_manager)


         class PprintProgressBar(ProgressBarBase):
             "Blank implementation of ProgressBarBase which does nothing"

             def update_to(self, fraction) -> None:
                 pass

             def refresh(self) -> None:
                 pass

             def close(self) -> None:
                 pass


         @plugins.hookimpl
         def conda_reporter_backends():
             yield CondaReporterBackend(
                 name="pprint",
                 description="Reporter backend based on the pprint module",
                 renderer=PprintReporterRenderer,
             )



   .. py:method:: conda_session_headers(host: str) -> collections.abc.Iterable[conda.plugins.types.CondaRequestHeader]

      Register new HTTP request headers

      The example below defines how to add HTTP headers for all requests
      with the hostname of ``example.com``.

      **Example:**

      .. code-block:: python

         from conda import plugins

         HOSTS = {"example.com", "sub.example.com"}


         @plugins.hookimpl
         def conda_session_headers(host: str):
             if host in HOSTS:
                 yield plugins.CondaRequestHeader(
                     name="Example-Header",
                     value="example",
                 )


   .. py:method:: conda_request_headers(host: str, path: str) -> collections.abc.Iterable[conda.plugins.types.CondaRequestHeader]

      Register new HTTP request headers

      The example below defines how to add HTTP headers for all requests
      with the hostname of ``example.com`` and a ``path/to/endpoint.json`` path.

      **Example:**

      .. code-block:: python

         from conda import plugins

         HOSTS = {"example.com", "sub.example.com"}
         ENDPOINT = "/path/to/endpoint.json"


         @plugins.hookimpl
         def conda_request_headers(host: str, path: str):
             if host in HOSTS and path == ENDPOINT:
                 yield plugins.CondaRequestHeader(
                     name="Example-Header",
                     value="example",
                 )