Skip to content

Commit 14681c1

Browse files
authored
Merge branch 'main' into int_freelist
2 parents 19f64f6 + ba2d2fd commit 14681c1

File tree

8 files changed

+74
-72
lines changed

8 files changed

+74
-72
lines changed

Doc/library/traceback.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ Module-Level Functions
274274
:class:`!TracebackException` objects are created from actual exceptions to
275275
capture data for later printing. They offer a more lightweight method of
276276
storing this information by avoiding holding references to
277-
:ref:`traceback<traceback-objects>` and :ref:`frame<frame-objects>` objects
277+
:ref:`traceback<traceback-objects>` and :ref:`frame<frame-objects>` objects.
278278
In addition, they expose more options to configure the output compared to
279279
the module-level functions described above.
280280

Lib/_colorize.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ def get_colors(colorize: bool = False) -> ANSIColors:
3232

3333

3434
def can_colorize() -> bool:
35+
if sys.platform == "win32":
36+
try:
37+
import nt
38+
39+
if not nt._supports_virtual_terminal():
40+
return False
41+
except (ImportError, AttributeError):
42+
return False
3543
if not sys.flags.ignore_environment:
3644
if os.environ.get("PYTHON_COLORS") == "0":
3745
return False
@@ -50,15 +58,6 @@ def can_colorize() -> bool:
5058
if not hasattr(sys.stderr, "fileno"):
5159
return False
5260

53-
if sys.platform == "win32":
54-
try:
55-
import nt
56-
57-
if not nt._supports_virtual_terminal():
58-
return False
59-
except (ImportError, AttributeError):
60-
return False
61-
6261
try:
6362
return os.isatty(sys.stderr.fileno())
6463
except io.UnsupportedOperation:

