Repository: pypa/virtualenv

Issue:
PermissionError creating Python 2.x virtualenvs on macOS 12.x arm64
**Issue**

Once #2269 is surmounted a further error occurs, a `PermissionError` exception is raised when `CPython2macOsArmFramework.fix_signature() attempts to call `Path.unlink()` on the directory `bk`.

Instead, I believe `Path.rmdir()` should be used. PR incoming.

**Environment**

Provide at least:
- OS: macOS 12.1, arm64
- ``pip list`` of the host python where ``virtualenv`` is installed:

  ```console
  $ .tox/py39/bin/pip list
  Package                           Version
  --------------------------------- ---------------------
  attrs                             21.2.0
  backports.entry-points-selectable 1.1.1
  coverage                          6.2
  coverage-enable-subprocess        1.0
  distlib                           0.3.4
  filelock                          3.4.0
  flaky                             3.7.0
  freezegun                         1.1.0
  importlib-metadata                4.10.0
  iniconfig                         1.1.1
  packaging                         21.3
  pip                               21.3.1
  platformdirs                      2.4.0
  pluggy                            1.0.0
  py                                1.11.0
  pyparsing                         3.0.6
  pytest                            6.2.5
  pytest-env                        0.6.2
  pytest-freezegun                  0.4.2
  pytest-mock                       3.6.1
  pytest-randomly                   3.10.3
  pytest-timeout                    2.0.2
  python-dateutil                   2.8.2
  setuptools                        59.2.0
  six                               1.16.0
  toml                              0.10.2
  virtualenv                        20.12.1.dev2+gd8cc529
  wheel                             0.37.0
  zipp                              3.6.0
  ```

**Output of the virtual environment creation**

Make sure to run the creation with `-vvv --with-traceback`:

