Skip to content
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
23 changes: 15 additions & 8 deletions Lib/compileall.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,15 @@ def compile_dir(dir, maxlevels=None, ddir=None, force=False,
files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels)
success = True
if workers != 1 and ProcessPoolExecutor is not None:
import multiprocessing
if multiprocessing.get_start_method() == 'fork':
mp_context = multiprocessing.get_context('forkserver')
else:
mp_context = None
# If workers == 0, let ProcessPoolExecutor choose
workers = workers or None
with ProcessPoolExecutor(max_workers=workers) as executor:
with ProcessPoolExecutor(max_workers=workers,
mp_context=mp_context) as executor:
results = executor.map(partial(compile_file,
ddir=ddir, force=force,
rx=rx, quiet=quiet,
Expand All @@ -110,7 +116,8 @@ def compile_dir(dir, maxlevels=None, ddir=None, force=False,
prependdir=prependdir,
limit_sl_dest=limit_sl_dest,
hardlink_dupes=hardlink_dupes),
files)
files,
chunksize=4)
success = min(results, default=True)
else:
for file in files:
Expand Down Expand Up @@ -166,13 +173,13 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
if stripdir is not None:
fullname_parts = fullname.split(os.path.sep)
stripdir_parts = stripdir.split(os.path.sep)
ddir_parts = list(fullname_parts)

for spart, opart in zip(stripdir_parts, fullname_parts):
if spart == opart:
ddir_parts.remove(spart)

dfile = os.path.join(*ddir_parts)
if stripdir_parts != fullname_parts[:len(stripdir_parts)]:
if quiet < 2:
print("The stripdir path {!r} is not a valid prefix for "
"source path {!r}; ignoring".format(stripdir, fullname))
else:
dfile = os.path.join(*fullname_parts[len(stripdir_parts):])

if prependdir is not None:
if dfile is None:
Expand Down
24 changes: 24 additions & 0 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2601,6 +2601,30 @@ def adjust_int_max_str_digits(max_digits):
'skipped on s390x')
HAVE_ASAN_FORK_BUG = check_sanitizer(address=True)

# From Cpython 3.13.5
@contextlib.contextmanager
def no_color():
import _colorize
from .os_helper import EnvironmentVarGuard

with (
swap_attr(_colorize, "can_colorize", lambda file=None: False),
EnvironmentVarGuard() as env,
):
env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS")
env.set("NO_COLOR", "1")
yield

# From Cpython 3.13.5
def force_not_colorized(func):
"""Force the terminal not to be colorized."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
with no_color():
return func(*args, **kwargs)
return wrapper


# From python 3.12.8
class BrokenIter:
def __init__(self, init_raises=False, next_raises=False, iter_raises=False):
Expand Down
30 changes: 28 additions & 2 deletions Lib/test/support/os_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import unittest
import warnings

# From CPython 3.13.5
from test import support


# Filename used for testing
TESTFN_ASCII = '@test'
Expand Down Expand Up @@ -196,6 +199,26 @@ def skip_unless_symlink(test):
return test if ok else unittest.skip(msg)(test)


# From CPython 3.13.5
_can_hardlink = None

# From CPython 3.13.5
def can_hardlink():
global _can_hardlink
if _can_hardlink is None:
# Android blocks hard links using SELinux
# (https://stackoverflow.com/q/32365690).
_can_hardlink = hasattr(os, "link") and not support.is_android
return _can_hardlink


# From CPython 3.13.5
def skip_unless_hardlink(test):
ok = can_hardlink()
msg = "requires hardlink support"
return test if ok else unittest.skip(msg)(test)


_can_xattr = None


Expand Down Expand Up @@ -699,8 +722,11 @@ def __len__(self):
def set(self, envvar, value):
self[envvar] = value

def unset(self, envvar):
del self[envvar]
# From CPython 3.13.5
def unset(self, envvar, /, *envvars):
"""Unset one or more environment variables."""
for ev in (envvar, *envvars):
del self[ev]

def copy(self):
# We do what os.environ.copy() does.
Expand Down
Loading
Loading