
    siU`                    2   S r SSKJr  SSKJr  SSKrSSKJr  SSKJ	r	  \(       a.  SSK
Jr  S	S
KJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJr  \	R>                  " SSS\SS9  \R@                  " \5      r! \RD                  " \5      r#  " S S5      r$g)z
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.

    )annotations)TYPE_CHECKINGN   )APP_NAME)
deprecated)Iterable   )CondaAuthHandlerCondaEnvironmentExporterCondaEnvironmentSpecifierCondaHealthCheckCondaPackageExtractorCondaPostCommandCondaPostSolveCondaPostTransactionActionCondaPreCommandCondaPrefixDataLoaderCondaPreSolveCondaPreTransactionActionCondaReporterBackendCondaRequestHeaderCondaSettingCondaSolverCondaSubcommandCondaVirtualPackagez26.3z26.9	spec_namez,Use `conda.base.constants.APP_NAME` instead.)addendumc                     \ rS rSrSr\SS j5       r\SS j5       r\SS j5       r\SS j5       r	\SS j5       r
\SS j5       r\SS	 j5       r\SS
 j5       r\S S j5       r\S!S j5       r\S"S j5       r\S#S j5       r\S$S j5       r\S%S j5       r\      S&S j5       r\S'S j5       r\S(S j5       r\S)S j5       r\S*S j5       rSrg)+
CondaSpecs;   z3Collection of all supported conda plugin hookspecs.c              #  $   #    S Sh  vN   g N7f)aY  
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.types.CondaSolver(
            name="verbose-classic",
            backend=VerboseSolver,
        )

:return: An iterable of solver entries.
 Nr"   selfs    6lib/python3.13/site-packages/conda/plugins/hookspec.pyconda_solversCondaSpecs.conda_solvers>   s     @    c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaSubcommand(
            name="example",
            summary="example command",
            action=example_command,
        )

:return: An iterable of subcommand entries.
r"   Nr"   r#   s    r%   conda_subcommandsCondaSpecs.conda_subcommands`   s     4 r(   c              #  $   #    S Sh  vN   g N7f)ak  
Register virtual packages in Conda.

**Example:**

.. code-block:: python

    from conda import plugins


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

:return: An iterable of virtual package entries.
r"   Nr"   r#   s    r%   conda_virtual_packages!CondaSpecs.conda_virtual_packages|   s     , r(   c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaPreCommand(
           name="example-pre-command",
           action=example_pre_command,
           run_for={"install", "create"},
       )
r"   Nr"   r#   s    r%   conda_pre_commandsCondaSpecs.conda_pre_commands        0 r(   c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaPostCommand(
           name="example-post-command",
           action=example_post_command,
           run_for={"install", "create"},
       )
r"   Nr"   r#   s    r%   conda_post_commandsCondaSpecs.conda_post_commands   r2   r(   c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaAuthHandler(
            name="environment-header-auth",
            handler=EnvironmentHeaderAuth,
        )
r"   Nr"   r#   s    r%   conda_auth_handlersCondaSpecs.conda_auth_handlers   s     H r(   c              #  $   #    S Sh  vN   g N7f)a  
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.

Health checks can optionally provide a ``fixer`` callable that is invoked
via ``conda doctor --fix`` or ``conda doctor --fix <check-name>``.

**Example (check only):**

.. 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.types.CondaHealthCheck(
            name="example-health-check",
            action=example_health_check,
        )

**Example (check with fix):**

.. code-block:: python

    from conda import plugins


    def my_health_check(prefix: str, verbose: bool):
        # Check and report issues
        print("Checking for issues...")


    def my_health_fix(prefix: str, args) -> int:
        # Fix the issues
        print("Fixing issues...")
        return 0  # exit code


    @plugins.hookimpl
    def conda_health_checks():
        yield plugins.CondaHealthCheck(
            name="my-check",
            action=my_health_check,
            fixer=my_health_fix,
            summary="Check for common issues",
            fix="Repair detected issues",
        )

:return: An iterable of health check entries.
r"   Nr"   r#   s    r%   conda_health_checksCondaSpecs.conda_health_checks        x r(   c              #  $   #    S Sh  vN   g N7f)a6  Register pre-transaction hooks.

Pre-transaction hooks run before all other actions run in a
UnlinkLinkTransaction. For information about the Action class,
see :class:`~conda.core.path_actions.Action`.

**Example:**

.. code-block:: python

    from conda import plugins
    from conda.plugins.types import CondaPreTransactionAction
    from conda.core.path_actions import Action


    class PrintAction(Action):
        def verify(self):
            print("Performing verification...")
            self._verified = True

        def execute(self):
            print(
                self.transaction_context,
                self.target_prefix,
                self.unlink_precs,
                self.link_precs,
                self.remove_specs,
                self.update_specs,
                self.neutered_specs,
            )

        def reverse(self):
            print("Reversing only happens when `execute` raises an exception.")

        def cleanup(self):
            print("Carrying out cleanup...")


    class PrintActionPlugin:
        @plugins.hookimpl
        def conda_pre_transaction_actions(
            self,
        ) -> Iterable[CondaPreTransactionAction]:
            yield CondaPreTransactionAction(
                name="example-pre-transaction-action",
                action=PrintAction,
            )