```console
$ .tox/py39/bin/python -mvirtualenv --python python2 -vvv --with-traceback v27
26 setup logging to NOTSET [DEBUG report:39]
30 find interpreter for spec PythonSpec(implementation=CPython, major=2) [INFO builtin:62]
30 discover exe for PythonInfo(spec=CPython3.9.9.final.0-64, exe=/Users/alex/src/virtualenv/.tox/py39/bin/python, platform=darwin, version='3.9.9 (main, Nov 21 2021, 03:16:13) \n[Clang 13.0.0 (clang-1300.0.29.3)]', encoding_fs_io=utf-8-utf-8) in /opt/homebrew/opt/python@3.9/Frameworks/Python.framework/Versions/3.9 [DEBUG py_info:403]
31 filesystem is not case-sensitive [DEBUG info:29]
31 Attempting to acquire lock 4318320000 on /Users/alex/Library/Application Support/virtualenv/py_info/1/345aa2f3f3153332aa0250f3057c4206b814c74c10594863073df44855256fe2.lock [DEBUG _api:165]
31 Lock 4318320000 acquired on /Users/alex/Library/Application Support/virtualenv/py_info/1/345aa2f3f3153332aa0250f3057c4206b814c74c10594863073df44855256fe2.lock [DEBUG _api:169]
31 got python info of /opt/homebrew/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/bin/python3.9 from /Users/alex/Library/Application Support/virtualenv/py_info/1/345aa2f3f3153332aa0250f3057c4206b814c74c10594863073df44855256fe2.json [DEBUG via_disk_folder:135]
32 Attempting to release lock 4318320000 on /Users/alex/Library/Application Support/virtualenv/py_info/1/345aa2f3f3153332aa0250f3057c4206b814c74c10594863073df44855256fe2.lock [DEBUG _api:199]
32 Lock 4318320000 released on /Users/alex/Library/Application Support/virtualenv/py_info/1/345aa2f3f3153332aa0250f3057c4206b814c74c10594863073df44855256fe2.lock [DEBUG _api:202]
32 Attempting to acquire lock 4318320720 on /Users/alex/Library/Application Support/virtualenv/py_info/1/50292dbb1f747f7151d445135d392af3138fb3c65386d17d9510cb605222b10b.lock [DEBUG _api:165]
32 Lock 4318320720 acquired on /Users/alex/Library/Application Support/virtualenv/py_info/1/50292dbb1f747f7151d445135d392af3138fb3c65386d17d9510cb605222b10b.lock [DEBUG _api:169]
32 got python info of /opt/homebrew/opt/python@3.9/bin/python3.9 from /Users/alex/Library/Application Support/virtualenv/py_info/1/50292dbb1f747f7151d445135d392af3138fb3c65386d17d9510cb605222b10b.json [DEBUG via_disk_folder:135]
32 Attempting to release lock 4318320720 on /Users/alex/Library/Application Support/virtualenv/py_info/1/50292dbb1f747f7151d445135d392af3138fb3c65386d17d9510cb605222b10b.lock [DEBUG _api:199]
32 Lock 4318320720 released on /Users/alex/Library/Application Support/virtualenv/py_info/1/50292dbb1f747f7151d445135d392af3138fb3c65386d17d9510cb605222b10b.lock [DEBUG _api:202]
32 proposed PythonInfo(spec=CPython3.9.9.final.0-64, system=/opt/homebrew/opt/python@3.9/bin/python3.9, exe=/Users/alex/src/virtualenv/.tox/py39/bin/python, platform=darwin, version='3.9.9 (main, Nov 21 2021, 03:16:13) \n[Clang 13.0.0 (clang-1300.0.29.3)]', encoding_fs_io=utf-8-utf-8) [INFO builtin:69]
32 discover PATH[0]=/opt/homebrew/bin [DEBUG builtin:114]
32 discover PATH[1]=/opt/homebrew/sbin [DEBUG builtin:114]
32 discover PATH[2]=/usr/local/bin [DEBUG builtin:114]
33 discover PATH[3]=/usr/bin [DEBUG builtin:114]
33 Attempting to acquire lock 4318208064 on /Users/alex/Library/Application Support/virtualenv/py_info/1/f92b2924b84ff19c1c3dc485f7644d4486f64738191026bf8e6de303969141b5.lock [DEBUG _api:165]
33 Lock 4318208064 acquired on /Users/alex/Library/Application Support/virtualenv/py_info/1/f92b2924b84ff19c1c3dc485f7644d4486f64738191026bf8e6de303969141b5.lock [DEBUG _api:169]
33 got python info of /usr/bin/python2 from /Users/alex/Library/Application Support/virtualenv/py_info/1/f92b2924b84ff19c1c3dc485f7644d4486f64738191026bf8e6de303969141b5.json [DEBUG via_disk_folder:135]
33 Attempting to release lock 4318208064 on /Users/alex/Library/Application Support/virtualenv/py_info/1/f92b2924b84ff19c1c3dc485f7644d4486f64738191026bf8e6de303969141b5.lock [DEBUG _api:199]
33 Lock 4318208064 released on /Users/alex/Library/Application Support/virtualenv/py_info/1/f92b2924b84ff19c1c3dc485f7644d4486f64738191026bf8e6de303969141b5.lock [DEBUG _api:202]
34 Attempting to acquire lock 4318210080 on /Users/alex/Library/Application Support/virtualenv/py_info/1/545e036c4b32438aced1f6b3c8d38ca151d9c36189e05839cb0aa568fda70ddd.lock [DEBUG _api:165]
34 Lock 4318210080 acquired on /Users/alex/Library/Application Support/virtualenv/py_info/1/545e036c4b32438aced1f6b3c8d38ca151d9c36189e05839cb0aa568fda70ddd.lock [DEBUG _api:169]
34 got python info of /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python from /Users/alex/Library/Application Support/virtualenv/py_info/1/545e036c4b32438aced1f6b3c8d38ca151d9c36189e05839cb0aa568fda70ddd.json [DEBUG via_disk_folder:135]
34 Attempting to release lock 4318210080 on /Users/alex/Library/Application Support/virtualenv/py_info/1/545e036c4b32438aced1f6b3c8d38ca151d9c36189e05839cb0aa568fda70ddd.lock [DEBUG _api:199]
34 Lock 4318210080 released on /Users/alex/Library/Application Support/virtualenv/py_info/1/545e036c4b32438aced1f6b3c8d38ca151d9c36189e05839cb0aa568fda70ddd.lock [DEBUG _api:202]
34 proposed PathPythonInfo(spec=CPython2.7.18.final.0-64, system=/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python, exe=/usr/bin/python2, platform=darwin, version='2.7.18 (default, Nov 13 2021, 06:17:34) \n[GCC Apple LLVM 13.0.0 (clang-1300.0.29.10) [+internal-os, ptrauth-isa=deployme', encoding_fs_io=utf-8-utf-8) [INFO builtin:69]
34 accepted PathPythonInfo(spec=CPython2.7.18.final.0-64, system=/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python, exe=/usr/bin/python2, platform=darwin, version='2.7.18 (default, Nov 13 2021, 06:17:34) \n[GCC Apple LLVM 13.0.0 (clang-1300.0.29.10) [+internal-os, ptrauth-isa=deployme', encoding_fs_io=utf-8-utf-8) [DEBUG builtin:71]
49 create virtual environment via CPython2macOsArmFramework(dest=/Users/alex/src/virtualenv/v27, clear=False, no_vcs_ignore=False, global=False) [INFO session:52]
49 create folder /Users/alex/src/virtualenv/v27/bin [DEBUG _sync:24]
49 create folder /Users/alex/src/virtualenv/v27/include [DEBUG _sync:24]
49 create folder /Users/alex/src/virtualenv/v27/lib/python2.7/site-packages [DEBUG _sync:24]
50 write /Users/alex/src/virtualenv/v27/pyvenv.cfg [DEBUG pyenv_cfg:34]
50      home = /System/Library/Frameworks/Python.framework/Versions/2.7 [DEBUG pyenv_cfg:38]
50      implementation = CPython [DEBUG pyenv_cfg:38]
50      version_info = 2.7.18.final.0 [DEBUG pyenv_cfg:38]
50      virtualenv = 20.12.1.dev2+gd8cc529 [DEBUG pyenv_cfg:38]
50      include-system-site-packages = false [DEBUG pyenv_cfg:38]
50      base-prefix = /System/Library/Frameworks/Python.framework/Versions/2.7 [DEBUG pyenv_cfg:38]
50      base-exec-prefix = /System/Library/Frameworks/Python.framework/Versions/2.7 [DEBUG pyenv_cfg:38]
50      base-executable = /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python [DEBUG pyenv_cfg:38]
50 copy /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python to /Users/alex/src/virtualenv/v27/bin/python [DEBUG _sync:51]
50 symlink /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py to /Users/alex/src/virtualenv/v27/lib/python2.7/os.py [DEBUG _sync:43]
50 symlink /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc to /Users/alex/src/virtualenv/v27/lib/python2.7/os.pyc [DEBUG _sync:43]
50 symlink directory /System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 to /Users/alex/src/virtualenv/v27/include/python2.7 [DEBUG _sync:43]
50 symlink /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config/Makefile to /Users/alex/src/virtualenv/v27/lib/python2.7/config/Makefile [DEBUG _sync:43]
51 symlink /System/Library/Frameworks/Python.framework/Versions/2.7/Python to /Users/alex/src/virtualenv/v27/.Python [DEBUG _sync:43]
51 symlink directory /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload to /Users/alex/src/virtualenv/v27/lib/python2.7/lib-dynload [DEBUG _sync:43]
51 create virtualenv import hook file /Users/alex/src/virtualenv/v27/lib/python2.7/site-packages/_virtualenv.pth [DEBUG api:95]
51 create /Users/alex/src/virtualenv/v27/lib/python2.7/site-packages/_virtualenv.py [DEBUG api:98]
51 change Mach-O for /Users/alex/src/virtualenv/v27/bin/python from /System/Library/Frameworks/Python.framework/Versions/2.7/Python to @executable_path/../.Python [DEBUG mac_os:201]
52 Changing signature of copied python exe /Users/alex/src/virtualenv/v27/bin/python [DEBUG mac_os:132]
56 Could not change MacOS code signing on copied python exe at /Users/alex/src/virtualenv/v27/bin/python [CRITICAL mac_os:144]
Traceback (most recent call last):
  File "/opt/homebrew/Cellar/python@3.9/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/homebrew/Cellar/python@3.9/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/__main__.py", line 80, in <module>
    run_with_catch()  # pragma: no cov
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/__main__.py", line 65, in run_with_catch
    run(args, options, env)
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/__main__.py", line 18, in run
    session = cli_run(args, options, env)
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/run/__init__.py", line 32, in cli_run
    of_session.run()
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/run/session.py", line 46, in run
    self._create()
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/run/session.py", line 53, in _create
    self.creator.run()
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/create/creator.py", line 171, in run
    self.create()
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py", line 122, in create
    self.fix_signature()
  File "/Users/alex/src/virtualenv/.tox/py39/lib/python3.9/site-packages/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py", line 139, in fix_signature
    bak_dir.unlink()
  File "/opt/homebrew/Cellar/python@3.9/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/pathlib.py", line 1354, in unlink
    self._accessor.unlink(self)
PermissionError: [Errno 1] Operation not permitted: '/Users/alex/src/virtualenv/v27/bin/bk'
```



