diff options
Diffstat (limited to 'Lib/test')
43 files changed, 336 insertions, 92 deletions
diff --git a/Lib/test/.ruff.toml b/Lib/test/.ruff.toml index 7aa8a4785d6..f1a967203ce 100644 --- a/Lib/test/.ruff.toml +++ b/Lib/test/.ruff.toml @@ -19,5 +19,12 @@ extend-exclude = [ [lint] select = [ + "F401", # Unused import "F811", # Redefinition of unused variable (useful for finding test methods with the same name) ] + +[lint.per-file-ignores] +"*/**/__main__.py" = ["F401"] # Unused import +"test_import/*.py" = ["F401"] # Unused import +"test_importlib/*.py" = ["F401"] # Unused import +"typinganndata/partialexecution/*.py" = ["F401"] # Unused import diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index b7cd7940eb1..351d832a26d 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1101,7 +1101,6 @@ class _MemoryWatchdog: self.started = False def start(self): - import warnings try: f = open(self.procfile, 'r') except OSError as e: @@ -2728,7 +2727,7 @@ def iter_builtin_types(): # Fall back to making a best-effort guess. if hasattr(object, '__flags__'): # Look for any type object with the Py_TPFLAGS_STATIC_BUILTIN flag set. - import datetime + import datetime # noqa: F401 seen = set() for cls, subs in walk_class_hierarchy(object): if cls in seen: diff --git a/Lib/test/support/interpreters/channels.py b/Lib/test/support/interpreters/channels.py index 7a2bd7d63f8..b25a17b1aab 100644 --- a/Lib/test/support/interpreters/channels.py +++ b/Lib/test/support/interpreters/channels.py @@ -6,8 +6,8 @@ from . import _crossinterp # aliases: from _interpchannels import ( - ChannelError, ChannelNotFoundError, ChannelClosedError, - ChannelEmptyError, ChannelNotEmptyError, + ChannelError, ChannelNotFoundError, ChannelClosedError, # noqa: F401 + ChannelEmptyError, ChannelNotEmptyError, # noqa: F401 ) from ._crossinterp import ( UNBOUND_ERROR, UNBOUND_REMOVE, diff --git a/Lib/test/support/interpreters/queues.py b/Lib/test/support/interpreters/queues.py index d6a3197d9e0..99987f2f692 100644 --- a/Lib/test/support/interpreters/queues.py +++ b/Lib/test/support/interpreters/queues.py @@ -1,6 +1,5 @@ """Cross-interpreter Queues High Level Module.""" -import pickle import queue import time import weakref diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index 73a821d15e3..fe091e52a86 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -7,7 +7,7 @@ import collections import functools import itertools import pickle -from string.templatelib import Interpolation, Template +from string.templatelib import Template import typing import unittest from annotationlib import ( @@ -815,6 +815,70 @@ class TestGetAnnotations(unittest.TestCase): {"x": int}, ) + def test_stringized_annotation_permutations(self): + def define_class(name, has_future, has_annos, base_text, extra_names=None): + lines = [] + if has_future: + lines.append("from __future__ import annotations") + lines.append(f"class {name}({base_text}):") + if has_annos: + lines.append(f" {name}_attr: int") + else: + lines.append(" pass") + code = "\n".join(lines) + ns = support.run_code(code, extra_names=extra_names) + return ns[name] + + def check_annotations(cls, has_future, has_annos): + if has_annos: + if has_future: + anno = "int" + else: + anno = int + self.assertEqual(get_annotations(cls), {f"{cls.__name__}_attr": anno}) + else: + self.assertEqual(get_annotations(cls), {}) + + for meta_future, base_future, child_future, meta_has_annos, base_has_annos, child_has_annos in itertools.product( + (False, True), + (False, True), + (False, True), + (False, True), + (False, True), + (False, True), + ): + with self.subTest( + meta_future=meta_future, + base_future=base_future, + child_future=child_future, + meta_has_annos=meta_has_annos, + base_has_annos=base_has_annos, + child_has_annos=child_has_annos, + ): + meta = define_class( + "Meta", + has_future=meta_future, + has_annos=meta_has_annos, + base_text="type", + ) + base = define_class( + "Base", + has_future=base_future, + has_annos=base_has_annos, + base_text="metaclass=Meta", + extra_names={"Meta": meta}, + ) + child = define_class( + "Child", + has_future=child_future, + has_annos=child_has_annos, + base_text="Base", + extra_names={"Base": base}, + ) + check_annotations(meta, meta_future, meta_has_annos) + check_annotations(base, base_future, base_has_annos) + check_annotations(child, child_future, child_has_annos) + def test_modify_annotations(self): def f(x: int): pass diff --git a/Lib/test/test_capi/test_config.py b/Lib/test/test_capi/test_config.py index a2d70dd3af4..04a27de8d84 100644 --- a/Lib/test/test_capi/test_config.py +++ b/Lib/test/test_capi/test_config.py @@ -3,7 +3,6 @@ Tests PyConfig_Get() and PyConfig_Set() C API (PEP 741). """ import os import sys -import sysconfig import types import unittest from test import support diff --git a/Lib/test/test_codeccallbacks.py b/Lib/test/test_codeccallbacks.py index a767f67a02c..65d54d1004d 100644 --- a/Lib/test/test_codeccallbacks.py +++ b/Lib/test/test_codeccallbacks.py @@ -2,7 +2,6 @@ from _codecs import _unregister_error as _codecs_unregister_error import codecs import html.entities import itertools -import re import sys import unicodedata import unittest diff --git a/Lib/test/test_crossinterp.py b/Lib/test/test_crossinterp.py index c54635eaeab..2fa0077a09b 100644 --- a/Lib/test/test_crossinterp.py +++ b/Lib/test/test_crossinterp.py @@ -1,6 +1,4 @@ import contextlib -import importlib -import importlib.util import itertools import sys import types diff --git a/Lib/test/test_ctypes/_support.py b/Lib/test/test_ctypes/_support.py index 946d654a19a..700657a4e41 100644 --- a/Lib/test/test_ctypes/_support.py +++ b/Lib/test/test_ctypes/_support.py @@ -3,7 +3,6 @@ import ctypes from _ctypes import Structure, Union, _Pointer, Array, _SimpleCData, CFuncPtr import sys -from test import support _CData = Structure.__base__ diff --git a/Lib/test/test_ctypes/test_byteswap.py b/Lib/test/test_ctypes/test_byteswap.py index ea5951603f9..f14e1aa32e1 100644 --- a/Lib/test/test_ctypes/test_byteswap.py +++ b/Lib/test/test_ctypes/test_byteswap.py @@ -1,5 +1,4 @@ import binascii -import ctypes import math import struct import sys diff --git a/Lib/test/test_ctypes/test_generated_structs.py b/Lib/test/test_ctypes/test_generated_structs.py index aa448fad5bb..1cb46a82701 100644 --- a/Lib/test/test_ctypes/test_generated_structs.py +++ b/Lib/test/test_ctypes/test_generated_structs.py @@ -10,7 +10,7 @@ Run this module to regenerate the files: """ import unittest -from test.support import import_helper, verbose +from test.support import import_helper import re from dataclasses import dataclass from functools import cached_property diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 9e298401dc3..c0a1e378583 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -28,7 +28,6 @@ import logging import math import os, sys import operator -import warnings import pickle, copy import unittest import numbers diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index ac12c3b2306..fd4ac2c404c 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -463,6 +463,19 @@ class TestParser(TestParserMixin, TestEmailBase): [errors.NonPrintableDefect], ')') self.assertEqual(ptext.defects[0].non_printables[0], '\x00') + def test_get_qp_ctext_close_paren_only(self): + self._test_get_x(parser.get_qp_ctext, + ')', '', ' ', [], ')') + + def test_get_qp_ctext_open_paren_only(self): + self._test_get_x(parser.get_qp_ctext, + '(', '', ' ', [], '(') + + def test_get_qp_ctext_no_end_char(self): + self._test_get_x(parser.get_qp_ctext, + '', '', ' ', [], '') + + # get_qcontent def test_get_qcontent_only(self): @@ -503,6 +516,14 @@ class TestParser(TestParserMixin, TestEmailBase): [errors.NonPrintableDefect], '"') self.assertEqual(ptext.defects[0].non_printables[0], '\x00') + def test_get_qcontent_empty(self): + self._test_get_x(parser.get_qcontent, + '"', '', '', [], '"') + + def test_get_qcontent_no_end_char(self): + self._test_get_x(parser.get_qcontent, + '', '', '', [], '') + # get_atext def test_get_atext_only(self): @@ -1283,6 +1304,18 @@ class TestParser(TestParserMixin, TestEmailBase): self._test_get_x(parser.get_dtext, 'foo[bar', 'foo', 'foo', [], '[bar') + def test_get_dtext_open_bracket_only(self): + self._test_get_x(parser.get_dtext, + '[', '', '', [], '[') + + def test_get_dtext_close_bracket_only(self): + self._test_get_x(parser.get_dtext, + ']', '', '', [], ']') + + def test_get_dtext_empty(self): + self._test_get_x(parser.get_dtext, + '', '', '', [], '') + # get_domain_literal def test_get_domain_literal_only(self): diff --git a/Lib/test/test_external_inspection.py b/Lib/test/test_external_inspection.py index ad3f669a030..291c419066a 100644 --- a/Lib/test/test_external_inspection.py +++ b/Lib/test/test_external_inspection.py @@ -4,6 +4,7 @@ import textwrap import importlib import sys import socket +import threading from asyncio import staggered, taskgroups from unittest.mock import ANY from test.support import os_helper, SHORT_TIMEOUT, busy_retry @@ -16,9 +17,7 @@ PROCESS_VM_READV_SUPPORTED = False try: from _remote_debugging import PROCESS_VM_READV_SUPPORTED - from _remote_debugging import get_stack_trace - from _remote_debugging import get_async_stack_trace - from _remote_debugging import get_all_awaited_by + from _remote_debugging import RemoteUnwinder except ImportError: raise unittest.SkipTest("Test only runs when _remote_debugging is available") @@ -34,7 +33,23 @@ skip_if_not_supported = unittest.skipIf( ) +def get_stack_trace(pid): + unwinder = RemoteUnwinder(pid, all_threads=True) + return unwinder.get_stack_trace() + + +def get_async_stack_trace(pid): + unwinder = RemoteUnwinder(pid) + return unwinder.get_async_stack_trace() + + +def get_all_awaited_by(pid): + unwinder = RemoteUnwinder(pid) + return unwinder.get_all_awaited_by() + + class TestGetStackTrace(unittest.TestCase): + maxDiff = None @skip_if_not_supported @unittest.skipIf( @@ -46,7 +61,7 @@ class TestGetStackTrace(unittest.TestCase): port = find_unused_port() script = textwrap.dedent( f"""\ - import time, sys, socket + import time, sys, socket, threading # Connect to the test process sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('localhost', {port})) @@ -55,13 +70,16 @@ class TestGetStackTrace(unittest.TestCase): for x in range(100): if x == 50: baz() + def baz(): foo() def foo(): - sock.sendall(b"ready"); time.sleep(10_000) # same line number + sock.sendall(b"ready:thread\\n"); time.sleep(10_000) # same line number - bar() + t = threading.Thread(target=bar) + t.start() + sock.sendall(b"ready:main\\n"); t.join() # same line number """ ) stack_trace = None @@ -82,8 +100,9 @@ class TestGetStackTrace(unittest.TestCase): p = subprocess.Popen([sys.executable, script_name]) client_socket, _ = server_socket.accept() server_socket.close() - response = client_socket.recv(1024) - self.assertEqual(response, b"ready") + response = b"" + while b"ready:main" not in response or b"ready:thread" not in response: + response += client_socket.recv(1024) stack_trace = get_stack_trace(p.pid) except PermissionError: self.skipTest("Insufficient permissions to read the stack trace") @@ -94,13 +113,23 @@ class TestGetStackTrace(unittest.TestCase): p.terminate() p.wait(timeout=SHORT_TIMEOUT) - expected_stack_trace = [ - ("foo", script_name, 14), - ("baz", script_name, 11), + thread_expected_stack_trace = [ + ("foo", script_name, 15), + ("baz", script_name, 12), ("bar", script_name, 9), - ("<module>", script_name, 16), + ('Thread.run', threading.__file__, ANY) ] - self.assertEqual(stack_trace, expected_stack_trace) + # Is possible that there are more threads, so we check that the + # expected stack traces are in the result (looking at you Windows!) + self.assertIn((ANY, thread_expected_stack_trace), stack_trace) + + # Check that the main thread stack trace is in the result + frame = ("<module>", script_name, 19) + for _, stack in stack_trace: + if frame in stack: + break + else: + self.fail("Main thread stack trace not found in result") @skip_if_not_supported @unittest.skipIf( @@ -700,13 +729,28 @@ class TestGetStackTrace(unittest.TestCase): ) def test_self_trace(self): stack_trace = get_stack_trace(os.getpid()) + # Is possible that there are more threads, so we check that the + # expected stack traces are in the result (looking at you Windows!) + this_tread_stack = None + for thread_id, stack in stack_trace: + if thread_id == threading.get_native_id(): + this_tread_stack = stack + break + self.assertIsNotNone(this_tread_stack) self.assertEqual( - stack_trace[0], - ( - "TestGetStackTrace.test_self_trace", - __file__, - self.test_self_trace.__code__.co_firstlineno + 6, - ), + stack[:2], + [ + ( + "get_stack_trace", + __file__, + get_stack_trace.__code__.co_firstlineno + 2, + ), + ( + "TestGetStackTrace.test_self_trace", + __file__, + self.test_self_trace.__code__.co_firstlineno + 6, + ), + ] ) diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index a71ddc01d1c..37046d8e1c0 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -1,11 +1,9 @@ import contextlib import os -import re import sys import tempfile import unittest -from io import StringIO from test import support from test import test_tools @@ -31,12 +29,11 @@ skip_if_different_mount_drives() test_tools.skip_if_missing("cases_generator") with test_tools.imports_under_tool("cases_generator"): - from analyzer import analyze_forest, StackItem + from analyzer import StackItem from cwriter import CWriter import parser from stack import Local, Stack import tier1_generator - import opcode_metadata_generator import optimizer_generator diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py index df07af01fc7..16c3268fefb 100644 --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -8,7 +8,7 @@ import sys import unittest import warnings from test.support import ( - is_apple, is_emscripten, os_helper, warnings_helper + is_apple, os_helper, warnings_helper ) from test.support.script_helper import assert_python_ok from test.support.os_helper import FakePath diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index ccbacc7c19b..a12ff5662a7 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -9,7 +9,6 @@ import os import struct import sys import unittest -import warnings from subprocess import PIPE, Popen from test.support import catch_unraisable_exception from test.support import import_helper diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index de4c8a1670f..161c7652d7a 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -17,7 +17,6 @@ import sysconfig import tempfile import threading import unittest -import warnings from test import support from test.support import _4G, bigmemtest from test.support import hashlib_helper diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index e898644dd8a..ff6e1bce0ef 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -21,7 +21,6 @@ import functools import hmac import hashlib import random -import test.support import test.support.hashlib_helper as hashlib_helper import types import unittest diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py index 3d8b7ecc0ec..ebf572ac5ca 100644 --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -16,7 +16,7 @@ idlelib.testing = True # Unittest.main and test.libregrtest.runtest.runtest_inner # call load_tests, when present here, to discover tests to run. -from idlelib.idle_test import load_tests +from idlelib.idle_test import load_tests # noqa: F401 if __name__ == '__main__': tk.NoDefaultRoot() diff --git a/Lib/test/test_interpreters/test_queues.py b/Lib/test/test_interpreters/test_queues.py index 64a2db1230d..757373904d7 100644 --- a/Lib/test/test_interpreters/test_queues.py +++ b/Lib/test/test_interpreters/test_queues.py @@ -9,7 +9,6 @@ from test.support import import_helper, Py_DEBUG _queues = import_helper.import_module('_interpqueues') from test.support import interpreters from test.support.interpreters import queues, _crossinterp -import test._crossinterp_definitions as defs from .utils import _run_output, TestBase as _TestBase diff --git a/Lib/test/test_interpreters/utils.py b/Lib/test/test_interpreters/utils.py index fc4ad662e03..c25e0fb7475 100644 --- a/Lib/test/test_interpreters/utils.py +++ b/Lib/test/test_interpreters/utils.py @@ -12,7 +12,6 @@ from textwrap import dedent import threading import types import unittest -import warnings from test import support diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index f83ef225a6e..c3b0bdaebc2 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -6,8 +6,7 @@ import subprocess import sys import unittest import warnings -from test.support import cpython_only, os_helper -from test.support import TestFailed, is_emscripten +from test.support import TestFailed, cpython_only, os_helper from test.support.os_helper import FakePath from test import test_genericpath from tempfile import TemporaryFile diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 0a9ba578673..f33de3d420c 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -12,7 +12,7 @@ except ImportError: from test import support from test.support.bytecode_helper import ( - BytecodeTestCase, CfgOptimizationTestCase, CompilationStepTestCase) + BytecodeTestCase, CfgOptimizationTestCase) def compile_pattern_with_fast_locals(pattern): diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index c1728f5019d..4836f38c388 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -20,7 +20,6 @@ import select import signal import socket import io # readline -import warnings TEST_STRING_1 = b"I wish to buy a fish license.\n" TEST_STRING_2 = b"For my pet fish, Eric.\n" diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 281b24eaa36..d1d6f4987de 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -553,7 +553,7 @@ class PydocDocTest(unittest.TestCase): # of the known subclasses of object. (doc.docclass() used to # fail if HeapType was imported before running this test, like # when running tests sequentially.) - from _testcapi import HeapType + from _testcapi import HeapType # noqa: F401 except ImportError: pass text = doc.docclass(object) diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index abb4bd1bc25..aa3a592766d 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -918,7 +918,14 @@ class TestPyReplCompleter(TestCase): class TestPyReplModuleCompleter(TestCase): def setUp(self): + import importlib + # Make iter_modules() search only the standard library. + # This makes the test more reliable in case there are + # other user packages/scripts on PYTHONPATH which can + # interfere with the completions. + lib_path = os.path.dirname(importlib.__path__[0]) self._saved_sys_path = sys.path + sys.path = [lib_path] def tearDown(self): sys.path = self._saved_sys_path @@ -932,14 +939,6 @@ class TestPyReplModuleCompleter(TestCase): return reader def test_import_completions(self): - import importlib - # Make iter_modules() search only the standard library. - # This makes the test more reliable in case there are - # other user packages/scripts on PYTHONPATH which can - # intefere with the completions. - lib_path = os.path.dirname(importlib.__path__[0]) - sys.path = [lib_path] - cases = ( ("import path\t\n", "import pathlib"), ("import importlib.\t\tres\t\n", "import importlib.resources"), @@ -1052,6 +1051,19 @@ class TestPyReplModuleCompleter(TestCase): output = reader.readline() self.assertEqual(output, expected) + def test_no_fallback_on_regular_completion(self): + cases = ( + ("import pri\t\n", "import pri"), + ("from pri\t\n", "from pri"), + ("from typing import Na\t\n", "from typing import Na"), + ) + for code, expected in cases: + with self.subTest(code=code): + events = code_to_events(code) + reader = self.prepare_reader(events, namespace={}) + output = reader.readline() + self.assertEqual(output, expected) + def test_get_path_and_prefix(self): cases = ( ('', ('', '')), diff --git a/Lib/test/test_pyrepl/test_unix_console.py b/Lib/test/test_pyrepl/test_unix_console.py index c447b310c49..b3f7dc028fe 100644 --- a/Lib/test/test_pyrepl/test_unix_console.py +++ b/Lib/test/test_pyrepl/test_unix_console.py @@ -20,6 +20,7 @@ except ImportError: def unix_console(events, **kwargs): console = UnixConsole() console.get_event = MagicMock(side_effect=events) + console.getpending = MagicMock(return_value=Event("key", "")) height = kwargs.get("height", 25) width = kwargs.get("width", 80) diff --git a/Lib/test/test_pyrepl/test_windows_console.py b/Lib/test/test_pyrepl/test_windows_console.py index e7bab226b31..f9607e02c60 100644 --- a/Lib/test/test_pyrepl/test_windows_console.py +++ b/Lib/test/test_pyrepl/test_windows_console.py @@ -35,6 +35,7 @@ class WindowsConsoleTests(TestCase): def console(self, events, **kwargs) -> Console: console = WindowsConsole() console.get_event = MagicMock(side_effect=events) + console.getpending = MagicMock(return_value=Event("key", "")) console.wait = MagicMock() console._scroll = MagicMock() console._hide_cursor = MagicMock() @@ -385,6 +386,7 @@ class WindowsConsoleGetEventTests(TestCase): self.console._read_input = self.mock self.console._WindowsConsole__vt_support = kwargs.get("vt_support", False) + self.console.wait = MagicMock(return_value=True) event = self.console.get_event(block=False) return event diff --git a/Lib/test/test_remote_pdb.py b/Lib/test/test_remote_pdb.py index aef8a6b0129..a1c50af15f3 100644 --- a/Lib/test/test_remote_pdb.py +++ b/Lib/test/test_remote_pdb.py @@ -1,5 +1,4 @@ import io -import time import itertools import json import os @@ -8,16 +7,13 @@ import signal import socket import subprocess import sys -import tempfile import textwrap -import threading import unittest import unittest.mock from contextlib import closing, contextmanager, redirect_stdout, redirect_stderr, ExitStack -from pathlib import Path from test.support import is_wasi, cpython_only, force_color, requires_subprocess, SHORT_TIMEOUT -from test.support.os_helper import temp_dir, TESTFN, unlink -from typing import Dict, List, Optional, Tuple, Union, Any +from test.support.os_helper import TESTFN, unlink +from typing import List import pdb from pdb import _PdbServer, _PdbClient @@ -1434,7 +1430,6 @@ class PdbConnectTestCase(unittest.TestCase): def _supports_remote_attaching(): - from contextlib import suppress PROCESS_VM_READV_SUPPORTED = False try: diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 62c80aab4b3..ebb6cf88336 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -3492,7 +3492,7 @@ class PublicAPITests(unittest.TestCase): target_api.append('disk_usage') self.assertEqual(set(shutil.__all__), set(target_api)) with self.assertWarns(DeprecationWarning): - from shutil import ExecError + from shutil import ExecError # noqa: F401 if __name__ == '__main__': diff --git a/Lib/test/test_string/_support.py b/Lib/test/test_string/_support.py index eaa3354a559..abdddaf187b 100644 --- a/Lib/test/test_string/_support.py +++ b/Lib/test/test_string/_support.py @@ -1,4 +1,3 @@ -import unittest from string.templatelib import Interpolation diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index d30f69ded66..2c0df9376ab 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -32,7 +32,6 @@ from sysconfig import (get_paths, get_platform, get_config_vars, from sysconfig.__main__ import _main, _parse_makefile, _get_pybuilddir, _get_json_data_name import _imp import _osx_support -import _sysconfig HAS_USER_BASE = sysconfig._HAS_USER_BASE diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 0e51e7fc8c5..59b3a749d2f 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1253,7 +1253,7 @@ class ThreadTests(BaseTestCase): # its state should be removed from interpreter' thread states list # to avoid its double cleanup try: - from resource import setrlimit, RLIMIT_NPROC + from resource import setrlimit, RLIMIT_NPROC # noqa: F401 except ImportError as err: self.skipTest(err) # RLIMIT_NPROC is specific to Linux and BSD code = """if 1: diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 2d41a5e5ac0..e6b19fe1812 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1975,6 +1975,10 @@ if 1: for case in cases: self.check_roundtrip(case) + self.check_roundtrip(r"t'{ {}}'") + self.check_roundtrip(r"t'{f'{ {}}'}{ {}}'") + self.check_roundtrip(r"f'{t'{ {}}'}{ {}}'") + def test_continuation(self): # Balancing continuation diff --git a/Lib/test/test_tools/i18n_data/docstrings.py b/Lib/test/test_tools/i18n_data/docstrings.py index 151a55a4b56..14559a632da 100644 --- a/Lib/test/test_tools/i18n_data/docstrings.py +++ b/Lib/test/test_tools/i18n_data/docstrings.py @@ -1,7 +1,7 @@ """Module docstring""" # Test docstring extraction -from gettext import gettext as _ +from gettext import gettext as _ # noqa: F401 # Empty docstring diff --git a/Lib/test/test_type_annotations.py b/Lib/test/test_type_annotations.py index 2c886bb6d36..c66cb058552 100644 --- a/Lib/test/test_type_annotations.py +++ b/Lib/test/test_type_annotations.py @@ -498,6 +498,28 @@ class DeferredEvaluationTests(unittest.TestCase): self.assertEqual(f.__annotate__(annotationlib.Format.VALUE), annos) self.assertEqual(f.__annotations__, annos) + def test_set_annotations(self): + function_code = textwrap.dedent(""" + def f(x: int): + pass + """) + class_code = textwrap.dedent(""" + class f: + x: int + """) + for future in (False, True): + for label, code in (("function", function_code), ("class", class_code)): + with self.subTest(future=future, label=label): + if future: + code = "from __future__ import annotations\n" + code + ns = run_code(code) + f = ns["f"] + anno = "int" if future else int + self.assertEqual(f.__annotations__, {"x": anno}) + + f.__annotations__ = {"x": str} + self.assertEqual(f.__annotations__, {"x": str}) + def test_name_clash_with_format(self): # this test would fail if __annotate__'s parameter was called "format" # during symbol table construction diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 3097c7ddf05..9011e0e1962 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -2516,7 +2516,7 @@ class SubinterpreterTests(unittest.TestCase): from test.support import interpreters except ModuleNotFoundError: raise unittest.SkipTest('subinterpreters required') - import test.support.interpreters.channels + import test.support.interpreters.channels # noqa: F401 @cpython_only @no_rerun('channels (and queues) might have a refleak; see gh-122199') diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 246be22a0d8..ef02e8202fc 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -46,11 +46,10 @@ import abc import textwrap import typing import weakref -import warnings import types from test.support import ( - captured_stderr, cpython_only, infinite_recursion, requires_docstrings, import_helper, run_code, + captured_stderr, cpython_only, requires_docstrings, import_helper, run_code, EqualToForwardRef, ) from test.typinganndata import ( @@ -6859,12 +6858,10 @@ class GetTypeHintsTests(BaseTestCase): self.assertEqual(hints, {'value': Final}) def test_top_level_class_var(self): - # https://bugs.python.org/issue45166 - with self.assertRaisesRegex( - TypeError, - r'typing.ClassVar\[int\] is not valid as type argument', - ): - get_type_hints(ann_module6) + # This is not meaningful but we don't raise for it. + # https://github.com/python/cpython/issues/133959 + hints = get_type_hints(ann_module6) + self.assertEqual(hints, {'wrong': ClassVar[int]}) def test_get_type_hints_typeddict(self): self.assertEqual(get_type_hints(TotalMovie), {'title': str, 'year': int}) @@ -6967,6 +6964,11 @@ class GetTypeHintsTests(BaseTestCase): self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': Callable[..., T]}) + def test_special_forms_no_forward(self): + def f(x: ClassVar[int]): + pass + self.assertEqual(get_type_hints(f), {'x': ClassVar[int]}) + def test_special_forms_forward(self): class C: @@ -6982,8 +6984,9 @@ class GetTypeHintsTests(BaseTestCase): self.assertEqual(get_type_hints(C, globals())['b'], Final[int]) self.assertEqual(get_type_hints(C, globals())['x'], ClassVar) self.assertEqual(get_type_hints(C, globals())['y'], Final) - with self.assertRaises(TypeError): - get_type_hints(CF, globals()), + lfi = get_type_hints(CF, globals())['b'] + self.assertIs(get_origin(lfi), list) + self.assertEqual(get_args(lfi), (Final[int],)) def test_union_forward_recursion(self): ValueList = List['Value'] @@ -7216,33 +7219,113 @@ class GetUtilitiesTestCase(TestCase): class EvaluateForwardRefTests(BaseTestCase): def test_evaluate_forward_ref(self): int_ref = ForwardRef('int') - missing = ForwardRef('missing') + self.assertIs(typing.evaluate_forward_ref(int_ref), int) self.assertIs( typing.evaluate_forward_ref(int_ref, type_params=()), int, ) self.assertIs( + typing.evaluate_forward_ref(int_ref, format=annotationlib.Format.VALUE), + int, + ) + self.assertIs( typing.evaluate_forward_ref( - int_ref, type_params=(), format=annotationlib.Format.FORWARDREF, + int_ref, format=annotationlib.Format.FORWARDREF, ), int, ) + self.assertEqual( + typing.evaluate_forward_ref( + int_ref, format=annotationlib.Format.STRING, + ), + 'int', + ) + + def test_evaluate_forward_ref_undefined(self): + missing = ForwardRef('missing') + with self.assertRaises(NameError): + typing.evaluate_forward_ref(missing) self.assertIs( typing.evaluate_forward_ref( - missing, type_params=(), format=annotationlib.Format.FORWARDREF, + missing, format=annotationlib.Format.FORWARDREF, ), missing, ) self.assertEqual( typing.evaluate_forward_ref( - int_ref, type_params=(), format=annotationlib.Format.STRING, + missing, format=annotationlib.Format.STRING, ), - 'int', + "missing", ) - def test_evaluate_forward_ref_no_type_params(self): - ref = ForwardRef('int') - self.assertIs(typing.evaluate_forward_ref(ref), int) + def test_evaluate_forward_ref_nested(self): + ref = ForwardRef("int | list['str']") + self.assertEqual( + typing.evaluate_forward_ref(ref), + int | list[str], + ) + self.assertEqual( + typing.evaluate_forward_ref(ref, format=annotationlib.Format.FORWARDREF), + int | list[str], + ) + self.assertEqual( + typing.evaluate_forward_ref(ref, format=annotationlib.Format.STRING), + "int | list['str']", + ) + + why = ForwardRef('"\'str\'"') + self.assertIs(typing.evaluate_forward_ref(why), str) + + def test_evaluate_forward_ref_none(self): + none_ref = ForwardRef('None') + self.assertIs(typing.evaluate_forward_ref(none_ref), None) + + def test_globals(self): + A = "str" + ref = ForwardRef('list[A]') + with self.assertRaises(NameError): + typing.evaluate_forward_ref(ref) + self.assertEqual( + typing.evaluate_forward_ref(ref, globals={'A': A}), + list[str], + ) + + def test_owner(self): + ref = ForwardRef("A") + + with self.assertRaises(NameError): + typing.evaluate_forward_ref(ref) + + # We default to the globals of `owner`, + # so it no longer raises `NameError` + self.assertIs( + typing.evaluate_forward_ref(ref, owner=Loop), A + ) + + def test_inherited_owner(self): + # owner passed to evaluate_forward_ref + ref = ForwardRef("list['A']") + self.assertEqual( + typing.evaluate_forward_ref(ref, owner=Loop), + list[A], + ) + + # owner set on the ForwardRef + ref = ForwardRef("list['A']", owner=Loop) + self.assertEqual( + typing.evaluate_forward_ref(ref), + list[A], + ) + + def test_partial_evaluation(self): + ref = ForwardRef("list[A]") + with self.assertRaises(NameError): + typing.evaluate_forward_ref(ref) + + self.assertEqual( + typing.evaluate_forward_ref(ref, format=annotationlib.Format.FORWARDREF), + list[EqualToForwardRef('A')], + ) class CollectionsAbcTests(BaseTestCase): diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 12c30e178ae..d62f3fba2d1 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -1008,7 +1008,7 @@ class EnsurePipTest(BaseTest): err, flags=re.MULTILINE) # Ignore warning about missing optional module: try: - import ssl + import ssl # noqa: F401 except ImportError: err = re.sub( "^WARNING: Disabling truststore since ssl support is missing$", diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index 4c3ea1cd8df..6b577ae100e 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -6,7 +6,6 @@ import subprocess import sys import unittest import webbrowser -from functools import partial from test import support from test.support import import_helper from test.support import is_apple_mobile diff --git a/Lib/test/test_zipfile/__main__.py b/Lib/test/test_zipfile/__main__.py index e25ac946edf..90da74ade38 100644 --- a/Lib/test/test_zipfile/__main__.py +++ b/Lib/test/test_zipfile/__main__.py @@ -1,6 +1,6 @@ import unittest -from . import load_tests # noqa: F401 +from . import load_tests if __name__ == "__main__": diff --git a/Lib/test/test_zstd.py b/Lib/test/test_zstd.py index 34c7c721b1a..bc809603cbc 100644 --- a/Lib/test/test_zstd.py +++ b/Lib/test/test_zstd.py @@ -12,7 +12,6 @@ import threading from test.support.import_helper import import_module from test.support import threading_helper from test.support import _1M -from test.support import Py_GIL_DISABLED _zstd = import_module("_zstd") zstd = import_module("compression.zstd") |