Trying to fix python
This commit is contained in:
parent
11b4874ad4
commit
aa815d591b
|
@ -7,24 +7,6 @@ __pycache__/
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# Usually these files are written by a python script from a template
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
import contextlib
|
||||||
|
import hashlib
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from types import TracebackType
|
||||||
|
from typing import Dict, Generator, Optional, Set, Type, Union
|
||||||
|
|
||||||
|
from pip._internal.models.link import Link
|
||||||
|
from pip._internal.req.req_install import InstallRequirement
|
||||||
|
from pip._internal.utils.temp_dir import TempDirectory
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def update_env_context_manager(**changes: str) -> Generator[None, None, None]:
|
||||||
|
target = os.environ
|
||||||
|
|
||||||
|
# Save values from the target and change them.
|
||||||
|
non_existent_marker = object()
|
||||||
|
saved_values: Dict[str, Union[object, str]] = {}
|
||||||
|
for name, new_value in changes.items():
|
||||||
|
try:
|
||||||
|
saved_values[name] = target[name]
|
||||||
|
except KeyError:
|
||||||
|
saved_values[name] = non_existent_marker
|
||||||
|
target[name] = new_value
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
# Restore original values in the target.
|
||||||
|
for name, original_value in saved_values.items():
|
||||||
|
if original_value is non_existent_marker:
|
||||||
|
del target[name]
|
||||||
|
else:
|
||||||
|
assert isinstance(original_value, str) # for mypy
|
||||||
|
target[name] = original_value
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def get_build_tracker() -> Generator["BuildTracker", None, None]:
|
||||||
|
root = os.environ.get("PIP_BUILD_TRACKER")
|
||||||
|
with contextlib.ExitStack() as ctx:
|
||||||
|
if root is None:
|
||||||
|
root = ctx.enter_context(TempDirectory(kind="build-tracker")).path
|
||||||
|
ctx.enter_context(update_env_context_manager(PIP_BUILD_TRACKER=root))
|
||||||
|
logger.debug("Initialized build tracking at %s", root)
|
||||||
|
|
||||||
|
with BuildTracker(root) as tracker:
|
||||||
|
yield tracker
|
||||||
|
|
||||||
|
|
||||||
|
class BuildTracker:
|
||||||
|
def __init__(self, root: str) -> None:
|
||||||
|
self._root = root
|
||||||
|
self._entries: Set[InstallRequirement] = set()
|
||||||
|
logger.debug("Created build tracker: %s", self._root)
|
||||||
|
|
||||||
|
def __enter__(self) -> "BuildTracker":
|
||||||
|
logger.debug("Entered build tracker: %s", self._root)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(
|
||||||
|
self,
|
||||||
|
exc_type: Optional[Type[BaseException]],
|
||||||
|
exc_val: Optional[BaseException],
|
||||||
|
exc_tb: Optional[TracebackType],
|
||||||
|
) -> None:
|
||||||
|
self.cleanup()
|
||||||
|
|
||||||
|
def _entry_path(self, link: Link) -> str:
|
||||||
|
hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest()
|
||||||
|
return os.path.join(self._root, hashed)
|
||||||
|
|
||||||
|
def add(self, req: InstallRequirement) -> None:
|
||||||
|
"""Add an InstallRequirement to build tracking."""
|
||||||
|
|
||||||
|
assert req.link
|
||||||
|
# Get the file to write information about this requirement.
|
||||||
|
entry_path = self._entry_path(req.link)
|
||||||
|
|
||||||
|
# Try reading from the file. If it exists and can be read from, a build
|
||||||
|
# is already in progress, so a LookupError is raised.
|
||||||
|
try:
|
||||||
|
with open(entry_path) as fp:
|
||||||
|
contents = fp.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
message = "{} is already being built: {}".format(req.link, contents)
|
||||||
|
raise LookupError(message)
|
||||||
|
|
||||||
|
# If we're here, req should really not be building already.
|
||||||
|
assert req not in self._entries
|
||||||
|
|
||||||
|
# Start tracking this requirement.
|
||||||
|
with open(entry_path, "w", encoding="utf-8") as fp:
|
||||||
|
fp.write(str(req))
|
||||||
|
self._entries.add(req)
|
||||||
|
|
||||||
|
logger.debug("Added %s to build tracker %r", req, self._root)
|
||||||
|
|
||||||
|
def remove(self, req: InstallRequirement) -> None:
|
||||||
|
"""Remove an InstallRequirement from build tracking."""
|
||||||
|
|
||||||
|
assert req.link
|
||||||
|
# Delete the created file and the corresponding entries.
|
||||||
|
os.unlink(self._entry_path(req.link))
|
||||||
|
self._entries.remove(req)
|
||||||
|
|
||||||
|
logger.debug("Removed %s from build tracker %r", req, self._root)
|
||||||
|
|
||||||
|
def cleanup(self) -> None:
|
||||||
|
for req in set(self._entries):
|
||||||
|
self.remove(req)
|
||||||
|
|
||||||
|
logger.debug("Removed build tracker: %r", self._root)
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def track(self, req: InstallRequirement) -> Generator[None, None, None]:
|
||||||
|
self.add(req)
|
||||||
|
yield
|
||||||
|
self.remove(req)
|
|
@ -0,0 +1,39 @@
|
||||||
|
"""Metadata generation logic for source distributions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from pip._vendor.pep517.wrappers import Pep517HookCaller
|
||||||
|
|
||||||
|
from pip._internal.build_env import BuildEnvironment
|
||||||
|
from pip._internal.exceptions import (
|
||||||
|
InstallationSubprocessError,
|
||||||
|
MetadataGenerationFailed,
|
||||||
|
)
|
||||||
|
from pip._internal.utils.subprocess import runner_with_spinner_message
|
||||||
|
from pip._internal.utils.temp_dir import TempDirectory
|
||||||
|
|
||||||
|
|
||||||
|
def generate_metadata(
|
||||||
|
build_env: BuildEnvironment, backend: Pep517HookCaller, details: str
|
||||||
|
) -> str:
|
||||||
|
"""Generate metadata using mechanisms described in PEP 517.
|
||||||
|
|
||||||
|
Returns the generated metadata directory.
|
||||||
|
"""
|
||||||
|
metadata_tmpdir = TempDirectory(kind="modern-metadata", globally_managed=True)
|
||||||
|
|
||||||
|
metadata_dir = metadata_tmpdir.path
|
||||||
|
|
||||||
|
with build_env:
|
||||||
|
# Note that Pep517HookCaller implements a fallback for
|
||||||
|
# prepare_metadata_for_build_wheel, so we don't have to
|
||||||
|
# consider the possibility that this hook doesn't exist.
|
||||||
|
runner = runner_with_spinner_message("Preparing metadata (pyproject.toml)")
|
||||||
|
with backend.subprocess_runner(runner):
|
||||||
|
try:
|
||||||
|
distinfo_dir = backend.prepare_metadata_for_build_wheel(metadata_dir)
|
||||||
|
except InstallationSubprocessError as error:
|
||||||
|
raise MetadataGenerationFailed(package_details=details) from error
|
||||||
|
|
||||||
|
return os.path.join(metadata_dir, distinfo_dir)
|
|
@ -0,0 +1,41 @@
|
||||||
|
"""Metadata generation logic for source distributions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from pip._vendor.pep517.wrappers import Pep517HookCaller
|
||||||
|
|
||||||
|
from pip._internal.build_env import BuildEnvironment
|
||||||
|
from pip._internal.exceptions import (
|
||||||
|
InstallationSubprocessError,
|
||||||
|
MetadataGenerationFailed,
|
||||||
|
)
|
||||||
|
from pip._internal.utils.subprocess import runner_with_spinner_message
|
||||||
|
from pip._internal.utils.temp_dir import TempDirectory
|
||||||
|
|
||||||
|
|
||||||
|
def generate_editable_metadata(
|
||||||
|
build_env: BuildEnvironment, backend: Pep517HookCaller, details: str
|
||||||
|
) -> str:
|
||||||
|
"""Generate metadata using mechanisms described in PEP 660.
|
||||||
|
|
||||||
|
Returns the generated metadata directory.
|
||||||
|
"""
|
||||||
|
metadata_tmpdir = TempDirectory(kind="modern-metadata", globally_managed=True)
|
||||||
|
|
||||||
|
metadata_dir = metadata_tmpdir.path
|
||||||
|
|
||||||
|
with build_env:
|
||||||
|
# Note that Pep517HookCaller implements a fallback for
|
||||||
|
# prepare_metadata_for_build_wheel/editable, so we don't have to
|
||||||
|
# consider the possibility that this hook doesn't exist.
|
||||||
|
runner = runner_with_spinner_message(
|
||||||
|
"Preparing editable metadata (pyproject.toml)"
|
||||||
|
)
|
||||||
|
with backend.subprocess_runner(runner):
|
||||||
|
try:
|
||||||
|
distinfo_dir = backend.prepare_metadata_for_build_editable(metadata_dir)
|
||||||
|
except InstallationSubprocessError as error:
|
||||||
|
raise MetadataGenerationFailed(package_details=details) from error
|
||||||
|
|
||||||
|
return os.path.join(metadata_dir, distinfo_dir)
|
|
@ -0,0 +1,74 @@
|
||||||
|
"""Metadata generation logic for legacy source distributions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from pip._internal.build_env import BuildEnvironment
|
||||||
|
from pip._internal.cli.spinners import open_spinner
|
||||||
|
from pip._internal.exceptions import (
|
||||||
|
InstallationError,
|
||||||
|
InstallationSubprocessError,
|
||||||
|
MetadataGenerationFailed,
|
||||||
|
)
|
||||||
|
from pip._internal.utils.setuptools_build import make_setuptools_egg_info_args
|
||||||
|
from pip._internal.utils.subprocess import call_subprocess
|
||||||
|
from pip._internal.utils.temp_dir import TempDirectory
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _find_egg_info(directory: str) -> str:
|
||||||
|
"""Find an .egg-info subdirectory in `directory`."""
|
||||||
|
filenames = [f for f in os.listdir(directory) if f.endswith(".egg-info")]
|
||||||
|
|
||||||
|
if not filenames:
|
||||||
|
raise InstallationError(f"No .egg-info directory found in {directory}")
|
||||||
|
|
||||||
|
if len(filenames) > 1:
|
||||||
|
raise InstallationError(
|
||||||
|
"More than one .egg-info directory found in {}".format(directory)
|
||||||
|
)
|
||||||
|
|
||||||
|
return os.path.join(directory, filenames[0])
|
||||||
|
|
||||||
|
|
||||||
|
def generate_metadata(
|
||||||
|
build_env: BuildEnvironment,
|
||||||
|
setup_py_path: str,
|
||||||
|
source_dir: str,
|
||||||
|
isolated: bool,
|
||||||
|
details: str,
|
||||||
|
) -> str:
|
||||||
|
"""Generate metadata using setup.py-based defacto mechanisms.
|
||||||
|
|
||||||
|
Returns the generated metadata directory.
|
||||||
|
"""
|
||||||
|
logger.debug(
|
||||||
|
"Running setup.py (path:%s) egg_info for package %s",
|
||||||
|
setup_py_path,
|
||||||
|
details,
|
||||||
|
)
|
||||||
|
|
||||||
|
egg_info_dir = TempDirectory(kind="pip-egg-info", globally_managed=True).path
|
||||||
|
|
||||||
|
args = make_setuptools_egg_info_args(
|
||||||
|
setup_py_path,
|
||||||
|
egg_info_dir=egg_info_dir,
|
||||||
|
no_user_config=isolated,
|
||||||
|
)
|
||||||
|
|
||||||
|
with build_env:
|
||||||
|
with open_spinner("Preparing metadata (setup.py)") as spinner:
|
||||||
|
try:
|
||||||
|
call_subprocess(
|
||||||
|
args,
|
||||||
|
cwd=source_dir,
|
||||||
|
command_desc="python setup.py egg_info",
|
||||||
|
spinner=spinner,
|
||||||
|
)
|
||||||
|
except InstallationSubprocessError as error:
|
||||||
|
raise MetadataGenerationFailed(package_details=details) from error
|
||||||
|
|
||||||
|
# Return the .egg-info directory.
|
||||||
|
return _find_egg_info(egg_info_dir)
|
|
@ -0,0 +1,37 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from pip._vendor.pep517.wrappers import Pep517HookCaller
|
||||||
|
|
||||||
|
from pip._internal.utils.subprocess import runner_with_spinner_message
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def build_wheel_pep517(
|
||||||
|
name: str,
|
||||||
|
backend: Pep517HookCaller,
|
||||||
|
metadata_directory: str,
|
||||||
|
tempd: str,
|
||||||
|
) -> Optional[str]:
|
||||||
|
"""Build one InstallRequirement using the PEP 517 build process.
|
||||||
|
|
||||||
|
Returns path to wheel if successfully built. Otherwise, returns None.
|
||||||
|
"""
|
||||||
|
assert metadata_directory is not None
|
||||||
|
try:
|
||||||
|
logger.debug("Destination directory: %s", tempd)
|
||||||
|
|
||||||
|
runner = runner_with_spinner_message(
|
||||||
|
f"Building wheel for {name} (pyproject.toml)"
|
||||||
|
)
|
||||||
|
with backend.subprocess_runner(runner):
|
||||||
|
wheel_name = backend.build_wheel(
|
||||||
|
tempd,
|
||||||
|
metadata_directory=metadata_directory,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
logger.error("Failed building wheel for %s", name)
|
||||||
|
return None
|
||||||
|
return os.path.join(tempd, wheel_name)
|
|
@ -0,0 +1,46 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from pip._vendor.pep517.wrappers import HookMissing, Pep517HookCaller
|
||||||
|
|
||||||
|
from pip._internal.utils.subprocess import runner_with_spinner_message
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def build_wheel_editable(
|
||||||
|
name: str,
|
||||||
|
backend: Pep517HookCaller,
|
||||||
|
metadata_directory: str,
|
||||||
|
tempd: str,
|
||||||
|
) -> Optional[str]:
|
||||||
|
"""Build one InstallRequirement using the PEP 660 build process.
|
||||||
|
|
||||||
|
Returns path to wheel if successfully built. Otherwise, returns None.
|
||||||
|
"""
|
||||||
|
assert metadata_directory is not None
|
||||||
|
try:
|
||||||
|
logger.debug("Destination directory: %s", tempd)
|
||||||
|
|
||||||
|
runner = runner_with_spinner_message(
|
||||||
|
f"Building editable for {name} (pyproject.toml)"
|
||||||
|
)
|
||||||
|
with backend.subprocess_runner(runner):
|
||||||
|
try:
|
||||||
|
wheel_name = backend.build_editable(
|
||||||
|
tempd,
|
||||||
|
metadata_directory=metadata_directory,
|
||||||
|
)
|
||||||
|
except HookMissing as e:
|
||||||
|
logger.error(
|
||||||
|
"Cannot build editable %s because the build "
|
||||||
|
"backend does not have the %s hook",
|
||||||
|
name,
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
logger.error("Failed building editable for %s", name)
|
||||||
|
return None
|
||||||
|
return os.path.join(tempd, wheel_name)
|
|
@ -0,0 +1,102 @@
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from pip._internal.cli.spinners import open_spinner
|
||||||
|
from pip._internal.utils.setuptools_build import make_setuptools_bdist_wheel_args
|
||||||
|
from pip._internal.utils.subprocess import call_subprocess, format_command_args
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def format_command_result(
|
||||||
|
command_args: List[str],
|
||||||
|
command_output: str,
|
||||||
|
) -> str:
|
||||||
|
"""Format command information for logging."""
|
||||||
|
command_desc = format_command_args(command_args)
|
||||||
|
text = f"Command arguments: {command_desc}\n"
|
||||||
|
|
||||||
|
if not command_output:
|
||||||
|
text += "Command output: None"
|
||||||
|
elif logger.getEffectiveLevel() > logging.DEBUG:
|
||||||
|
text += "Command output: [use --verbose to show]"
|
||||||
|
else:
|
||||||
|
if not command_output.endswith("\n"):
|
||||||
|
command_output += "\n"
|
||||||
|
text += f"Command output:\n{command_output}"
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def get_legacy_build_wheel_path(
|
||||||
|
names: List[str],
|
||||||
|
temp_dir: str,
|
||||||
|
name: str,
|
||||||
|
command_args: List[str],
|
||||||
|
command_output: str,
|
||||||
|
) -> Optional[str]:
|
||||||
|
"""Return the path to the wheel in the temporary build directory."""
|
||||||
|
# Sort for determinism.
|
||||||
|
names = sorted(names)
|
||||||
|
if not names:
|
||||||
|
msg = ("Legacy build of wheel for {!r} created no files.\n").format(name)
|
||||||
|
msg += format_command_result(command_args, command_output)
|
||||||
|
logger.warning(msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(names) > 1:
|
||||||
|
msg = (
|
||||||
|
"Legacy build of wheel for {!r} created more than one file.\n"
|
||||||
|
"Filenames (choosing first): {}\n"
|
||||||
|
).format(name, names)
|
||||||
|
msg += format_command_result(command_args, command_output)
|
||||||
|
logger.warning(msg)
|
||||||
|
|
||||||
|
return os.path.join(temp_dir, names[0])
|
||||||
|
|
||||||
|
|
||||||
|
def build_wheel_legacy(
|
||||||
|
name: str,
|
||||||
|
setup_py_path: str,
|
||||||
|
source_dir: str,
|
||||||
|
global_options: List[str],
|
||||||
|
build_options: List[str],
|
||||||
|
tempd: str,
|
||||||
|
) -> Optional[str]:
|
||||||
|
"""Build one unpacked package using the "legacy" build process.
|
||||||
|
|
||||||
|
Returns path to wheel if successfully built. Otherwise, returns None.
|
||||||
|
"""
|
||||||
|
wheel_args = make_setuptools_bdist_wheel_args(
|
||||||
|
setup_py_path,
|
||||||
|
global_options=global_options,
|
||||||
|
build_options=build_options,
|
||||||
|
destination_dir=tempd,
|
||||||
|
)
|
||||||
|
|
||||||
|
spin_message = f"Building wheel for {name} (setup.py)"
|
||||||
|
with open_spinner(spin_message) as spinner:
|
||||||
|
logger.debug("Destination directory: %s", tempd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
output = call_subprocess(
|
||||||
|
wheel_args,
|
||||||
|
command_desc="python setup.py bdist_wheel",
|
||||||
|
cwd=source_dir,
|
||||||
|
spinner=spinner,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
spinner.finish("error")
|
||||||
|
logger.error("Failed building wheel for %s", name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
names = os.listdir(tempd)
|
||||||
|
wheel_path = get_legacy_build_wheel_path(
|
||||||
|
names=names,
|
||||||
|
temp_dir=tempd,
|
||||||
|
name=name,
|
||||||
|
command_args=wheel_args,
|
||||||
|
command_output=output,
|
||||||
|
)
|
||||||
|
return wheel_path
|
Loading…
Reference in New Issue