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
9 changes: 5 additions & 4 deletions Lib/profiling/sampling/_sync_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,15 @@ def _execute_script(script_path: str, script_args: List[str], cwd: str) -> None:
try:
with open(script_path, 'rb') as f:
source_code = f.read()

# Compile and execute the script
code = compile(source_code, script_path, 'exec')
exec(code, {'__name__': '__main__', '__file__': script_path})
except FileNotFoundError as e:
raise TargetError(f"Script file not found: {script_path}") from e
except PermissionError as e:
raise TargetError(f"Permission denied reading script: {script_path}") from e

try:
# Compile and execute the script
code = compile(source_code, script_path, 'exec')
exec(code, {'__name__': '__main__', '__file__': script_path})
except SyntaxError as e:
raise TargetError(f"Syntax error in script {script_path}: {e}") from e
except SystemExit:
Expand Down
8 changes: 8 additions & 0 deletions Lib/test/libregrtest/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import unittest
from test import support
from test.support.os_helper import TESTFN_UNDECODABLE, FS_NONASCII
from _colorize import can_colorize # type: ignore[import-not-found]

from .filter import set_match_tests
from .runtests import RunTests
Expand Down Expand Up @@ -139,3 +140,10 @@ def setup_tests(runtests: RunTests) -> None:
gc.set_threshold(runtests.gc_threshold)

random.seed(runtests.random_seed)

# sys.stdout is redirected to a StringIO in single process mode on which
# color auto-detect fails as StringIO is not a TTY. If the original
# sys.stdout supports color pass that through with FORCE_COLOR so that when
# results are printed, such as with -W, they get color.
if can_colorize(file=sys.stdout):
os.environ['FORCE_COLOR'] = "1"
7 changes: 7 additions & 0 deletions Lib/test/libregrtest/worker.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import subprocess
import sys
import os
from _colorize import can_colorize # type: ignore[import-not-found]
from typing import Any, NoReturn

from test.support import os_helper, Py_DEBUG
Expand Down Expand Up @@ -32,6 +33,12 @@ def create_worker_process(runtests: WorkerRunTests, output_fd: int,
env['TEMP'] = tmp_dir
env['TMP'] = tmp_dir

# The subcommand is run with a temporary output which means it is not a TTY
# and won't auto-color. The test results are printed to stdout so if we can
# color that have the subprocess use color.
if can_colorize(file=sys.stdout):
env['FORCE_COLOR'] = '1'

# Running the child from the same working directory as regrtest's original
# invocation ensures that TEMPDIR for the child is the same when
# sysconfig.is_python_build() is true. See issue 15300.
Expand Down
4 changes: 4 additions & 0 deletions Lib/test/pythoninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ def format_groups(groups):
"DISTUTILS_USE_SDK",
"DYLD_LIBRARY_PATH",
"ENSUREPIP_OPTIONS",
"FORCE_COLOR",
"GITHUB_ACTIONS",
"HISTORY_FILE",
"HOME",
"HOMEDRIVE",
Expand All @@ -307,11 +309,13 @@ def format_groups(groups):
"MAKEFLAGS",
"MIXERDEV",
"MSSDK",
"NO_COLOR",
"PATH",
"PATHEXT",
"PIP_CONFIG_FILE",
"PLAT",
"POSIXLY_CORRECT",
"PYTHON_COLORS",
"PY_SAX_PARSER",
"ProgramFiles",
"ProgramFiles(x86)",
Expand Down
18 changes: 18 additions & 0 deletions Lib/test/test_profiling/test_sampling_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,24 @@ def test_valid_output_formats(self):
# Expected errors - we just want to test format validation
pass

def test_script_error_treatment(self):
script_file = tempfile.NamedTemporaryFile("w", delete=False, suffix=".py")
script_file.write("open('nonexistent_file.txt')\n")
script_file.close()
self.addCleanup(os.unlink, script_file.name)

result = subprocess.run(
[sys.executable, "-m", "profiling.sampling.sample", "-d", "1", script_file.name],
capture_output=True,
text=True,
)
output = result.stdout + result.stderr

if "PermissionError" in output:
self.skipTest("Insufficient permissions for remote profiling")
self.assertNotIn("Script file not found", output)
self.assertIn("No such file or directory: 'nonexistent_file.txt'", output)


class TestSampleProfilerCLI(unittest.TestCase):
def _setup_sync_mocks(self, mock_socket, mock_popen):
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_tokenize.py
Original file line number Diff line number Diff line change
Expand Up @@ -3183,6 +3183,7 @@ def get_tokens(string):
f'__{
x:d
}__'""",
" a\n\x00",
]:
with self.subTest(case=case):
self.assertRaises(tokenize.TokenError, get_tokens, case)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed crash in :func:`tokenize.generate_tokens` in case of
specific incorrect input. Patch by Mikhail Efimov.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :func:`profiling.sampling.sample` incorrectly handling a
:exc:`FileNotFoundError` or :exc:`PermissionError`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Update ``python -m test`` to set ``FORCE_COLOR=1`` when being run with color
enabled so that :mod:`unittest` which is run by it with redirected output will
output in color.
3 changes: 3 additions & 0 deletions Parser/lexer/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,9 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
return MAKE_TOKEN(ERRORTOKEN);
}
}
else if (c == EOF && PyErr_Occurred()) {
return MAKE_TOKEN(ERRORTOKEN);
}
else {
break;
}
Expand Down
Loading