Skip to content

[3.12] gh-109615: Fix test_tools.test_freeze SRCDIR (#109935) #109950

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Lib/test/libregrtest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ def set_temp_dir(self):
if sysconfig.is_python_build():
self.tmp_dir = sysconfig.get_config_var('abs_builddir')
if self.tmp_dir is None:
# bpo-30284: On Windows, only srcdir is available. Using
# gh-74470: On Windows, only srcdir is available. Using
# abs_builddir mostly matters on UNIX when building Python
# out of the source tree, especially when the source tree
# is read only.
Expand Down
26 changes: 26 additions & 0 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2539,3 +2539,29 @@ def adjust_int_max_str_digits(max_digits):
#Windows doesn't have os.uname() but it doesn't support s390x.
skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x',
'skipped on s390x')

_BASE_COPY_SRC_DIR_IGNORED_NAMES = frozenset({
# SRC_DIR/.git
'.git',
# ignore all __pycache__/ sub-directories
'__pycache__',
})

# Ignore function for shutil.copytree() to copy the Python source code.
def copy_python_src_ignore(path, names):
ignored = _BASE_COPY_SRC_DIR_IGNORED_NAMES
if os.path.basename(path) == 'Doc':
ignored |= {
# SRC_DIR/Doc/build/
'build',
# SRC_DIR/Doc/venv/
'venv',
}

# check if we are at the root of the source code
elif 'Modules' in names:
ignored |= {
# SRC_DIR/build/
'build',
}
return ignored
22 changes: 22 additions & 0 deletions Lib/test/test_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import stat
import subprocess
import sys
import sysconfig
import tempfile
import textwrap
import unittest
Expand Down Expand Up @@ -765,6 +766,27 @@ def recursive_function(depth):

#self.assertEqual(available, 2)

def test_copy_python_src_ignore(self):
src_dir = sysconfig.get_config_var('srcdir')
src_dir = os.path.abspath(src_dir)

ignored = {'.git', '__pycache__'}

# Source code directory
names = os.listdir(src_dir)
self.assertEqual(support.copy_python_src_ignore(src_dir, names),
ignored | {'build'})

# Doc/ directory
path = os.path.join(src_dir, 'Doc')
self.assertEqual(support.copy_python_src_ignore(path, os.listdir(path)),
ignored | {'build', 'venv'})

# An other directory
path = os.path.join(src_dir, 'Objects')
self.assertEqual(support.copy_python_src_ignore(path, os.listdir(path)),
ignored)

# XXX -follows a list of untested API
# make_legacy_pyc
# is_resource_enabled
Expand Down
6 changes: 4 additions & 2 deletions Lib/test/test_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
skip_if_broken_multiprocessing_synchronize, verbose,
requires_subprocess, is_emscripten, is_wasi,
requires_venv_with_pip, TEST_HOME_DIR,
requires_resource)
requires_resource, copy_python_src_ignore)
from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree)
import unittest
import venv
Expand Down Expand Up @@ -561,6 +561,7 @@ def test_zippath_from_non_installed_posix(self):
platlibdir,
stdlib_zip)
additional_pythonpath_for_non_installed = []

# Copy stdlib files to the non-installed python so venv can
# correctly calculate the prefix.
for eachpath in sys.path:
Expand All @@ -577,7 +578,8 @@ def test_zippath_from_non_installed_posix(self):
if os.path.isfile(fn):
shutil.copy(fn, libdir)
elif os.path.isdir(fn):
shutil.copytree(fn, os.path.join(libdir, name))
shutil.copytree(fn, os.path.join(libdir, name),
ignore=copy_python_src_ignore)
else:
additional_pythonpath_for_non_installed.append(
eachpath)
Expand Down
54 changes: 7 additions & 47 deletions Tools/freeze/test/freeze.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import os
import os.path
import re
import shlex
import shutil
import subprocess
import sysconfig
from test import support


TESTS_DIR = os.path.dirname(__file__)
TOOL_ROOT = os.path.dirname(TESTS_DIR)
SRCDIR = os.path.dirname(os.path.dirname(TOOL_ROOT))
SRCDIR = os.path.abspath(sysconfig.get_config_var('srcdir'))

MAKE = shutil.which('make')
FREEZE = os.path.join(TOOL_ROOT, 'freeze.py')
Expand Down Expand Up @@ -75,56 +76,17 @@ def ensure_opt(args, name, value):


def copy_source_tree(newroot, oldroot):
print(f'copying the source tree into {newroot}...')
print(f'copying the source tree from {oldroot} to {newroot}...')
if os.path.exists(newroot):
if newroot == SRCDIR:
raise Exception('this probably isn\'t what you wanted')
shutil.rmtree(newroot)

def ignore_non_src(src, names):
"""Turns what could be a 1000M copy into a 100M copy."""
# Don't copy the ~600M+ of needless git repo metadata.
# source only, ignore cached .pyc files.
subdirs_to_skip = {'.git', '__pycache__'}
if os.path.basename(src) == 'Doc':
# Another potential ~250M+ of non test related data.
subdirs_to_skip.add('build')
subdirs_to_skip.add('venv')
return subdirs_to_skip

shutil.copytree(oldroot, newroot, ignore=ignore_non_src)
shutil.copytree(oldroot, newroot, ignore=support.copy_python_src_ignore)
if os.path.exists(os.path.join(newroot, 'Makefile')):
_run_quiet([MAKE, 'clean'], newroot)


def get_makefile_var(builddir, name):
regex = re.compile(rf'^{name} *=\s*(.*?)\s*$')
filename = os.path.join(builddir, 'Makefile')
try:
infile = open(filename, encoding='utf-8')
except FileNotFoundError:
return None
with infile:
for line in infile:
m = regex.match(line)
if m:
value, = m.groups()
return value or ''
return None


def get_config_var(builddir, name):
python = os.path.join(builddir, 'python')
if os.path.isfile(python):
cmd = [python, '-c',
f'import sysconfig; print(sysconfig.get_config_var("{name}"))']
try:
return _run_stdout(cmd)
except subprocess.CalledProcessError:
pass
return get_makefile_var(builddir, name)


##################################
# freezing

Expand All @@ -151,10 +113,8 @@ def prepare(script=None, outdir=None):

# Run configure.
print(f'configuring python in {builddir}...')
cmd = [
os.path.join(srcdir, 'configure'),
*shlex.split(get_config_var(SRCDIR, 'CONFIG_ARGS') or ''),
]
config_args = shlex.split(sysconfig.get_config_var('CONFIG_ARGS') or '')
cmd = [os.path.join(srcdir, 'configure'), *config_args]
ensure_opt(cmd, 'cache-file', os.path.join(outdir, 'python-config.cache'))
prefix = os.path.join(outdir, 'python-installation')
ensure_opt(cmd, 'prefix', prefix)
Expand Down