Discussion:

Resolving patch:
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
--- a/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py
+++ b/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py
@@ -70,7 +70,9 @@ def image_ref(cls, interpreter):
 class CPython2macOsFramework(CPythonmacOsFramework, CPython2PosixBase):
     @classmethod
     def can_create(cls, interpreter):
-        return not IS_MAC_ARM64 and super(CPython2macOsFramework, cls).can_describe(interpreter)
+        if not IS_MAC_ARM64 and super(CPython2macOsFramework, cls).can_describe(interpreter):
+            return super(CPython2macOsFramework, cls).can_create(interpreter)
+        return False
 
     @classmethod
     def image_ref(cls, interpreter):
@@ -111,7 +113,9 @@ def reload_code(self):
 class CPython2macOsArmFramework(CPython2macOsFramework, CPythonmacOsFramework, CPython2PosixBase):
     @classmethod
     def can_create(cls, interpreter):
-        return IS_MAC_ARM64 and super(CPythonmacOsFramework, cls).can_describe(interpreter)
+        if IS_MAC_ARM64 and super(CPythonmacOsFramework, cls).can_describe(interpreter):
+            return super(CPythonmacOsFramework, cls).can_create(interpreter)
+        return False
 
     def create(self):
         super(CPython2macOsFramework, self).create()
@@ -132,7 +136,7 @@ def fix_signature(self):
             bak_dir.mkdir(parents=True, exist_ok=True)
             subprocess.check_call(["cp", exe, bak_dir])
             subprocess.check_call(["mv", bak_dir / exe.name, exe])
-            bak_dir.unlink()
+            bak_dir.rmdir()
             cmd = ["codesign", "-s", "-", "--preserve-metadata=identifier,entitlements,flags,runtime", "-f", exe]
             logging.debug("Changing Signature: %s", cmd)
             subprocess.check_call(cmd)


Test patch: