Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Installation test always fails on native Windows #1651

Closed
@EliahKagan

Description

GitPython supports and can be installed on native Windows systems (not just Cygwin), but the TestInstallation.test_installation test in test/test_installation.py always fails with a FileNotFoundError. This is not caught on CI because, for Windows, only Cygwin currently has CI coverage. The test failure happens for two reasons:

  • The test relies on the virtual environment having a bin directory, but on Windows this is called Scripts. This is the immediate cause of the error, but if only this is fixed, a second, closely related incompatibility will cause the test to fail.
  • The test relies on the virtual environment having python3 and pip3 commands, but Windows does not have these in virtual environments. Python virtual environments on all systems have python and pip commands (even on systems such as Debian and Ubuntu where those commands are not available globally or whose global versions are part of a legacy Python 2 installation).

The following output is produced on Windows 10 using Python 3.11.5, installing GitPython from the tip of the main branch (c8e303f), but I believe the test would fail on all Windows systems with all versions of Python in the same way:

(.venv) C:\Users\ek\source\repos\GitPython [main ≡]> pytest --no-cov -k test_installation
Test session starts (platform: win32, Python 3.11.5, pytest 7.4.2, pytest-sugar 0.9.7)
rootdir: C:\Users\ek\source\repos\GitPython
configfile: pyproject.toml
testpaths: test
plugins: cov-4.1.0, sugar-0.9.7
collected 504 items / 503 deselected / 1 selected
――――――――――――――――――――――――――――――――――――――――― TestInstallation.test_installation ――――――――――――――――――――――――――――――――――――――――――
self = <test.test_installation.TestInstallation testMethod=test_installation>
rw_dir = 'C:\\Users\\ek\\AppData\\Local\\Temp\\test_installatione9rg39ma'
 @with_rw_directory
 def test_installation(self, rw_dir):
 self.setUp_venv(rw_dir)
> result = subprocess.run(
 [self.pip, "install", "-r", "requirements.txt"],
 stdout=subprocess.PIPE,
 cwd=self.sources,
 )