r"   Nr"   r#   s    r%   conda_pre_transaction_actions(CondaSpecs.conda_pre_transaction_actions,       d r(   c              #  $   #    S Sh  vN   g N7f)a<  Register post-transaction hooks.

Post-transaction hooks run after all other actions run in a
UnlinkLinkTransaction. For information about the Action class,
see :class:`~conda.core.path_actions.Action`.

**Example:**

.. code-block:: python

    from conda import plugins
    from conda.plugins.types import CondaPostTransactionAction
    from conda.core.path_actions import Action


    class PrintAction(Action):
        def verify(self):
            print("Performing verification...")
            self._verified = True

        def execute(self):
            print(
                self.transaction_context,
                self.target_prefix,
                self.unlink_precs,
                self.link_precs,
                self.remove_specs,
                self.update_specs,
                self.neutered_specs,
            )

        def reverse(self):
            print("Reversing only happens when `execute` raises an exception.")

        def cleanup(self):
            print("Carrying out cleanup...")


    class PrintActionPlugin:
        @plugins.hookimpl
        def conda_post_transaction_actions(
            self,
        ) -> Iterable[CondaPostTransactionAction]:
            yield CondaPostTransactionAction(
                name="example-post-transaction-action",
                action=PrintAction,
            )
r"   Nr"   r#   s    r%   conda_post_transaction_actions)CondaSpecs.conda_post_transaction_actions`  r@   r(   c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaPreSolve(
           name="example-pre-solve",
           action=example_pre_solve,
       )
r"   Nr"   r#   s    r%   conda_pre_solvesCondaSpecs.conda_pre_solves  s     < r(   c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaPostSolve(
           name="example-post-solve",
           action=example_post_solve,
       )
r"   Nr"   r#   s    r%   conda_post_solvesCondaSpecs.conda_post_solves  s     > r(   c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaSetting(
           name="example_option",
           description="This is an example option",
           parameter=PrimitiveParameter("default_value", element_type=str),
           aliases=("example_option_alias",),
       )
r"   Nr"   r#   s    r%   conda_settingsCondaSpecs.conda_settings  r2   r(   c              #  $   #    S Sh  vN   g N7f)ag  
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,
       )

r"   Nr"   r#   s    r%   conda_reporter_backends"CondaSpecs.conda_reporter_backends  s     t r(   c              #  $   #    S Sh  vN   g N7f)a  
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.types.CondaRequestHeader(
               name="Example-Header",
               value="example",
           )
