Aluode/PerceptionLabPortable
0
1from __future__ import annotations2 3import inspect4import platform5from collections.abc import Callable6from typing import TYPE_CHECKING, Any, ClassVar7 8from ..dist import Distribution9from ..warnings import SetuptoolsDeprecationWarning, SetuptoolsWarning10 11import distutils.command.install as orig12from distutils.errors import DistutilsArgError13 14if TYPE_CHECKING:15 # This is only used for a type-cast, don't import at runtime or it'll cause deprecation warnings16 from .easy_install import easy_install as easy_install_cls17else:18 easy_install_cls = None19 20 21def __getattr__(name: str): # pragma: no cover22 if name == "_install":23 SetuptoolsDeprecationWarning.emit(24 "`setuptools.command._install` was an internal implementation detail "25 "that was left in for numpy<1.9 support.",26 due_date=(2025, 5, 2), # Originally added on 2024-11-0127 )28 return orig.install29 raise AttributeError(f"module {__name__!r} has no attribute {name!r}")30 31 32class install(orig.install):33 """Use easy_install to install the package, w/dependencies"""34 35 distribution: Distribution # override distutils.dist.Distribution with setuptools.dist.Distribution36 37 user_options = orig.install.user_options + [38 ('old-and-unmanageable', None, "Try not to use this!"),39 (40 'single-version-externally-managed',41 None,42 "used by system package builders to create 'flat' eggs",43 ),44 ]45 boolean_options = orig.install.boolean_options + [46 'old-and-unmanageable',47 'single-version-externally-managed',48 ]49 # Type the same as distutils.command.install.install.sub_commands50 # Must keep the second tuple item potentially None due to invariance51 new_commands: ClassVar[list[tuple[str, Callable[[Any], bool] | None]]] = [52 ('install_egg_info', lambda self: True),53 ('install_scripts', lambda self: True),54 ]55 _nc = dict(new_commands)56 57 def initialize_options(self):58 SetuptoolsDeprecationWarning.emit(59 "setup.py install is deprecated.",60 """61 Please avoid running ``setup.py`` directly.62 Instead, use pypa/build, pypa/installer or other63 standards-based tools.64 """,65 see_url="https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html",66 due_date=(2025, 10, 31),67 )68 69 super().initialize_options()70 self.old_and_unmanageable = None71 self.single_version_externally_managed = None72 73 def finalize_options(self) -> None:74 super().finalize_options()75 if self.root:76 self.single_version_externally_managed = True77 elif self.single_version_externally_managed:78 if not self.root and not self.record:79 raise DistutilsArgError(80 "You must specify --record or --root when building system packages"81 )82 83 def handle_extra_path(self):84 if self.root or self.single_version_externally_managed:85 # explicit backward-compatibility mode, allow extra_path to work86 return orig.install.handle_extra_path(self)87 88 # Ignore extra_path when installing an egg (or being run by another89 # command without --root or --single-version-externally-managed90 self.path_file = None91 self.extra_dirs = ''92 return None93 94 @staticmethod95 def _called_from_setup(run_frame):96 """97 Attempt to detect whether run() was called from setup() or by another98 command. If called by setup(), the parent caller will be the99 'run_command' method in 'distutils.dist', and *its* caller will be100 the 'run_commands' method. If called any other way, the101 immediate caller *might* be 'run_command', but it won't have been102 called by 'run_commands'. Return True in that case or if a call stack103 is unavailable. Return False otherwise.104 """105 if run_frame is None:106 msg = "Call stack not available. bdist_* commands may fail."107 SetuptoolsWarning.emit(msg)108 if platform.python_implementation() == 'IronPython':109 msg = "For best results, pass -X:Frames to enable call stack."110 SetuptoolsWarning.emit(msg)111 return True112 113 frames = inspect.getouterframes(run_frame)114 for frame in frames[2:4]:115 (caller,) = frame[:1]116 info = inspect.getframeinfo(caller)117 caller_module = caller.f_globals.get('__name__', '')118 119 if caller_module == "setuptools.dist" and info.function == "run_command":120 # Starting from v61.0.0 setuptools overwrites dist.run_command121 continue122 123 return caller_module == 'distutils.dist' and info.function == 'run_commands'124 125 return False126 127 128# XXX Python 3.1 doesn't see _nc if this is inside the class129install.sub_commands = [130 cmd for cmd in orig.install.sub_commands if cmd[0] not in install._nc131] + install.new_commands132 