test\test_installation.py:24:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1520.0_x64__qbz5n2kfra8p0\Lib\subprocess.py:548: in run
 with Popen(*popenargs, **kwargs) as process:
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1520.0_x64__qbz5n2kfra8p0\Lib\subprocess.py:1026: in __init__
 self._execute_child(args, executable, preexec_fn, close_fds,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <Popen: returncode: None args: ['C:\\Users\\ek\\AppData\\Local\\Temp\\test_i...>
args = 'C:\\Users\\ek\\AppData\\Local\\Temp\\test_installatione9rg39ma\\bin/pip3 install -r requirements.txt'
executable = None, preexec_fn = None, close_fds = False, pass_fds = ()
cwd = 'C:\\Users\\ek\\AppData\\Local\\Temp\\test_installatione9rg39ma\\src', env = None
startupinfo = <subprocess.STARTUPINFO object at 0x000001B4D625B390>, creationflags = 0, shell = False
p2cread = Handle(1292), p2cwrite = -1, c2pread = 15, c2pwrite = Handle(1396), errread = -1, errwrite = Handle(1416)
unused_restore_signals = True, unused_gid = None, unused_gids = None, unused_uid = None, unused_umask = -1
unused_start_new_session = False, unused_process_group = -1
 def _execute_child(self, args, executable, preexec_fn, close_fds,
 pass_fds, cwd, env,
 startupinfo, creationflags, shell,
 p2cread, p2cwrite,
 c2pread, c2pwrite,
 errread, errwrite,
 unused_restore_signals,
 unused_gid, unused_gids, unused_uid,
 unused_umask,
 unused_start_new_session, unused_process_group):
 """Execute program (MS Windows version)"""
 assert not pass_fds, "pass_fds not supported on Windows."
 if isinstance(args, str):
 pass
 elif isinstance(args, bytes):
 if shell:
 raise TypeError('bytes args is not allowed on Windows')
 args = list2cmdline([args])
 elif isinstance(args, os.PathLike):
 if shell:
 raise TypeError('path-like args is not allowed when '
 'shell is true')
 args = list2cmdline([args])
 else:
 args = list2cmdline(args)
 if executable is not None:
 executable = os.fsdecode(executable)
 # Process startup details
 if startupinfo is None:
 startupinfo = STARTUPINFO()
 else:
 # bpo-34044: Copy STARTUPINFO since it is modified above,
 # so the caller can reuse it multiple times.
 startupinfo = startupinfo.copy()
 use_std_handles = -1 not in (p2cread, c2pwrite, errwrite)
 if use_std_handles:
 startupinfo.dwFlags |= _winapi.STARTF_USESTDHANDLES
 startupinfo.hStdInput = p2cread
 startupinfo.hStdOutput = c2pwrite
 startupinfo.hStdError = errwrite
 attribute_list = startupinfo.lpAttributeList
 have_handle_list = bool(attribute_list and
 "handle_list" in attribute_list and
 attribute_list["handle_list"])
 # If we were given an handle_list or need to create one
 if have_handle_list or (use_std_handles and close_fds):
 if attribute_list is None:
 attribute_list = startupinfo.lpAttributeList = {}
 handle_list = attribute_list["handle_list"] = \
 list(attribute_list.get("handle_list", []))
 if use_std_handles:
 handle_list += [int(p2cread), int(c2pwrite), int(errwrite)]
 handle_list[:] = self._filter_handle_list(handle_list)
 if handle_list:
 if not close_fds:
 warnings.warn("startupinfo.lpAttributeList['handle_list'] "
 "overriding close_fds", RuntimeWarning)
 # When using the handle_list we always request to inherit
 # handles but the only handles that will be inherited are
 # the ones in the handle_list
 close_fds = False
 if shell:
 startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW
 startupinfo.wShowWindow = _winapi.SW_HIDE
 if not executable:
 # gh-101283: without a fully-qualified path, before Windows
 # checks the system directories, it first looks in the
 # application directory, and also the current directory if
 # NeedCurrentDirectoryForExePathW(ExeName) is true, so try
 # to avoid executing unqualified "cmd.exe".
 comspec = os.environ.get('ComSpec')
 if not comspec:
 system_root = os.environ.get('SystemRoot', '')
 comspec = os.path.join(system_root, 'System32', 'cmd.exe')
 if not os.path.isabs(comspec):
 raise FileNotFoundError('shell not found: neither %ComSpec% nor %SystemRoot% is set')
 if os.path.isabs(comspec):
 executable = comspec
 else:
 comspec = executable
 args = '{} /c "{}"'.format (comspec, args)
 if cwd is not None:
 cwd = os.fsdecode(cwd)
 sys.audit("subprocess.Popen", executable, args, cwd, env)
 # Start the process
 try:
> hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
 # no special security
 None, None,
 int(not close_fds),
 creationflags,
 env,
 cwd,
 startupinfo)
E FileNotFoundError: [WinError 2] The system cannot find the file specified
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.1520.0_x64__qbz5n2kfra8p0\Lib\subprocess.py:1538: FileNotFoundError
 test/test_installation.py ⨯ 100% ██████████
=============================================== short test summary info ===============================================
FAILED test/test_installation.py::TestInstallation::test_installation - FileNotFoundError: [WinError 2] The system cannot find the file specified
Results (7.00s):
 1 failed
 - test/test_installation.py:21 TestInstallation.test_installation
 503 deselected

I have also verified that this occurs on Python 3.12.0rc2 on Windows. #1640 affects Windows as much as other systems, but this specific issue causes the test to fail first.

I think it would make sense to fix this together with #1640, since a fix for that would include related changes to test_installation. I've opened #1654 for this (which also fixes #1652 and #1653).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /