diff --git a/docs/changelog/2284.feature.rst b/docs/changelog/2284.feature.rst new file mode 100644 index 000000000..9f93dba5a --- /dev/null +++ b/docs/changelog/2284.feature.rst @@ -0,0 +1 @@ +Support for creating a virtual environment from a Python 2.7 framework on macOS 12 - by :user:`nickhutchinson`. diff --git a/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py b/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py index 6024c97d1..d64f0d99b 100644 --- a/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py +++ b/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py @@ -25,20 +25,11 @@ class CPythonmacOsFramework(CPython): def can_describe(cls, interpreter): return is_mac_os_framework(interpreter) and super(CPythonmacOsFramework, cls).can_describe(interpreter) - @classmethod - def sources(cls, interpreter): - for src in super(CPythonmacOsFramework, cls).sources(interpreter): - yield src - # add a symlink to the host python image - exe = cls.image_ref(interpreter) - ref = PathRefToDest(exe, dest=lambda self, _: self.dest / ".Python", must=RefMust.SYMLINK) - yield ref - def create(self): super(CPythonmacOsFramework, self).create() # change the install_name of the copied python executables - target = "@executable_path/../.Python" + target = self.desired_mach_o_image_path() current = self.current_mach_o_image_path() for src in self._sources: if isinstance(src, ExePathRefToDest): @@ -62,8 +53,8 @@ def _executables(cls, interpreter): def current_mach_o_image_path(self): raise NotImplementedError - @classmethod - def image_ref(cls, interpreter): + @abstractmethod + def desired_mach_o_image_path(self): raise NotImplementedError @@ -74,13 +65,12 @@ def can_create(cls, interpreter): return super(CPython2macOsFramework, cls).can_create(interpreter) return False - @classmethod - def image_ref(cls, interpreter): - return Path(interpreter.prefix) / "Python" - def current_mach_o_image_path(self): return os.path.join(self.interpreter.prefix, "Python") + def desired_mach_o_image_path(self): + return "@executable_path/../Python" + @classmethod def sources(cls, interpreter): for src in super(CPython2macOsFramework, cls).sources(interpreter): @@ -89,6 +79,14 @@ def sources(cls, interpreter): exec_marker_file, to_path, _ = cls.from_stdlib(cls.mappings(interpreter), "lib-dynload") yield PathRefToDest(exec_marker_file, dest=to_path) + # add a copy of the host python image + exe = Path(interpreter.prefix) / "Python" + yield PathRefToDest(exe, dest=lambda self, _: self.dest / "Python", must=RefMust.COPY) + + # add a symlink to the Resources dir + resources = Path(interpreter.prefix) / "Resources" + yield PathRefToDest(resources, dest=lambda self, _: self.dest / "Resources") + @property def reload_code(self): result = super(CPython2macOsFramework, self).reload_code @@ -147,13 +145,21 @@ def fix_signature(self): class CPython3macOsFramework(CPythonmacOsFramework, CPython3, CPythonPosix): - @classmethod - def image_ref(cls, interpreter): - return Path(interpreter.prefix) / "Python3" - def current_mach_o_image_path(self): return "@executable_path/../../../../Python3" + def desired_mach_o_image_path(self): + return "@executable_path/../.Python" + + @classmethod + def sources(cls, interpreter): + for src in super(CPython3macOsFramework, cls).sources(interpreter): + yield src + + # add a symlink to the host python image + exe = Path(interpreter.prefix) / "Python3" + yield PathRefToDest(exe, dest=lambda self, _: self.dest / ".Python", must=RefMust.SYMLINK) + @property def reload_code(self): result = super(CPython3macOsFramework, self).reload_code