about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks')
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py31
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py410
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py21
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py389
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/py.typed0
5 files changed, 851 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py
new file mode 100644
index 00000000..746b89f7
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py
@@ -0,0 +1,31 @@
+"""Wrappers to call pyproject.toml-based build backend hooks.
+"""
+
+from typing import TYPE_CHECKING
+
+from ._impl import (
+    BackendUnavailable,
+    BuildBackendHookCaller,
+    HookMissing,
+    UnsupportedOperation,
+    default_subprocess_runner,
+    quiet_subprocess_runner,
+)
+
+__version__ = "1.2.0"
+__all__ = [
+    "BackendUnavailable",
+    "BackendInvalid",
+    "HookMissing",
+    "UnsupportedOperation",
+    "default_subprocess_runner",
+    "quiet_subprocess_runner",
+    "BuildBackendHookCaller",
+]
+
+BackendInvalid = BackendUnavailable  # Deprecated alias, previously a separate exception
+
+if TYPE_CHECKING:
+    from ._impl import SubprocessRunner
+
+    __all__ += ["SubprocessRunner"]
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py
new file mode 100644
index 00000000..d1e9d7bb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py
@@ -0,0 +1,410 @@
+import json
+import os
+import sys
+import tempfile
+from contextlib import contextmanager
+from os.path import abspath
+from os.path import join as pjoin
+from subprocess import STDOUT, check_call, check_output
+from typing import TYPE_CHECKING, Any, Iterator, Mapping, Optional, Sequence
+
+from ._in_process import _in_proc_script_path
+
+if TYPE_CHECKING:
+    from typing import Protocol
+
+    class SubprocessRunner(Protocol):
+        """A protocol for the subprocess runner."""
+
+        def __call__(
+            self,
+            cmd: Sequence[str],
+            cwd: Optional[str] = None,
+            extra_environ: Optional[Mapping[str, str]] = None,
+        ) -> None:
+            ...
+
+
+def write_json(obj: Mapping[str, Any], path: str, **kwargs) -> None:
+    with open(path, "w", encoding="utf-8") as f:
+        json.dump(obj, f, **kwargs)
+
+
+def read_json(path: str) -> Mapping[str, Any]:
+    with open(path, encoding="utf-8") as f:
+        return json.load(f)
+
+
+class BackendUnavailable(Exception):
+    """Will be raised if the backend cannot be imported in the hook process."""
+
+    def __init__(
+        self,
+        traceback: str,
+        message: Optional[str] = None,
+        backend_name: Optional[str] = None,
+        backend_path: Optional[Sequence[str]] = None,
+    ) -> None:
+        # Preserving arg order for the sake of API backward compatibility.
+        self.backend_name = backend_name
+        self.backend_path = backend_path
+        self.traceback = traceback
+        super().__init__(message or "Error while importing backend")
+
+
+class HookMissing(Exception):
+    """Will be raised on missing hooks (if a fallback can't be used)."""
+
+    def __init__(self, hook_name: str) -> None:
+        super().__init__(hook_name)
+        self.hook_name = hook_name
+
+
+class UnsupportedOperation(Exception):
+    """May be raised by build_sdist if the backend indicates that it can't."""
+
+    def __init__(self, traceback: str) -> None:
+        self.traceback = traceback
+
+
+def default_subprocess_runner(
+    cmd: Sequence[str],
+    cwd: Optional[str] = None,
+    extra_environ: Optional[Mapping[str, str]] = None,
+) -> None:
+    """The default method of calling the wrapper subprocess.
+
+    This uses :func:`subprocess.check_call` under the hood.
+    """
+    env = os.environ.copy()
+    if extra_environ:
+        env.update(extra_environ)
+
+    check_call(cmd, cwd=cwd, env=env)
+
+
+def quiet_subprocess_runner(
+    cmd: Sequence[str],
+    cwd: Optional[str] = None,
+    extra_environ: Optional[Mapping[str, str]] = None,
+) -> None:
+    """Call the subprocess while suppressing output.
+
+    This uses :func:`subprocess.check_output` under the hood.
+    """
+    env = os.environ.copy()
+    if extra_environ:
+        env.update(extra_environ)
+
+    check_output(cmd, cwd=cwd, env=env, stderr=STDOUT)
+
+
+def norm_and_check(source_tree: str, requested: str) -> str:
+    """Normalise and check a backend path.
+
+    Ensure that the requested backend path is specified as a relative path,
+    and resolves to a location under the given source tree.
+
+    Return an absolute version of the requested path.
+    """
+    if os.path.isabs(requested):
+        raise ValueError("paths must be relative")
+
+    abs_source = os.path.abspath(source_tree)
+    abs_requested = os.path.normpath(os.path.join(abs_source, requested))
+    # We have to use commonprefix for Python 2.7 compatibility. So we
+    # normalise case to avoid problems because commonprefix is a character
+    # based comparison :-(
+    norm_source = os.path.normcase(abs_source)
+    norm_requested = os.path.normcase(abs_requested)
+    if os.path.commonprefix([norm_source, norm_requested]) != norm_source:
+        raise ValueError("paths must be inside source tree")
+
+    return abs_requested
+
+
+class BuildBackendHookCaller:
+    """A wrapper to call the build backend hooks for a source directory."""
+
+    def __init__(
+        self,
+        source_dir: str,
+        build_backend: str,
+        backend_path: Optional[Sequence[str]] = None,
+        runner: Optional["SubprocessRunner"] = None,
+        python_executable: Optional[str] = None,
+    ) -> None:
+        """
+        :param source_dir: The source directory to invoke the build backend for
+        :param build_backend: The build backend spec
+        :param backend_path: Additional path entries for the build backend spec
+        :param runner: The :ref:`subprocess runner <Subprocess Runners>` to use
+        :param python_executable:
+            The Python executable used to invoke the build backend
+        """
+        if runner is None:
+            runner = default_subprocess_runner
+
+        self.source_dir = abspath(source_dir)
+        self.build_backend = build_backend
+        if backend_path:
+            backend_path = [norm_and_check(self.source_dir, p) for p in backend_path]
+        self.backend_path = backend_path
+        self._subprocess_runner = runner
+        if not python_executable:
+            python_executable = sys.executable
+        self.python_executable = python_executable
+
+    @contextmanager
+    def subprocess_runner(self, runner: "SubprocessRunner") -> Iterator[None]:
+        """A context manager for temporarily overriding the default
+        :ref:`subprocess runner <Subprocess Runners>`.
+
+        :param runner: The new subprocess runner to use within the context.
+
+        .. code-block:: python
+
+            hook_caller = BuildBackendHookCaller(...)
+            with hook_caller.subprocess_runner(quiet_subprocess_runner):
+                ...
+        """
+        prev = self._subprocess_runner
+        self._subprocess_runner = runner
+        try:
+            yield
+        finally:
+            self._subprocess_runner = prev
+
+    def _supported_features(self) -> Sequence[str]:
+        """Return the list of optional features supported by the backend."""
+        return self._call_hook("_supported_features", {})
+
+    def get_requires_for_build_wheel(
+        self,
+        config_settings: Optional[Mapping[str, Any]] = None,
+    ) -> Sequence[str]:
+        """Get additional dependencies required for building a wheel.
+
+        :param config_settings: The configuration settings for the build backend
+        :returns: A list of :pep:`dependency specifiers <508>`.
+
+        .. admonition:: Fallback
+
+            If the build backend does not defined a hook with this name, an
+            empty list will be returned.
+        """
+        return self._call_hook(
+            "get_requires_for_build_wheel", {"config_settings": config_settings}
+        )
+
+    def prepare_metadata_for_build_wheel(
+        self,
+        metadata_directory: str,
+        config_settings: Optional[Mapping[str, Any]] = None,
+        _allow_fallback: bool = True,
+    ) -> str:
+        """Prepare a ``*.dist-info`` folder with metadata for this project.
+
+        :param metadata_directory: The directory to write the metadata to
+        :param config_settings: The configuration settings for the build backend
+        :param _allow_fallback:
+            Whether to allow the fallback to building a wheel and extracting
+            the metadata from it. Should be passed as a keyword argument only.
+
+        :returns: Name of the newly created subfolder within
+                  ``metadata_directory``, containing the metadata.
+
+        .. admonition:: Fallback
+
+            If the build backend does not define a hook with this name and
+            ``_allow_fallback`` is truthy, the backend will be asked to build a
+            wheel via the ``build_wheel`` hook and the dist-info extracted from
+            that will be returned.
+        """
+        return self._call_hook(
+            "prepare_metadata_for_build_wheel",
+            {
+                "metadata_directory": abspath(metadata_directory),
+                "config_settings": config_settings,
+                "_allow_fallback": _allow_fallback,
+            },
+        )
+
+    def build_wheel(
+        self,
+        wheel_directory: str,
+        config_settings: Optional[Mapping[str, Any]] = None,
+        metadata_directory: Optional[str] = None,
+    ) -> str:
+        """Build a wheel from this project.
+
+        :param wheel_directory: The directory to write the wheel to
+        :param config_settings: The configuration settings for the build backend
+        :param metadata_directory: The directory to reuse existing metadata from
+        :returns:
+            The name of the newly created wheel within ``wheel_directory``.
+
+        .. admonition:: Interaction with fallback
+
+            If the ``build_wheel`` hook was called in the fallback for
+            :meth:`prepare_metadata_for_build_wheel`, the build backend would
+            not be invoked. Instead, the previously built wheel will be copied
+            to ``wheel_directory`` and the name of that file will be returned.
+        """
+        if metadata_directory is not None:
+            metadata_directory = abspath(metadata_directory)
+        return self._call_hook(
+            "build_wheel",
+            {
+                "wheel_directory": abspath(wheel_directory),
+                "config_settings": config_settings,
+                "metadata_directory": metadata_directory,
+            },
+        )
+
+    def get_requires_for_build_editable(
+        self,
+        config_settings: Optional[Mapping[str, Any]] = None,
+    ) -> Sequence[str]:
+        """Get additional dependencies required for building an editable wheel.
+
+        :param config_settings: The configuration settings for the build backend
+        :returns: A list of :pep:`dependency specifiers <508>`.
+
+        .. admonition:: Fallback
+
+            If the build backend does not defined a hook with this name, an
+            empty list will be returned.
+        """
+        return self._call_hook(
+            "get_requires_for_build_editable", {"config_settings": config_settings}
+        )
+
+    def prepare_metadata_for_build_editable(
+        self,
+        metadata_directory: str,
+        config_settings: Optional[Mapping[str, Any]] = None,
+        _allow_fallback: bool = True,
+    ) -> Optional[str]:
+        """Prepare a ``*.dist-info`` folder with metadata for this project.
+
+        :param metadata_directory: The directory to write the metadata to
+        :param config_settings: The configuration settings for the build backend
+        :param _allow_fallback:
+            Whether to allow the fallback to building a wheel and extracting
+            the metadata from it. Should be passed as a keyword argument only.
+        :returns: Name of the newly created subfolder within
+                  ``metadata_directory``, containing the metadata.
+
+        .. admonition:: Fallback
+
+            If the build backend does not define a hook with this name and
+            ``_allow_fallback`` is truthy, the backend will be asked to build a
+            wheel via the ``build_editable`` hook and the dist-info
+            extracted from that will be returned.
+        """
+        return self._call_hook(
+            "prepare_metadata_for_build_editable",
+            {
+                "metadata_directory": abspath(metadata_directory),
+                "config_settings": config_settings,
+                "_allow_fallback": _allow_fallback,
+            },
+        )
+
+    def build_editable(
+        self,
+        wheel_directory: str,
+        config_settings: Optional[Mapping[str, Any]] = None,
+        metadata_directory: Optional[str] = None,
+    ) -> str:
+        """Build an editable wheel from this project.
+
+        :param wheel_directory: The directory to write the wheel to
+        :param config_settings: The configuration settings for the build backend
+        :param metadata_directory: The directory to reuse existing metadata from
+        :returns:
+            The name of the newly created wheel within ``wheel_directory``.
+
+        .. admonition:: Interaction with fallback
+
+            If the ``build_editable`` hook was called in the fallback for
+            :meth:`prepare_metadata_for_build_editable`, the build backend
+            would not be invoked. Instead, the previously built wheel will be
+            copied to ``wheel_directory`` and the name of that file will be
+            returned.
+        """
+        if metadata_directory is not None:
+            metadata_directory = abspath(metadata_directory)
+        return self._call_hook(
+            "build_editable",
+            {
+                "wheel_directory": abspath(wheel_directory),
+                "config_settings": config_settings,
+                "metadata_directory": metadata_directory,
+            },
+        )
+
+    def get_requires_for_build_sdist(
+        self,
+        config_settings: Optional[Mapping[str, Any]] = None,
+    ) -> Sequence[str]:
+        """Get additional dependencies required for building an sdist.
+
+        :returns: A list of :pep:`dependency specifiers <508>`.
+        """
+        return self._call_hook(
+            "get_requires_for_build_sdist", {"config_settings": config_settings}
+        )
+
+    def build_sdist(
+        self,
+        sdist_directory: str,
+        config_settings: Optional[Mapping[str, Any]] = None,
+    ) -> str:
+        """Build an sdist from this project.
+
+        :returns:
+            The name of the newly created sdist within ``wheel_directory``.
+        """
+        return self._call_hook(
+            "build_sdist",
+            {
+                "sdist_directory": abspath(sdist_directory),
+                "config_settings": config_settings,
+            },
+        )
+
+    def _call_hook(self, hook_name: str, kwargs: Mapping[str, Any]) -> Any:
+        extra_environ = {"_PYPROJECT_HOOKS_BUILD_BACKEND": self.build_backend}
+
+        if self.backend_path:
+            backend_path = os.pathsep.join(self.backend_path)
+            extra_environ["_PYPROJECT_HOOKS_BACKEND_PATH"] = backend_path
+
+        with tempfile.TemporaryDirectory() as td:
+            hook_input = {"kwargs": kwargs}
+            write_json(hook_input, pjoin(td, "input.json"), indent=2)
+
+            # Run the hook in a subprocess
+            with _in_proc_script_path() as script:
+                python = self.python_executable
+                self._subprocess_runner(
+                    [python, abspath(str(script)), hook_name, td],
+                    cwd=self.source_dir,
+                    extra_environ=extra_environ,
+                )
+
+            data = read_json(pjoin(td, "output.json"))
+            if data.get("unsupported"):
+                raise UnsupportedOperation(data.get("traceback", ""))
+            if data.get("no_backend"):
+                raise BackendUnavailable(
+                    data.get("traceback", ""),
+                    message=data.get("backend_error", ""),
+                    backend_name=self.build_backend,
+                    backend_path=self.backend_path,
+                )
+            if data.get("hook_missing"):
+                raise HookMissing(data.get("missing_hook_name") or hook_name)
+            return data["return_val"]
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py
new file mode 100644
index 00000000..906d0ba2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py
@@ -0,0 +1,21 @@
+"""This is a subpackage because the directory is on sys.path for _in_process.py
+
+The subpackage should stay as empty as possible to avoid shadowing modules that
+the backend might import.
+"""
+
+import importlib.resources as resources
+
+try:
+    resources.files
+except AttributeError:
+    # Python 3.8 compatibility
+    def _in_proc_script_path():
+        return resources.path(__package__, "_in_process.py")
+
+else:
+
+    def _in_proc_script_path():
+        return resources.as_file(
+            resources.files(__package__).joinpath("_in_process.py")
+        )
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py
new file mode 100644
index 00000000..d689bab7
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py
@@ -0,0 +1,389 @@
+"""This is invoked in a subprocess to call the build backend hooks.
+
+It expects:
+- Command line args: hook_name, control_dir
+- Environment variables:
+      _PYPROJECT_HOOKS_BUILD_BACKEND=entry.point:spec
+      _PYPROJECT_HOOKS_BACKEND_PATH=paths (separated with os.pathsep)
+- control_dir/input.json:
+  - {"kwargs": {...}}
+
+Results:
+- control_dir/output.json
+  - {"return_val": ...}
+"""
+import json
+import os
+import os.path
+import re
+import shutil
+import sys
+import traceback
+from glob import glob
+from importlib import import_module
+from importlib.machinery import PathFinder
+from os.path import join as pjoin
+
+# This file is run as a script, and `import wrappers` is not zip-safe, so we
+# include write_json() and read_json() from wrappers.py.
+
+
+def write_json(obj, path, **kwargs):
+    with open(path, "w", encoding="utf-8") as f:
+        json.dump(obj, f, **kwargs)
+
+
+def read_json(path):
+    with open(path, encoding="utf-8") as f:
+        return json.load(f)
+
+
+class BackendUnavailable(Exception):
+    """Raised if we cannot import the backend"""
+
+    def __init__(self, message, traceback=None):
+        super().__init__(message)
+        self.message = message
+        self.traceback = traceback
+
+
+class HookMissing(Exception):
+    """Raised if a hook is missing and we are not executing the fallback"""
+
+    def __init__(self, hook_name=None):
+        super().__init__(hook_name)
+        self.hook_name = hook_name
+
+
+def _build_backend():
+    """Find and load the build backend"""
+    backend_path = os.environ.get("_PYPROJECT_HOOKS_BACKEND_PATH")
+    ep = os.environ["_PYPROJECT_HOOKS_BUILD_BACKEND"]
+    mod_path, _, obj_path = ep.partition(":")
+
+    if backend_path:
+        # Ensure in-tree backend directories have the highest priority when importing.
+        extra_pathitems = backend_path.split(os.pathsep)
+        sys.meta_path.insert(0, _BackendPathFinder(extra_pathitems, mod_path))
+
+    try:
+        obj = import_module(mod_path)
+    except ImportError:
+        msg = f"Cannot import {mod_path!r}"
+        raise BackendUnavailable(msg, traceback.format_exc())
+
+    if obj_path:
+        for path_part in obj_path.split("."):
+            obj = getattr(obj, path_part)
+    return obj
+
+
+class _BackendPathFinder:
+    """Implements the MetaPathFinder interface to locate modules in ``backend-path``.
+
+    Since the environment provided by the frontend can contain all sorts of
+    MetaPathFinders, the only way to ensure the backend is loaded from the
+    right place is to prepend our own.
+    """
+
+    def __init__(self, backend_path, backend_module):
+        self.backend_path = backend_path
+        self.backend_module = backend_module
+        self.backend_parent, _, _ = backend_module.partition(".")
+
+    def find_spec(self, fullname, _path, _target=None):
+        if "." in fullname:
+            # Rely on importlib to find nested modules based on parent's path
+            return None
+
+        # Ignore other items in _path or sys.path and use backend_path instead:
+        spec = PathFinder.find_spec(fullname, path=self.backend_path)
+        if spec is None and fullname == self.backend_parent:
+            # According to the spec, the backend MUST be loaded from backend-path.
+            # Therefore, we can halt the import machinery and raise a clean error.
+            msg = f"Cannot find module {self.backend_module!r} in {self.backend_path!r}"
+            raise BackendUnavailable(msg)
+
+        return spec
+
+    if sys.version_info >= (3, 8):
+
+        def find_distributions(self, context=None):
+            # Delayed import: Python 3.7 does not contain importlib.metadata
+            from importlib.metadata import DistributionFinder, MetadataPathFinder
+
+            context = DistributionFinder.Context(path=self.backend_path)
+            return MetadataPathFinder.find_distributions(context=context)
+
+
+def _supported_features():
+    """Return the list of options features supported by the backend.
+
+    Returns a list of strings.
+    The only possible value is 'build_editable'.
+    """
+    backend = _build_backend()
+    features = []
+    if hasattr(backend, "build_editable"):
+        features.append("build_editable")
+    return features
+
+
+def get_requires_for_build_wheel(config_settings):
+    """Invoke the optional get_requires_for_build_wheel hook
+
+    Returns [] if the hook is not defined.
+    """
+    backend = _build_backend()
+    try:
+        hook = backend.get_requires_for_build_wheel
+    except AttributeError:
+        return []
+    else:
+        return hook(config_settings)
+
+
+def get_requires_for_build_editable(config_settings):
+    """Invoke the optional get_requires_for_build_editable hook
+
+    Returns [] if the hook is not defined.
+    """
+    backend = _build_backend()
+    try:
+        hook = backend.get_requires_for_build_editable
+    except AttributeError:
+        return []
+    else:
+        return hook(config_settings)
+
+
+def prepare_metadata_for_build_wheel(
+    metadata_directory, config_settings, _allow_fallback
+):
+    """Invoke optional prepare_metadata_for_build_wheel
+
+    Implements a fallback by building a wheel if the hook isn't defined,
+    unless _allow_fallback is False in which case HookMissing is raised.
+    """
+    backend = _build_backend()
+    try:
+        hook = backend.prepare_metadata_for_build_wheel
+    except AttributeError:
+        if not _allow_fallback:
+            raise HookMissing()
+    else:
+        return hook(metadata_directory, config_settings)
+    # fallback to build_wheel outside the try block to avoid exception chaining
+    # which can be confusing to users and is not relevant
+    whl_basename = backend.build_wheel(metadata_directory, config_settings)
+    return _get_wheel_metadata_from_wheel(
+        whl_basename, metadata_directory, config_settings
+    )
+
+
+def prepare_metadata_for_build_editable(
+    metadata_directory, config_settings, _allow_fallback
+):
+    """Invoke optional prepare_metadata_for_build_editable
+
+    Implements a fallback by building an editable wheel if the hook isn't
+    defined, unless _allow_fallback is False in which case HookMissing is
+    raised.
+    """
+    backend = _build_backend()
+    try:
+        hook = backend.prepare_metadata_for_build_editable
+    except AttributeError:
+        if not _allow_fallback:
+            raise HookMissing()
+        try:
+            build_hook = backend.build_editable
+        except AttributeError:
+            raise HookMissing(hook_name="build_editable")
+        else:
+            whl_basename = build_hook(metadata_directory, config_settings)
+            return _get_wheel_metadata_from_wheel(
+                whl_basename, metadata_directory, config_settings
+            )
+    else:
+        return hook(metadata_directory, config_settings)
+
+
+WHEEL_BUILT_MARKER = "PYPROJECT_HOOKS_ALREADY_BUILT_WHEEL"
+
+
+def _dist_info_files(whl_zip):
+    """Identify the .dist-info folder inside a wheel ZipFile."""
+    res = []
+    for path in whl_zip.namelist():
+        m = re.match(r"[^/\\]+-[^/\\]+\.dist-info/", path)
+        if m:
+            res.append(path)
+    if res:
+        return res
+    raise Exception("No .dist-info folder found in wheel")
+
+
+def _get_wheel_metadata_from_wheel(whl_basename, metadata_directory, config_settings):
+    """Extract the metadata from a wheel.
+
+    Fallback for when the build backend does not
+    define the 'get_wheel_metadata' hook.
+    """
+    from zipfile import ZipFile
+
+    with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), "wb"):
+        pass  # Touch marker file
+
+    whl_file = os.path.join(metadata_directory, whl_basename)
+    with ZipFile(whl_file) as zipf:
+        dist_info = _dist_info_files(zipf)
+        zipf.extractall(path=metadata_directory, members=dist_info)
+    return dist_info[0].split("/")[0]
+
+
+def _find_already_built_wheel(metadata_directory):
+    """Check for a wheel already built during the get_wheel_metadata hook."""
+    if not metadata_directory:
+        return None
+    metadata_parent = os.path.dirname(metadata_directory)
+    if not os.path.isfile(pjoin(metadata_parent, WHEEL_BUILT_MARKER)):
+        return None
+
+    whl_files = glob(os.path.join(metadata_parent, "*.whl"))
+    if not whl_files:
+        print("Found wheel built marker, but no .whl files")
+        return None
+    if len(whl_files) > 1:
+        print(
+            "Found multiple .whl files; unspecified behaviour. "
+            "Will call build_wheel."
+        )
+        return None
+
+    # Exactly one .whl file
+    return whl_files[0]
+
+
+def build_wheel(wheel_directory, config_settings, metadata_directory=None):
+    """Invoke the mandatory build_wheel hook.
+
+    If a wheel was already built in the
+    prepare_metadata_for_build_wheel fallback, this
+    will copy it rather than rebuilding the wheel.
+    """
+    prebuilt_whl = _find_already_built_wheel(metadata_directory)
+    if prebuilt_whl:
+        shutil.copy2(prebuilt_whl, wheel_directory)
+        return os.path.basename(prebuilt_whl)
+
+    return _build_backend().build_wheel(
+        wheel_directory, config_settings, metadata_directory
+    )
+
+
+def build_editable(wheel_directory, config_settings, metadata_directory=None):
+    """Invoke the optional build_editable hook.
+
+    If a wheel was already built in the
+    prepare_metadata_for_build_editable fallback, this
+    will copy it rather than rebuilding the wheel.
+    """
+    backend = _build_backend()
+    try:
+        hook = backend.build_editable
+    except AttributeError:
+        raise HookMissing()
+    else:
+        prebuilt_whl = _find_already_built_wheel(metadata_directory)
+        if prebuilt_whl:
+            shutil.copy2(prebuilt_whl, wheel_directory)
+            return os.path.basename(prebuilt_whl)
+
+        return hook(wheel_directory, config_settings, metadata_directory)
+
+
+def get_requires_for_build_sdist(config_settings):
+    """Invoke the optional get_requires_for_build_wheel hook
+
+    Returns [] if the hook is not defined.
+    """
+    backend = _build_backend()
+    try:
+        hook = backend.get_requires_for_build_sdist
+    except AttributeError:
+        return []
+    else:
+        return hook(config_settings)
+
+
+class _DummyException(Exception):
+    """Nothing should ever raise this exception"""
+
+
+class GotUnsupportedOperation(Exception):
+    """For internal use when backend raises UnsupportedOperation"""
+
+    def __init__(self, traceback):
+        self.traceback = traceback
+
+
+def build_sdist(sdist_directory, config_settings):
+    """Invoke the mandatory build_sdist hook."""
+    backend = _build_backend()
+    try:
+        return backend.build_sdist(sdist_directory, config_settings)
+    except getattr(backend, "UnsupportedOperation", _DummyException):
+        raise GotUnsupportedOperation(traceback.format_exc())
+
+
+HOOK_NAMES = {
+    "get_requires_for_build_wheel",
+    "prepare_metadata_for_build_wheel",
+    "build_wheel",
+    "get_requires_for_build_editable",
+    "prepare_metadata_for_build_editable",
+    "build_editable",
+    "get_requires_for_build_sdist",
+    "build_sdist",
+    "_supported_features",
+}
+
+
+def main():
+    if len(sys.argv) < 3:
+        sys.exit("Needs args: hook_name, control_dir")
+    hook_name = sys.argv[1]
+    control_dir = sys.argv[2]
+    if hook_name not in HOOK_NAMES:
+        sys.exit("Unknown hook: %s" % hook_name)
+
+    # Remove the parent directory from sys.path to avoid polluting the backend
+    # import namespace with this directory.
+    here = os.path.dirname(__file__)
+    if here in sys.path:
+        sys.path.remove(here)
+
+    hook = globals()[hook_name]
+
+    hook_input = read_json(pjoin(control_dir, "input.json"))
+
+    json_out = {"unsupported": False, "return_val": None}
+    try:
+        json_out["return_val"] = hook(**hook_input["kwargs"])
+    except BackendUnavailable as e:
+        json_out["no_backend"] = True
+        json_out["traceback"] = e.traceback
+        json_out["backend_error"] = e.message
+    except GotUnsupportedOperation as e:
+        json_out["unsupported"] = True
+        json_out["traceback"] = e.traceback
+    except HookMissing as e:
+        json_out["hook_missing"] = True
+        json_out["missing_hook_name"] = e.hook_name or hook_name
+
+    write_json(json_out, pjoin(control_dir, "output.json"), indent=2)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/py.typed b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/py.typed
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/py.typed