summaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks
diff options
context:
space:
mode:
authorblackhao <13851610112@163.com>2025-08-22 02:51:50 -0500
committerblackhao <13851610112@163.com>2025-08-22 02:51:50 -0500
commit4aab4087dc97906d0b9890035401175cdaab32d4 (patch)
tree4e2e9d88a711ec5b1cfa02e8ac72a55183b99123 /.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks
parentafa8f50d1d21c721dabcb31ad244610946ab65a3 (diff)
2.0
Diffstat (limited to '.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks')
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__init__.py23
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pycbin0 -> 619 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pycbin0 -> 380 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pycbin0 -> 14731 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_compat.py8
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_impl.py330
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__init__.py18
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pycbin0 -> 1086 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pycbin0 -> 14403 bytes
-rw-r--r--.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/_in_process.py353
10 files changed, 732 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__init__.py b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__init__.py
new file mode 100644
index 0000000..ddfcf7f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__init__.py
@@ -0,0 +1,23 @@
+"""Wrappers to call pyproject.toml-based build backend hooks.
+"""
+
+from ._impl import (
+ BackendInvalid,
+ BackendUnavailable,
+ BuildBackendHookCaller,
+ HookMissing,
+ UnsupportedOperation,
+ default_subprocess_runner,
+ quiet_subprocess_runner,
+)
+
+__version__ = '1.0.0'
+__all__ = [
+ 'BackendUnavailable',
+ 'BackendInvalid',
+ 'HookMissing',
+ 'UnsupportedOperation',
+ 'default_subprocess_runner',
+ 'quiet_subprocess_runner',
+ 'BuildBackendHookCaller',
+]
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..6d79331
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc
new file mode 100644
index 0000000..5ae635a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc
new file mode 100644
index 0000000..056aad6
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_compat.py b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_compat.py
new file mode 100644
index 0000000..95e509c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_compat.py
@@ -0,0 +1,8 @@
+__all__ = ("tomllib",)
+
+import sys
+
+if sys.version_info >= (3, 11):
+ import tomllib
+else:
+ from pip._vendor import tomli as tomllib
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_impl.py b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_impl.py
new file mode 100644
index 0000000..37b0e65
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_impl.py
@@ -0,0 +1,330 @@
+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 ._in_process import _in_proc_script_path
+
+
+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):
+ """Will be raised if the backend cannot be imported in the hook process."""
+ def __init__(self, traceback):
+ self.traceback = traceback
+
+
+class BackendInvalid(Exception):
+ """Will be raised if the backend is invalid."""
+ def __init__(self, backend_name, backend_path, message):
+ super().__init__(message)
+ self.backend_name = backend_name
+ self.backend_path = backend_path
+
+
+class HookMissing(Exception):
+ """Will be raised on missing hooks (if a fallback can't be used)."""
+ def __init__(self, hook_name):
+ 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):
+ self.traceback = traceback
+
+
+def default_subprocess_runner(cmd, cwd=None, extra_environ=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, cwd=None, extra_environ=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, requested):
+ """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,
+ build_backend,
+ backend_path=None,
+ runner=None,
+ python_executable=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):
+ """A context manager for temporarily overriding the default
+ :ref:`subprocess runner <Subprocess Runners>`.
+
+ .. 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):
+ """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=None):
+ """Get additional dependencies required for building a wheel.
+
+ :returns: A list of :pep:`dependency specifiers <508>`.
+ :rtype: list[str]
+
+ .. 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, config_settings=None,
+ _allow_fallback=True):
+ """Prepare a ``*.dist-info`` folder with metadata for this project.
+
+ :returns: Name of the newly created subfolder within
+ ``metadata_directory``, containing the metadata.
+ :rtype: str
+
+ .. 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, config_settings=None,
+ metadata_directory=None):
+ """Build a wheel from this project.
+
+ :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=None):
+ """Get additional dependencies required for building an editable wheel.
+
+ :returns: A list of :pep:`dependency specifiers <508>`.
+ :rtype: list[str]
+
+ .. 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, config_settings=None,
+ _allow_fallback=True):
+ """Prepare a ``*.dist-info`` folder with metadata for this project.
+
+ :returns: Name of the newly created subfolder within
+ ``metadata_directory``, containing the metadata.
+ :rtype: str
+
+ .. 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, config_settings=None,
+ metadata_directory=None):
+ """Build an editable wheel from this project.
+
+ :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=None):
+ """Get additional dependencies required for building an sdist.
+
+ :returns: A list of :pep:`dependency specifiers <508>`.
+ :rtype: list[str]
+ """
+ return self._call_hook('get_requires_for_build_sdist', {
+ 'config_settings': config_settings
+ })
+
+ def build_sdist(self, sdist_directory, config_settings=None):
+ """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, kwargs):
+ extra_environ = {'PEP517_BUILD_BACKEND': self.build_backend}
+
+ if self.backend_path:
+ backend_path = os.pathsep.join(self.backend_path)
+ extra_environ['PEP517_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', ''))
+ if data.get('backend_invalid'):
+ raise BackendInvalid(
+ backend_name=self.build_backend,
+ backend_path=self.backend_path,
+ message=data.get('backend_error', '')
+ )
+ 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/~ip/_vendor/pyproject_hooks/_in_process/__init__.py b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__init__.py
new file mode 100644
index 0000000..917fa06
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__init__.py
@@ -0,0 +1,18 @@
+"""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/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..4a60c03
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc
new file mode 100644
index 0000000..1f52136
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc
Binary files differ
diff --git a/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/_in_process.py b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/_in_process.py
new file mode 100644
index 0000000..ee511ff
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/~ip/_vendor/pyproject_hooks/_in_process/_in_process.py
@@ -0,0 +1,353 @@
+"""This is invoked in a subprocess to call the build backend hooks.
+
+It expects:
+- Command line args: hook_name, control_dir
+- Environment variables:
+ PEP517_BUILD_BACKEND=entry.point:spec
+ PEP517_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 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, traceback):
+ self.traceback = traceback
+
+
+class BackendInvalid(Exception):
+ """Raised if the backend is invalid"""
+ def __init__(self, message):
+ self.message = message
+
+
+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 contained_in(filename, directory):
+ """Test if a file is located within the given directory."""
+ filename = os.path.normcase(os.path.abspath(filename))
+ directory = os.path.normcase(os.path.abspath(directory))
+ return os.path.commonprefix([filename, directory]) == directory
+
+
+def _build_backend():
+ """Find and load the build backend"""
+ # Add in-tree backend directories to the front of sys.path.
+ backend_path = os.environ.get('PEP517_BACKEND_PATH')
+ if backend_path:
+ extra_pathitems = backend_path.split(os.pathsep)
+ sys.path[:0] = extra_pathitems
+
+ ep = os.environ['PEP517_BUILD_BACKEND']
+ mod_path, _, obj_path = ep.partition(':')
+ try:
+ obj = import_module(mod_path)
+ except ImportError:
+ raise BackendUnavailable(traceback.format_exc())
+
+ if backend_path:
+ if not any(
+ contained_in(obj.__file__, path)
+ for path in extra_pathitems
+ ):
+ raise BackendInvalid("Backend was not loaded from backend-path")
+
+ if obj_path:
+ for path_part in obj_path.split('.'):
+ obj = getattr(obj, path_part)
+ return obj
+
+
+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 = 'PEP517_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)
+ 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
+ except BackendInvalid as e:
+ json_out['backend_invalid'] = True
+ 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()