r"   Nr"   )r$   hosts     r%   conda_session_headers CondaSpecs.conda_session_headers+  s     2 r(   c              #  $   #    S Sh  vN   g N7f)aK  
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.types.CondaRequestHeader(
               name="Example-Header",
               value="example",
           )
r"   Nr"   )r$   rQ   paths      r%   conda_request_headers CondaSpecs.conda_request_headersF  s     8 r(   c               #  $   #    S Sh  vN   g N7f)aj  
Register new loaders for PrefixData

The example below defines how to expose the packages installed
by a hypothetical 'penguin' tool as conda packages.

**Example:**

.. code-block:: python

    from pathlib import Path

    from conda import plugins
    from conda.common.path import PathType
    from conda.models.records import PrefixRecord
    from conda.plugins.types import CondaPrefixDataLoader


    @plugins.hookimpl
    def conda_prefix_data_loaders():
        yield CondaPrefixDataLoader(
            "hypothetical",
            load_hypothetical_packages,
        )


    def load_hypothetical_packages(
        prefix: PathType, records: dict[str, PrefixRecord]
    ) -> dict[str, PrefixRecord]:
        penguin_records = {}
        for info in Path(prefix).glob("lib/penguin/*.penguin-info"):
            name, version = info.name.rsplit("-", 1)
            kwargs = {}  # retrieve extra fields here
            penguin_records[name] = PrefixRecord(
                name=name, version=version, build_number=0, build="0", **kwargs
            )
        records.update(penguin_records)
        return penguin_records
r"   Nr"   r"       r%   conda_prefix_data_loaders$CondaSpecs.conda_prefix_data_loadersd  s     R r(   c              #  $   #    S Sh  vN   g N7f)a  
**EXPERIMENTAL**
Register new conda env spec type

The example below defines a type of conda env file called "random". It
can parse a file with the file extension `.random`. This plugin will ignore
whatever is in the input environment file and produce an environment with a
random name and with random packages.

**Example:**

.. code-block:: python

    import json
    import random
    from pathlib import Path
    from subprocess import run
    from conda import plugins
    from ...plugins.types import EnvironmentSpecBase
    from conda.env.env import Environment

    packages = ["python", "numpy", "scipy", "matplotlib", "pandas", "scikit-learn"]


    class RandomSpec(EnvironmentSpecBase):
        extensions = {".random"}

        def __init__(self, filename: str):
            self.filename = filename

        def can_handle(self):
            # Return early if no filename was provided
            if self.filename is None:
                return False

            # Extract the file extension (e.g., '.txt' or '' if no extension)
            file_ext = os.path.splitext(self.filename)[1]

            # Check if the file has a supported extension and exists
            return any(
                spec_ext == file_ext and os.path.exists(self.filename)
                for spec_ext in RandomSpec.extensions
            )

        def env(self):
            return Environment(
                name="".join(random.choice("0123456789abcdef") for i in range(6)),
                dependencies=[random.choice(packages) for i in range(6)],
            )


    @plugins.hookimpl
    def conda_environment_specifiers():
        yield plugins.CondaEnvSpec(
            name="random",
            environment_spec=RandomSpec,
        )
r"   Nr"   r#   s    r%   conda_environment_specifiers'CondaSpecs.conda_environment_specifiers  r<   r(   c              #  $   #    S Sh  vN   g N7f)a  
Register new conda environment exporter

Environment exporters serialize conda Environment objects to different
output formats (JSON, TOML, XML, etc.) for the 'conda export' command.
This is separate from environment specifiers which parse input files.

**Example:**

.. code-block:: python

    import tomlkit
    from conda import plugins
    from conda.exceptions import CondaValueError
    from conda.models.environment import Environment
    from conda.plugins.types import CondaEnvironmentExporter


    def export_toml(env: Environment) -> str:
        # Export Environment to TOML format
        # For formats that use the standard dictionary structure,
        # you can use the shared utility:
        from conda.plugins.environment_exporters.standard import to_dict

        env_dict = to_dict(env)

        # Create TOML document
        toml_doc = tomlkit.document()

        if env_dict.get("name"):
            toml_doc["name"] = env_dict["name"]

        if env_dict.get("channels"):
            toml_doc["channels"] = env_dict["channels"]

        if env_dict.get("dependencies"):
            toml_doc["dependencies"] = env_dict["dependencies"]

        if env_dict.get("variables"):
            toml_doc["variables"] = env_dict["variables"]

        return tomlkit.dumps(toml_doc)


    @plugins.hookimpl
    def conda_environment_exporters():
        yield CondaEnvironmentExporter(
            name="environment-toml",
            aliases=("toml",),
            default_filenames=("environment.toml",),
            export=export_toml,
        )
r"   Nr"   r#   s    r%   conda_environment_exporters&CondaSpecs.conda_environment_exporters  s     n r(   c              #  $   #    S Sh  vN   g N7f)a  
Register package extractors for different archive formats.

Package extractors handle the unpacking of package archives. Each extractor
specifies which file extensions it supports (e.g., ``.conda``, ``.tar.bz2``)
and provides an extraction function that takes the source archive path and
destination directory.

**Example:**

.. code-block:: python

    from conda import plugins
    from conda.common.path import PathType


    def extract_custom(source_path: PathType, destination_directory: PathType) -> None:
        # Custom extraction logic for a hypothetical package format
        ...


    @plugins.hookimpl
    def conda_package_extractors():
        yield plugins.types.CondaPackageExtractor(
            name="custom-package",
            extensions=[".custom"],
            extract=extract_custom,
        )

:return: An iterable of :class:`~conda.plugins.types.CondaPackageExtractor` entries.
r"   Nr"   r#   s    r%   conda_package_extractors#CondaSpecs.conda_package_extractors  s     B r(   r"   N)returnzIterable[CondaSolver])re   zIterable[CondaSubcommand])re   zIterable[CondaVirtualPackage])re   zIterable[CondaPreCommand])re   zIterable[CondaPostCommand])re   zIterable[CondaAuthHandler])re   zIterable[CondaHealthCheck])re   z#Iterable[CondaPreTransactionAction])re   z$Iterable[CondaPostTransactionAction])re   zIterable[CondaPreSolve])re   zIterable[CondaPostSolve])re   zIterable[CondaSetting])re   zIterable[CondaReporterBackend])rQ   strre   Iterable[CondaRequestHeader])rQ   rf   rU   rf   re   rg   )re   zIterable[CondaPrefixDataLoader])re   z#Iterable[CondaEnvironmentSpecifier])re   z"Iterable[CondaEnvironmentExporter])re   zIterable[CondaPackageExtractor])__name__
__module____qualname____firstlineno____doc__	_hookspecr&   r*   r-   r0   r4   r7   r:   r>   rB   rE   rH   rK   rN   rR   rV   rZ   r]   r`   rc   __static_attributes__r"   rY   r%   r   r   ;   s   = B  6  .  2  2 # #J ; ;z 1 1f 1 1f  >  @  2 9 9v  4 "	% : ( (T ; ;z 6 6p    rY   r   )%rl   
__future__r   typingr   pluggybase.constantsr   deprecationsr   collections.abcr   typesr
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   constantHookspecMarkerrm   HookimplMarkerhookimplr   r"   rY   r%   <module>rz      s    #    % %(    *   

; !!(+	 ]  * Nl lrY   