Lib/test/test__colorize.py

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -50,47 +50,10 @@ def test_colorized_detection_checks_for_environment_variables(self):
5050
with unittest.mock.patch("os.environ",
5151
{'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
5252
self.assertEqual(_colorize.can_colorize(), False)
53-
with unittest.mock.patch("os.environ", {}):
54-
self.assertEqual(_colorize.can_colorize(), True)
55-
5653
isatty_mock.return_value = False
5754
with unittest.mock.patch("os.environ", {}):
5855
self.assertEqual(_colorize.can_colorize(), False)
5956

60-
@force_not_colorized
61-
@unittest.skipUnless(sys.platform == "win32", "Windows only")
62-
def test_colorized_detection_checks_for_environment_variables_no_vt(self):
63-
with (unittest.mock.patch("nt._supports_virtual_terminal", return_value=False),
64-
unittest.mock.patch("os.isatty") as isatty_mock,
65-
unittest.mock.patch("sys.flags", unittest.mock.MagicMock(ignore_environment=False)),
66-
unittest.mock.patch("_colorize.can_colorize", ORIGINAL_CAN_COLORIZE)):
67-
isatty_mock.return_value = True
68-
with unittest.mock.patch("os.environ", {'TERM': 'dumb'}):
69-
self.assertEqual(_colorize.can_colorize(), False)
70-
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}):
71-
self.assertEqual(_colorize.can_colorize(), True)
72-
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}):
73-
self.assertEqual(_colorize.can_colorize(), False)
74-
with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}):
75-
self.assertEqual(_colorize.can_colorize(), False)
76-
with unittest.mock.patch("os.environ",
77-
{'NO_COLOR': '1', "PYTHON_COLORS": '1'}):
78-
self.assertEqual(_colorize.can_colorize(), True)
79-
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}):
80-
self.assertEqual(_colorize.can_colorize(), True)
81-
with unittest.mock.patch("os.environ",
82-
{'FORCE_COLOR': '1', 'NO_COLOR': '1'}):
83-
self.assertEqual(_colorize.can_colorize(), False)
84-
with unittest.mock.patch("os.environ",
85-
{'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
86-
self.assertEqual(_colorize.can_colorize(), False)
87-
with unittest.mock.patch("os.environ", {}):
88-
self.assertEqual(_colorize.can_colorize(), False)
89-
90-
isatty_mock.return_value = False
91-
with unittest.mock.patch("os.environ", {}):
92-
self.assertEqual(_colorize.can_colorize(), False)
93-
9457

9558
if __name__ == "__main__":
9659
unittest.main()

Lib/venv/__init__.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ def _venv_path(self, env_dir, name):
103103
vars = {
104104
'base': env_dir,
105105
'platbase': env_dir,
106-
'installed_base': env_dir,
107-
'installed_platbase': env_dir,
108106
}
109107
return sysconfig.get_path(name, scheme='venv', vars=vars)
110108

@@ -175,9 +173,20 @@ def create_if_needed(d):
175173
context.python_dir = dirname
176174
context.python_exe = exename
177175
binpath = self._venv_path(env_dir, 'scripts')
178-
incpath = self._venv_path(env_dir, 'include')
179176
libpath = self._venv_path(env_dir, 'purelib')
180177

178+
# PEP 405 says venvs should create a local include directory.
179+
# See https://peps.python.org/pep-0405/#include-files
180+
# XXX: This directory is not exposed in sysconfig or anywhere else, and
181+
# doesn't seem to be utilized by modern packaging tools. We keep it
182+
# for backwards-compatibility, and to follow the PEP, but I would
183+
# recommend against using it, as most tooling does not pass it to
184+
# compilers. Instead, until we standardize a site-specific include
185+
# directory, I would recommend installing headers as package data,
186+
# and providing some sort of API to get the include directories.
187+
# Example: https://numpy.org/doc/2.1/reference/generated/numpy.get_include.html
188+
incpath = os.path.join(env_dir, 'Include' if os.name == 'nt' else 'include')
189+
181190
context.inc_path = incpath
182191
create_if_needed(incpath)
183192
context.lib_path = libpath

Makefile.pre.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,7 @@ testios:
21692169
$(PYTHON_FOR_BUILD) $(srcdir)/iOS/testbed clone --framework $(PYTHONFRAMEWORKPREFIX) "$(XCFOLDER)"
21702170

21712171
# Run the testbed project
2172-
$(PYTHON_FOR_BUILD) "$(XCFOLDER)" run -- test -uall --single-process --rerun -W
2172+
$(PYTHON_FOR_BUILD) "$(XCFOLDER)" run --verbose -- test -uall --single-process --rerun -W
21732173

21742174
# Like test, but using --slow-ci which enables all test resources and use
21752175
# longer timeout. Run an optional pybuildbot.identify script to include

Misc/NEWS.d/next/Windows/2024-11-28-15-55-48.gh-issue-127353.i-XOXg.rst

Lines changed: 0 additions & 2 deletions
This file was deleted.

iOS/testbed/__main__.py

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,12 @@ async def log_stream_task(initial_devices):
141141
else:
142142
suppress_dupes = False
143143
sys.stdout.write(line)
144+
sys.stdout.flush()
144145

145146

146-
async def xcode_test(location, simulator):
147+
async def xcode_test(location, simulator, verbose):
147148
# Run the test suite on the named simulator
149+
print("Starting xcodebuild...")
148150
args = [
149151
"xcodebuild",
150152
"test",
@@ -159,13 +161,17 @@ async def xcode_test(location, simulator):
159161
"-derivedDataPath",
160162
str(location / "DerivedData"),
161163
]
164+
if not verbose:
165+
args += ["-quiet"]
166+
162167
async with async_process(
163168
*args,
164169
stdout=subprocess.PIPE,
165170
stderr=subprocess.STDOUT,
166171
) as process:
167172
while line := (await process.stdout.readline()).decode(*DECODE_ARGS):
168173
sys.stdout.write(line)
174+
sys.stdout.flush()
169175

170176
status = await asyncio.wait_for(process.wait(), timeout=1)
171177
exit(status)
@@ -182,7 +188,9 @@ def clone_testbed(
182188
sys.exit(10)
183189

184190
if framework is None:
185-
if not (source / "Python.xcframework/ios-arm64_x86_64-simulator/bin").is_dir():
191+
if not (
192+
source / "Python.xcframework/ios-arm64_x86_64-simulator/bin"
193+
).is_dir():
186194
print(
187195
f"The testbed being cloned ({source}) does not contain "
188196
f"a simulator framework. Re-run with --framework"
@@ -202,33 +210,48 @@ def clone_testbed(
202210
)
203211
sys.exit(13)
204212

205-
print("Cloning testbed project...")
206-
shutil.copytree(source, target)
213+
print("Cloning testbed project:")
214+
print(f" Cloning {source}...", end="", flush=True)
215+
shutil.copytree(source, target, symlinks=True)
216+
print(" done")
207217

208218
if framework is not None:
209219
if framework.suffix == ".xcframework":
210-
print("Installing XCFramework...")
211-
xc_framework_path = target / "Python.xcframework"
212-
shutil.rmtree(xc_framework_path)
213-
shutil.copytree(framework, xc_framework_path)
220+
print(" Installing XCFramework...", end="", flush=True)
221+
xc_framework_path = (target / "Python.xcframework").resolve()
222+
if xc_framework_path.is_dir():
223+
shutil.rmtree(xc_framework_path)
224+
else:
225+
xc_framework_path.unlink()
226+
xc_framework_path.symlink_to(
227+
framework.relative_to(xc_framework_path.parent, walk_up=True)
228+
)
229+
print(" done")
214230
else:
215-
print("Installing simulator Framework...")
231+
print(" Installing simulator framework...", end="", flush=True)
216232
sim_framework_path = (
217233
target / "Python.xcframework" / "ios-arm64_x86_64-simulator"
234+
).resolve()
235+
if sim_framework_path.is_dir():
236+
shutil.rmtree(sim_framework_path)
237+
else:
238+
sim_framework_path.unlink()
239+
sim_framework_path.symlink_to(
240+
framework.relative_to(sim_framework_path.parent, walk_up=True)
218241
)
219-
shutil.rmtree(sim_framework_path)
220-
shutil.copytree(framework, sim_framework_path)
242+
print(" done")
221243
else:
222-
print("Using pre-existing iOS framework.")
244+
print(" Using pre-existing iOS framework.")
223245

224246
for app_src in apps:
225-
print(f"Installing app {app_src.name!r}...")
247+
print(f" Installing app {app_src.name!r}...", end="", flush=True)
226248
app_target = target / f"iOSTestbed/app/{app_src.name}"
227249
if app_target.is_dir():
228250
shutil.rmtree(app_target)
229251
shutil.copytree(app_src, app_target)
252+
print(" done")
230253

231-
print(f"Testbed project created in {target}")
254+
print(f"Successfully cloned testbed: {target.resolve()}")
232255

233256

234257
def update_plist(testbed_path, args):
@@ -243,10 +266,11 @@ def update_plist(testbed_path, args):
243266
plistlib.dump(info, f)
244267

245268

246-
async def run_testbed(simulator: str, args: list[str]):
269+
async def run_testbed(simulator: str, args: list[str], verbose: bool=False):
247270
location = Path(__file__).parent
248-
print("Updating plist...")
271+
print("Updating plist...", end="", flush=True)
249272
update_plist(location, args)
273+
print(" done.")
250274

251275
# Get the list of devices that are booted at the start of the test run.
252276
# The simulator started by the test suite will be detected as the new
@@ -256,7 +280,7 @@ async def run_testbed(simulator: str, args: list[str]):
256280
try:
257281
async with asyncio.TaskGroup() as tg:
258282
tg.create_task(log_stream_task(initial_devices))
259-
tg.create_task(xcode_test(location, simulator))
283+
tg.create_task(xcode_test(location, simulator=simulator, verbose=verbose))
260284
except* MySystemExit as e:
261285
raise SystemExit(*e.exceptions[0].args) from None
262286
except* subprocess.CalledProcessError as e:
@@ -315,6 +339,11 @@ def main():
315339
default="iPhone SE (3rd Generation)",
316340
help="The name of the simulator to use (default: 'iPhone SE (3rd Generation)')",
317341
)
342+
run.add_argument(
343+
"-v", "--verbose",
344+
action="store_true",
345+
help="Enable verbose output",
346+
)
318347

319348
try:
320349
pos = sys.argv.index("--")
@@ -330,7 +359,7 @@ def main():
330359
clone_testbed(
331360
source=Path(__file__).parent,
332361
target=Path(context.location),
333-
framework=Path(context.framework) if context.framework else None,
362+
framework=Path(context.framework).resolve() if context.framework else None,
334363
apps=[Path(app) for app in context.apps],
335364
)
336365
elif context.subcommand == "run":
@@ -348,6 +377,7 @@ def main():
348377
asyncio.run(
349378
run_testbed(
350379
simulator=context.simulator,
380+
verbose=context.verbose,
351381
args=test_args,
352382
)
353383
)

iOS/testbed/iOSTestbedTests/iOSTestbedTests.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ - (void)testPython {
2424

2525
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
2626

27-
// Disable all color, as the Xcode log can't display color
27+
// Set some other common environment indicators to disable color, as the
28+
// Xcode log can't display color. Stdout will report that it is *not* a
29+
// TTY.
2830
setenv("NO_COLOR", "1", true);
31+
setenv("PY_COLORS", "0", true);
2932

3033
// Arguments to pass into the test suite runner.
3134
// argv[0] must identify the process; any subsequent arg

0 commit comments

Comments
 (0)