Skip to content

Commit f1fbba3

Browse files
committed
gh-149879: Fix test_embed on Cygwin
1 parent a5be25d commit f1fbba3

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

Lib/test/test_embed.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,27 @@ def debug_build(program):
7474
return name.casefold().endswith("_d".casefold())
7575

7676

77+
def getpath_which(program_name):
78+
if sys.platform != 'cygwin':
79+
return shutil.which(program_name)
80+
81+
# shutil.which() checks for os.access(fn, os.F_OK | os.X_OK), whereas
82+
# getpath.isxfile() doesn't. The difference matters on Cygwin.
83+
import stat
84+
def isxfile(fn):
85+
try:
86+
st = os.stat(fn)
87+
except OSError:
88+
return False
89+
return stat.S_ISREG(st.st_mode)
90+
91+
for p in os.environ['PATH'].split(':'):
92+
p = os.path.join(p, program_name)
93+
if isxfile(p):
94+
return p
95+
return None
96+
97+
7798
def remove_python_envvars():
7899
env = dict(os.environ)
79100
# Remove PYTHON* environment variables to get deterministic environment
@@ -92,6 +113,8 @@ def setUp(self):
92113
exename += ext
93114
exepath = builddir
94115
else:
116+
if sys.platform == 'cygwin':
117+
exename += '.exe'
95118
exepath = os.path.join(builddir, 'Programs')
96119
self.test_exe = exe = os.path.join(exepath, exename)
97120
if not os.path.exists(exe):
@@ -328,6 +351,8 @@ def test_pre_initialization_api(self):
328351
expected_path = self.test_exe
329352
else:
330353
expected_path = os.path.join(os.getcwd(), "_testembed")
354+
if sys.platform == 'cygwin':
355+
expected_path += '.exe'
331356
expected_output = f"sys.executable: {expected_path}\n"
332357
self.assertIn(expected_output, out)
333358
self.assertEqual(err, '')
@@ -872,12 +897,16 @@ def get_expected_config(self, expected_preconfig, expected,
872897
default_executable = os.path.abspath(expected['program_name'])
873898
else:
874899
default_executable = os.path.join(os.getcwd(), '_testembed')
900+
if sys.platform == 'cygwin':
901+
default_executable += '.exe'
875902
if expected['executable'] is self.GET_DEFAULT_CONFIG:
876903
expected['executable'] = default_executable
877904
if expected['base_executable'] is self.GET_DEFAULT_CONFIG:
878905
expected['base_executable'] = default_executable
879906
if expected['program_name'] is self.GET_DEFAULT_CONFIG:
880907
expected['program_name'] = './_testembed'
908+
if sys.platform == 'cygwin':
909+
expected['program_name'] += '.exe'
881910

882911
config = configs['config']
883912
for key, value in expected.items():
@@ -1370,7 +1399,7 @@ def default_program_name(self, config):
13701399
if MACOS:
13711400
executable = self.test_exe
13721401
else:
1373-
executable = shutil.which(program_name) or ''
1402+
executable = getpath_which(program_name) or ''
13741403
config.update({
13751404
'program_name': program_name,
13761405
'base_executable': executable,
@@ -1469,6 +1498,12 @@ def tmpdir_with_python(self, subdir=None):
14691498
shutil.copystat(self.test_exe, exec_copy)
14701499
self.test_exe = exec_copy
14711500

1501+
if sys.platform == "cygwin":
1502+
exe_path = os.path.dirname(sys.executable)
1503+
libpython_dll = sysconfig.get_config_var('DLLLIBRARY')
1504+
shutil.copy2(os.path.join(exe_path, libpython_dll),
1505+
os.path.join(tmpdir, libpython_dll))
1506+
14721507
yield tmpdir
14731508

14741509
def test_init_setpythonhome(self):

Programs/_testembed.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,13 @@ char **main_argv;
4141
#define PROGRAM "test_embed"
4242

4343
/* Use path starting with "./" avoids a search along the PATH */
44-
#define PROGRAM_NAME L"./_testembed"
45-
#define PROGRAM_NAME_UTF8 "./_testembed"
44+
#ifdef __CYGWIN__
45+
# define PROGRAM_NAME L"./_testembed.exe"
46+
# define PROGRAM_NAME_UTF8 "./_testembed.exe"
47+
#else
48+
# define PROGRAM_NAME L"./_testembed"
49+
# define PROGRAM_NAME_UTF8 "./_testembed"
50+
#endif
4651

4752
#define INIT_LOOPS 4
4853

0 commit comments

Comments
 (0)