Update Lib with changed files in 3.13.8 (#6186)

* Update changed files from 3.13.7 -> 3.13.8

* Reapply some patches

* Reaaply patches to `test_bytes.py`

* fix test markers in `test_exceptions.py`

* Patch `test_posix.py`

* Patched `test_{pyexpat,site,sysconfig}.py`

* Patched `test_typing.py`

* Patch failing tests in `test_typing.py`

* Update `seq_tests` from 3.13.8

* Mark failing tests in `test_genericalias.py`

* mark failing tests in `test_pyexpat.py`

* Mark failing tests in `test_posix.py`

* reapply patch

* mark failing tests

* skip flaky test
This commit is contained in:
Jeong, YunWon
2025-10-22 20:28:05 +09:00
committed by GitHub
23 changed files with 1137 additions and 400 deletions

View File

@@ -29,15 +29,19 @@ def init_streams(android_log_write, stdout_prio, stderr_prio):
global logcat
logcat = Logcat(android_log_write)
sys.stdout = TextLogStream(
stdout_prio, "python.stdout", sys.stdout.fileno())
sys.stderr = TextLogStream(
stderr_prio, "python.stderr", sys.stderr.fileno())
sys.stdout = TextLogStream(stdout_prio, "python.stdout", sys.stdout)
sys.stderr = TextLogStream(stderr_prio, "python.stderr", sys.stderr)
class TextLogStream(io.TextIOWrapper):
def __init__(self, prio, tag, fileno=None, **kwargs):
def __init__(self, prio, tag, original=None, **kwargs):
# Respect the -u option.
if original:
kwargs.setdefault("write_through", original.write_through)
fileno = original.fileno()
else:
fileno = None
# The default is surrogateescape for stdout and backslashreplace for
# stderr, but in the context of an Android log, readability is more
# important than reversibility.

View File

@@ -512,7 +512,7 @@ class _CallableGenericAlias(GenericAlias):
new_args = (t_args, t_result)
return _CallableGenericAlias(Callable, tuple(new_args))
# TODO: RUSTPYTHON patch for common call
# TODO: RUSTPYTHON; patch for common call
def __or__(self, other):
super().__or__(other)
@@ -1087,7 +1087,7 @@ class _DeprecateByteStringMeta(ABCMeta):
warnings._deprecated(
"collections.abc.ByteString",
remove=(3, 14),
remove=(3, 17),
)
return super().__new__(cls, name, bases, namespace, **kwargs)
@@ -1096,14 +1096,18 @@ class _DeprecateByteStringMeta(ABCMeta):
warnings._deprecated(
"collections.abc.ByteString",
remove=(3, 14),
remove=(3, 17),
)
return super().__instancecheck__(instance)
class ByteString(Sequence, metaclass=_DeprecateByteStringMeta):
"""This unifies bytes and bytearray.
"""Deprecated ABC serving as a common supertype of ``bytes`` and ``bytearray``.
XXX Should add all their methods.
This ABC is scheduled for removal in Python 3.17.
Use ``isinstance(obj, collections.abc.Buffer)`` to test if ``obj``
implements the buffer protocol at runtime. For use in type annotations,
either use ``Buffer`` or a union that explicitly specifies the types your
code supports (e.g., ``bytes | bytearray | memoryview``).
"""
__slots__ = ()

24
Lib/html/parser.py vendored
View File

@@ -146,6 +146,7 @@ class HTMLParser(_markupbase.ParserBase):
self.lasttag = '???'
self.interesting = interesting_normal
self.cdata_elem = None
self._support_cdata = True
self._escapable = True
super().reset()
@@ -183,6 +184,19 @@ class HTMLParser(_markupbase.ParserBase):
self.cdata_elem = None
self._escapable = True
def _set_support_cdata(self, flag=True):
"""Enable or disable support of the CDATA sections.
If enabled, "<[CDATA[" starts a CDATA section which ends with "]]>".
If disabled, "<[CDATA[" starts a bogus comments which ends with ">".
This method is not called by default. Its purpose is to be called
in custom handle_starttag() and handle_endtag() methods, with
value that depends on the adjusted current node.
See https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state
for details.
"""
self._support_cdata = flag
# Internal -- handle data as far as reasonable. May leave state
# and data to be processed by a subsequent call. If 'end' is
# true, force handling all data as if followed by EOF marker.
@@ -257,7 +271,7 @@ class HTMLParser(_markupbase.ParserBase):
j -= len(suffix)
break
self.handle_comment(rawdata[i+4:j])
elif startswith("<![CDATA[", i):
elif startswith("<![CDATA[", i) and self._support_cdata:
self.unknown_decl(rawdata[i+3:])
elif rawdata[i:i+9].lower() == '<!doctype':
self.handle_decl(rawdata[i+2:])
@@ -333,8 +347,12 @@ class HTMLParser(_markupbase.ParserBase):
if rawdata[i:i+4] == '<!--':
# this case is actually already handled in goahead()
return self.parse_comment(i)
elif rawdata[i:i+9] == '<![CDATA[':
return self.parse_marked_section(i)
elif rawdata[i:i+9] == '<![CDATA[' and self._support_cdata:
j = rawdata.find(']]>', i+9)
if j < 0:
return -1
self.unknown_decl(rawdata[i+3: j])
return j + 3
elif rawdata[i:i+9].lower() == '<!doctype':
# find the closing >
gtpos = rawdata.find('>', i+9)

View File

@@ -127,12 +127,13 @@ class ForkServer(object):
cmd = ('from multiprocessing.forkserver import main; ' +
'main(%d, %d, %r, **%r)')
main_kws = {}
if self._preload_modules:
desired_keys = {'main_path', 'sys_path'}
data = spawn.get_preparation_data('ignore')
data = {x: y for x, y in data.items() if x in desired_keys}
else:
data = {}
if 'sys_path' in data:
main_kws['sys_path'] = data['sys_path']
if 'init_main_from_path' in data:
main_kws['main_path'] = data['init_main_from_path']
with socket.socket(socket.AF_UNIX) as listener:
address = connection.arbitrary_address('AF_UNIX')
@@ -147,7 +148,7 @@ class ForkServer(object):
try:
fds_to_pass = [listener.fileno(), alive_r]
cmd %= (listener.fileno(), alive_r, self._preload_modules,
data)
main_kws)
exe = spawn.get_executable()
args = [exe] + util._args_from_interpreter_flags()
args += ['-c', cmd]
@@ -182,6 +183,10 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
except ImportError:
pass
# gh-135335: flush stdout/stderr in case any of the preloaded modules
# wrote to them, otherwise children might inherit buffered data
util._flush_std_streams()
util._close_stdin()
sig_r, sig_w = os.pipe()

View File

@@ -57,6 +57,10 @@ class Popen(popen_fork.Popen):
self._fds.extend([child_r, child_w])
self.pid = util.spawnv_passfds(spawn.get_executable(),
cmd, self._fds)
os.close(child_r)
child_r = None
os.close(child_w)
child_w = None
self.sentinel = parent_r
with open(parent_w, 'wb', closefd=False) as f:
f.write(fp.getbuffer())

View File

@@ -596,18 +596,22 @@ def get_platform():
isn't particularly important.
Examples of returned values:
linux-i586
linux-alpha (?)
solaris-2.6-sun4u
Windows will return one of:
win-amd64 (64-bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
win-arm64 (64-bit Windows on ARM64 (aka AArch64)
win32 (all others - specifically, sys.platform is returned)
For other non-POSIX platforms, currently just returns 'sys.platform'.
Windows:
"""
- win-amd64 (64-bit Windows on AMD64, aka x86_64, Intel64, and EM64T)
- win-arm64 (64-bit Windows on ARM64, aka AArch64)
- win32 (all others - specifically, sys.platform is returned)
POSIX based OS:
- linux-x86_64
- macosx-15.5-arm64
- macosx-26.0-universal2 (macOS on Apple Silicon or Intel)
- android-24-arm64_v8a
For other non-POSIX platforms, currently just returns :data:`sys.platform`."""
if os.name == 'nt':
if 'amd64' in sys.version.lower():
return 'win-amd64'

View File

@@ -6451,6 +6451,35 @@ class _TestSpawnedSysPath(BaseTestCase):
self.assertEqual(child_sys_path[1:], sys.path[1:])
self.assertIsNone(import_error, msg=f"child could not import {self._mod_name}")
def test_std_streams_flushed_after_preload(self):
# gh-135335: Check fork server flushes standard streams after
# preloading modules
if multiprocessing.get_start_method() != "forkserver":
self.skipTest("forkserver specific test")
# Create a test module in the temporary directory on the child's path
# TODO: This can all be simplified once gh-126631 is fixed and we can
# use __main__ instead of a module.
dirname = os.path.join(self._temp_dir, 'preloaded_module')
init_name = os.path.join(dirname, '__init__.py')
os.mkdir(dirname)
with open(init_name, "w") as f:
cmd = '''if 1:
import sys
print('stderr', end='', file=sys.stderr)
print('stdout', end='', file=sys.stdout)
'''
f.write(cmd)
name = os.path.join(os.path.dirname(__file__), 'mp_preload_flush.py')
env = {'PYTHONPATH': self._temp_dir}
_, out, err = test.support.script_helper.assert_python_ok(name, **env)
# Check stderr first, as it is more likely to be useful to see in the
# event of a failure.
self.assertEqual(err.decode().rstrip(), 'stderr')
self.assertEqual(out.decode().rstrip(), 'stdout')
class MiscTestCase(unittest.TestCase):
def test__all__(self):
@@ -6516,6 +6545,18 @@ class MiscTestCase(unittest.TestCase):
self.assertEqual(q.get_nowait(), "done")
close_queue(q)
def test_preload_main(self):
# gh-126631: Check that __main__ can be pre-loaded
if multiprocessing.get_start_method() != "forkserver":
self.skipTest("forkserver specific test")
name = os.path.join(os.path.dirname(__file__), 'mp_preload_main.py')
_, out, err = test.support.script_helper.assert_python_ok(name)
self.assertEqual(err, b'')
# The trailing empty string comes from split() on output ending with \n
out = out.decode().split("\n")
self.assertEqual(out, ['__main__', '__mp_main__', 'f', 'f', ''])
#
# Mixins

View File

@@ -2,13 +2,11 @@
Tests common to list and UserList.UserList
"""
import unittest
import sys
import os
from functools import cmp_to_key
from test import support, seq_tests
from test.support import ALWAYS_EQ, NEVER_EQ
from test import seq_tests
from test.support import ALWAYS_EQ, NEVER_EQ, get_c_recursion_limit
class CommonTest(seq_tests.CommonTest):
@@ -33,13 +31,13 @@ class CommonTest(seq_tests.CommonTest):
self.assertEqual(a, b)
def test_getitem_error(self):
a = []
a = self.type2test([])
msg = "list indices must be integers or slices"
with self.assertRaisesRegex(TypeError, msg):
a['a']
def test_setitem_error(self):
a = []
a = self.type2test([])
msg = "list indices must be integers or slices"
with self.assertRaisesRegex(TypeError, msg):
a['a'] = "python"
@@ -63,7 +61,7 @@ class CommonTest(seq_tests.CommonTest):
def test_repr_deep(self):
a = self.type2test([])
for i in range(sys.getrecursionlimit() + 100):
for i in range(get_c_recursion_limit() + 1):
a = self.type2test([a])
self.assertRaises(RecursionError, repr, a)
@@ -193,6 +191,14 @@ class CommonTest(seq_tests.CommonTest):
self.assertRaises(TypeError, a.__setitem__)
def test_slice_assign_iterator(self):
x = self.type2test(range(5))
x[0:3] = reversed(range(3))
self.assertEqual(x, self.type2test([2, 1, 0, 3, 4]))
x[:] = reversed(range(3))
self.assertEqual(x, self.type2test([2, 1, 0]))
def test_delslice(self):
a = self.type2test([0, 1])
del a[1:2]
@@ -552,7 +558,7 @@ class CommonTest(seq_tests.CommonTest):
class F(object):
def __iter__(self):
raise KeyboardInterrupt
self.assertRaises(KeyboardInterrupt, list, F())
self.assertRaises(KeyboardInterrupt, self.type2test, F())
def test_exhausted_iterator(self):
a = self.type2test([1, 2, 3])
@@ -564,3 +570,8 @@ class CommonTest(seq_tests.CommonTest):
self.assertEqual(list(exhit), [])
self.assertEqual(list(empit), [9])
self.assertEqual(a, self.type2test([1, 2, 3, 9]))
# gh-115733: Crash when iterating over exhausted iterator
exhit = iter(self.type2test([1, 2, 3]))
for _ in exhit:
next(exhit, 1)

14
Lib/test/mp_preload_main.py vendored Normal file
View File

@@ -0,0 +1,14 @@
import multiprocessing
print(f"{__name__}")
def f():
print("f")
if __name__ == "__main__":
ctx = multiprocessing.get_context("forkserver")
ctx.set_forkserver_preload(['__main__'])
for _ in range(2):
p = ctx.Process(target=f)
p.start()
p.join()

View File

@@ -145,6 +145,9 @@ class CommonTest(unittest.TestCase):
self.assertEqual(self.type2test(LyingTuple((2,))), self.type2test((1,)))
self.assertEqual(self.type2test(LyingList([2])), self.type2test([1]))
with self.assertRaises(TypeError):
self.type2test(unsupported_arg=[])
def test_truth(self):
self.assertFalse(self.type2test())
self.assertTrue(self.type2test([42]))
@@ -423,8 +426,8 @@ class CommonTest(unittest.TestCase):
self.assertEqual(lst2, lst)
self.assertNotEqual(id(lst2), id(lst))
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@support.suppress_immortalization()
def test_free_after_iterating(self):
support.check_free_after_iterating(self, iter, self.type2test)
support.check_free_after_iterating(self, reversed, self.type2test)

View File

@@ -305,6 +305,16 @@ def requires(resource, msg=None):
if resource == 'gui' and not _is_gui_available():
raise ResourceDenied(_is_gui_available.reason)
def _get_kernel_version(sysname="Linux"):
import platform
if platform.system() != sysname:
return None
version_txt = platform.release().split('-', 1)[0]
try:
return tuple(map(int, version_txt.split('.')))
except ValueError:
return None
def _requires_unix_version(sysname, min_version):
"""Decorator raising SkipTest if the OS is `sysname` and the version is less
than `min_version`.
@@ -501,8 +511,7 @@ def requires_lzma(reason='requires lzma'):
import lzma
except ImportError:
lzma = None
# XXX: RUSTPYTHON; xz is not supported yet
lzma = None
lzma = None # XXX: RUSTPYTHON; xz is not supported yet
return unittest.skipUnless(lzma, reason)
def has_no_debug_ranges():
@@ -521,25 +530,43 @@ def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
reason = e.args[0] if e.args else reason
return unittest.skipIf(skip, reason)
@contextlib.contextmanager
def suppress_immortalization(suppress=True):
"""Suppress immortalization of deferred objects."""
def can_use_suppress_immortalization(suppress=True):
"""Check if suppress_immortalization(suppress) can be used.
Use this helper in code where SkipTest must be eagerly handled.
"""
if not suppress:
return True
try:
import _testinternalcapi
except ImportError:
yield
return
return False
return True
@contextlib.contextmanager
def suppress_immortalization(suppress=True):
"""Suppress immortalization of deferred objects.
If _testinternalcapi is not available, the decorated test or class
is skipped. Use can_use_suppress_immortalization() outside test cases
to check if this decorator can be used.
"""
if not suppress:
yield
yield # no-op
return
from .import_helper import import_module
_testinternalcapi = import_module("_testinternalcapi")
_testinternalcapi.suppress_immortalization(True)
try:
yield
finally:
_testinternalcapi.suppress_immortalization(False)
def skip_if_suppress_immortalization():
try:
import _testinternalcapi
@@ -1645,7 +1672,7 @@ def check__all__(test_case, module, name_of_module=None, extra=(),
'module'.
The 'name_of_module' argument can specify (as a string or tuple thereof)
what module(s) an API could be defined in in order to be detected as a
what module(s) an API could be defined in order to be detected as a
public API. One case for this is when 'module' imports part of its public
API from other modules, possibly a C backend (like 'csv' and its '_csv').
@@ -2296,6 +2323,7 @@ def check_disallow_instantiation(testcase, tp, *args, **kwds):
qualname = f"{name}"
msg = f"cannot create '{re.escape(qualname)}' instances"
testcase.assertRaisesRegex(TypeError, msg, tp, *args, **kwds)
testcase.assertRaisesRegex(TypeError, msg, tp.__new__, tp, *args, **kwds)
def get_recursion_depth():
"""Get the recursion depth of the caller function.
@@ -2757,7 +2785,7 @@ def no_color():
from .os_helper import EnvironmentVarGuard
with (
swap_attr(_colorize, "can_colorize", lambda file=None: False),
swap_attr(_colorize, "can_colorize", lambda *, file=None: False),
EnvironmentVarGuard() as env,
):
env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS")

110
Lib/test/test_bytes.py vendored
View File

@@ -201,8 +201,7 @@ class BaseBytesTest:
self.assertRaises(ValueError, self.type2test, [sys.maxsize+1])
self.assertRaises(ValueError, self.type2test, [10**100])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@bigaddrspacetest
def test_constructor_overflow(self):
size = MAX_Py_ssize_t
@@ -326,8 +325,7 @@ class BaseBytesTest:
# Default encoding is utf-8
self.assertEqual(self.type2test(b'\xe2\x98\x83').decode(), '\u2603')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_check_encoding_errors(self):
# bpo-37388: bytes(str) and bytes.encode() must check encoding
# and errors arguments in dev mode
@@ -972,8 +970,7 @@ class BaseBytesTest:
self.assertRaises(ValueError, method, 256)
self.assertRaises(ValueError, method, 9999)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_find_etc_raise_correct_error_messages(self):
# issue 11828
b = self.type2test(b'hello')
@@ -993,8 +990,7 @@ class BaseBytesTest:
self.assertRaisesRegex(TypeError, r'\bendswith\b', b.endswith,
x, None, None, None)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_free_after_iterating(self):
test.support.check_free_after_iterating(self, iter, self.type2test)
test.support.check_free_after_iterating(self, reversed, self.type2test)
@@ -1845,6 +1841,8 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
self.assertEqual(b3, b'xcxcxc')
def test_mutating_index(self):
# bytearray slice assignment can call into python code
# that reallocates the internal buffer
# See gh-91153
class Boom:
@@ -1862,22 +1860,82 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
with self.assertRaises(IndexError):
self._testlimitedcapi.sequence_setitem(b, 0, Boom())
def test_mutating_index_inbounds(self):
# gh-91153 continued
# Ensure buffer is not broken even if length is correct
class MutatesOnIndex:
def __init__(self):
self.ba = bytearray(0x180)
def __index__(self):
self.ba.clear()
self.new_ba = bytearray(0x180) # to catch out-of-bounds writes
self.ba.extend([0] * 0x180) # to check bounds checks
return 0
with self.subTest("skip_bounds_safety"):
instance = MutatesOnIndex()
instance.ba[instance] = ord("?")
self.assertEqual(instance.ba[0], ord("?"), "Assigned bytearray not altered")
self.assertEqual(instance.new_ba, bytearray(0x180), "Wrong object altered")
with self.subTest("skip_bounds_safety_capi"):
instance = MutatesOnIndex()
instance.ba[instance] = ord("?")
self._testlimitedcapi.sequence_setitem(instance.ba, instance, ord("?"))
self.assertEqual(instance.ba[0], ord("?"), "Assigned bytearray not altered")
self.assertEqual(instance.new_ba, bytearray(0x180), "Wrong object altered")
with self.subTest("skip_bounds_safety_slice"):
instance = MutatesOnIndex()
instance.ba[instance:1] = [ord("?")]
self.assertEqual(instance.ba[0], ord("?"), "Assigned bytearray not altered")
self.assertEqual(instance.new_ba, bytearray(0x180), "Wrong object altered")
class AssortedBytesTest(unittest.TestCase):
#
# Test various combinations of bytes and bytearray
#
def test_bytes_repr(self, f=repr):
self.assertEqual(f(b''), "b''")
self.assertEqual(f(b"abc"), "b'abc'")
self.assertEqual(f(bytes([92])), r"b'\\'")
self.assertEqual(f(bytes([0, 1, 254, 255])), r"b'\x00\x01\xfe\xff'")
self.assertEqual(f(b'\a\b\t\n\v\f\r'), r"b'\x07\x08\t\n\x0b\x0c\r'")
self.assertEqual(f(b'"'), """b'"'""") # '"'
self.assertEqual(f(b"'"), '''b"'"''') # "'"
self.assertEqual(f(b"'\""), r"""b'\'"'""") # '\'"'
self.assertEqual(f(b"\"'\""), r"""b'"\'"'""") # '"\'"'
self.assertEqual(f(b"'\"'"), r"""b'\'"\''""") # '\'"\''
self.assertEqual(f(BytesSubclass(b"abc")), "b'abc'")
def test_bytearray_repr(self, f=repr):
self.assertEqual(f(bytearray()), "bytearray(b'')")
self.assertEqual(f(bytearray(b'abc')), "bytearray(b'abc')")
self.assertEqual(f(bytearray([92])), r"bytearray(b'\\')")
self.assertEqual(f(bytearray([0, 1, 254, 255])),
r"bytearray(b'\x00\x01\xfe\xff')")
self.assertEqual(f(bytearray([7, 8, 9, 10, 11, 12, 13])),
r"bytearray(b'\x07\x08\t\n\x0b\x0c\r')")
self.assertEqual(f(bytearray(b'"')), """bytearray(b'"')""") # '"'
self.assertEqual(f(bytearray(b"'")), r'''bytearray(b"\'")''') # "\'"
self.assertEqual(f(bytearray(b"'\"")), r"""bytearray(b'\'"')""") # '\'"'
self.assertEqual(f(bytearray(b"\"'\"")), r"""bytearray(b'"\'"')""") # '"\'"'
self.assertEqual(f(bytearray(b'\'"\'')), r"""bytearray(b'\'"\'')""") # '\'"\''
self.assertEqual(f(ByteArraySubclass(b"abc")), "ByteArraySubclass(b'abc')")
self.assertEqual(f(ByteArraySubclass.Nested(b"abc")), "Nested(b'abc')")
self.assertEqual(f(ByteArraySubclass.Ŭñıçöđë(b"abc")), "Ŭñıçöđë(b'abc')")
@check_bytes_warnings
def test_repr_str(self):
for f in str, repr:
self.assertEqual(f(bytearray()), "bytearray(b'')")
self.assertEqual(f(bytearray([0])), "bytearray(b'\\x00')")
self.assertEqual(f(bytearray([0, 1, 254, 255])),
"bytearray(b'\\x00\\x01\\xfe\\xff')")
self.assertEqual(f(b"abc"), "b'abc'")
self.assertEqual(f(b"'"), '''b"'"''') # '''
self.assertEqual(f(b"'\""), r"""b'\'"'""") # '
def test_bytes_str(self):
self.test_bytes_repr(str)
@check_bytes_warnings
def test_bytearray_str(self):
self.test_bytearray_repr(str)
@check_bytes_warnings
def test_format(self):
@@ -1930,15 +1988,6 @@ class AssortedBytesTest(unittest.TestCase):
b = bytearray(buf)
self.assertEqual(b, bytearray(sample))
@check_bytes_warnings
def test_to_str(self):
self.assertEqual(str(b''), "b''")
self.assertEqual(str(b'x'), "b'x'")
self.assertEqual(str(b'\x80'), "b'\\x80'")
self.assertEqual(str(bytearray(b'')), "bytearray(b'')")
self.assertEqual(str(bytearray(b'x')), "bytearray(b'x')")
self.assertEqual(str(bytearray(b'\x80')), "bytearray(b'\\x80')")
def test_literal(self):
tests = [
(b"Wonderful spam", "Wonderful spam"),
@@ -2089,7 +2138,7 @@ class SubclassTest:
s3 = s1.join([b"abcd"])
self.assertIs(type(s3), self.basetype)
@unittest.skip("TODO: RUSTPYTHON, Fails on ByteArraySubclassWithSlotsTest")
@unittest.skip('TODO: RUSTPYTHON; Fails on ByteArraySubclassWithSlotsTest')
def test_pickle(self):
a = self.type2test(b"abcd")
a.x = 10
@@ -2104,7 +2153,7 @@ class SubclassTest:
self.assertEqual(type(a.z), type(b.z))
self.assertFalse(hasattr(b, 'y'))
@unittest.skip("TODO: RUSTPYTHON, Fails on ByteArraySubclassWithSlotsTest")
@unittest.skip('TODO: RUSTPYTHON; Fails on ByteArraySubclassWithSlotsTest')
def test_copy(self):
a = self.type2test(b"abcd")
a.x = 10
@@ -2148,7 +2197,10 @@ class SubclassTest:
class ByteArraySubclass(bytearray):
pass
class Nested(bytearray):
pass
class Ŭñıçöđë(bytearray):
pass
class ByteArraySubclassWithSlots(bytearray):
__slots__ = ('x', 'y', '__dict__')

View File

@@ -29,6 +29,16 @@ class TestWithAscii(unittest.TestCase):
('delete', 40, 41, 40, 40),
('equal', 41, 81, 40, 80)])
def test_opcode_caching(self):
sm = difflib.SequenceMatcher(None, 'b' * 100, 'a' + 'b' * 100)
opcode = sm.get_opcodes()
self.assertEqual(opcode,
[ ('insert', 0, 0, 0, 1),
('equal', 0, 100, 1, 101)])
# Implementation detail: opcodes are cached;
# `get_opcodes()` returns the same object
self.assertIs(opcode, sm.get_opcodes())
def test_bjunk(self):
sm = difflib.SequenceMatcher(isjunk=lambda x: x == ' ',
a='a' * 40 + 'b' * 40, b='a' * 44 + 'b' * 40)
@@ -273,6 +283,15 @@ class TestSFpatches(unittest.TestCase):
self.assertIn('&#305;mpl&#305;c&#305;t', output)
def test_one_insert(self):
m = difflib.Differ().compare('b' * 2, 'a' + 'b' * 2)
self.assertEqual(list(m), ['+ a', ' b', ' b'])
def test_one_delete(self):
m = difflib.Differ().compare('a' + 'b' * 2, 'b' * 2)
self.assertEqual(list(m), ['- a', ' b', ' b'])
class TestOutputFormat(unittest.TestCase):
def test_tab_delimiter(self):
args = ['one', 'two', 'Original', 'Current',
@@ -547,6 +566,26 @@ class TestFindLongest(unittest.TestCase):
self.assertFalse(self.longer_match_exists(a, b, match.size))
class TestCloseMatches(unittest.TestCase):
# Happy paths are tested in the doctests of `difflib.get_close_matches`.
def test_invalid_inputs(self):
self.assertRaises(ValueError, difflib.get_close_matches, "spam", ['egg'], n=0)
self.assertRaises(ValueError, difflib.get_close_matches, "spam", ['egg'], n=-1)
self.assertRaises(ValueError, difflib.get_close_matches, "spam", ['egg'], cutoff=1.1)
self.assertRaises(ValueError, difflib.get_close_matches, "spam", ['egg'], cutoff=-0.1)
class TestRestore(unittest.TestCase):
# Happy paths are tested in the doctests of `difflib.restore`.
def test_invalid_input(self):
with self.assertRaises(ValueError):
''.join(difflib.restore([], 0))
with self.assertRaises(ValueError):
''.join(difflib.restore([], 3))
def setUpModule():
difflib.HtmlDiff._default_prefix = 0

View File

@@ -60,8 +60,7 @@ class ExceptionTests(unittest.TestCase):
self.assertEqual(buf1, buf2)
self.assertEqual(exc.__name__, excname)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def testRaising(self):
self.raise_catch(AttributeError, "AttributeError")
self.assertRaises(AttributeError, getattr, sys, "undefined_attribute")
@@ -146,8 +145,7 @@ class ExceptionTests(unittest.TestCase):
self.raise_catch(StopAsyncIteration, "StopAsyncIteration")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def testSyntaxErrorMessage(self):
# make sure the right exception message is raised for each of
# these code fragments
@@ -172,8 +170,7 @@ class ExceptionTests(unittest.TestCase):
ckmsg("continue\n", "'continue' not properly in loop")
ckmsg("f'{6 0}'", "invalid syntax. Perhaps you forgot a comma?")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def testSyntaxErrorMissingParens(self):
def ckmsg(src, msg, exception=SyntaxError):
try:
@@ -232,14 +229,12 @@ class ExceptionTests(unittest.TestCase):
line = src.split('\n')[lineno-1]
self.assertIn(line, cm.exception.text)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_error_offset_continuation_characters(self):
check = self.check
check('"\\\n"(1 for c in I,\\\n\\', 2, 2)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def testSyntaxErrorOffset(self):
check = self.check
check('def fact(x):\n\treturn x!\n', 2, 10)
@@ -443,8 +438,7 @@ class ExceptionTests(unittest.TestCase):
with self.assertRaisesRegex(OSError, 'Windows Error 0x%x' % code):
ctypes.pythonapi.PyErr_SetFromWindowsErr(code)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def testAttributes(self):
# test that exception attributes are happy
@@ -607,8 +601,7 @@ class ExceptionTests(unittest.TestCase):
with self.assertRaisesRegex(TypeError, "state is not a dictionary"):
e.__setstate__(42)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_notes(self):
for e in [BaseException(1), Exception(2), ValueError(3)]:
with self.subTest(e=e):
@@ -665,8 +658,7 @@ class ExceptionTests(unittest.TestCase):
else:
self.fail("No exception raised")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_invalid_setattr(self):
TE = TypeError
exc = Exception()
@@ -679,8 +671,7 @@ class ExceptionTests(unittest.TestCase):
msg = "exception context must be None or derive from BaseException"
self.assertRaisesRegex(TE, msg, setattr, exc, '__context__', 1)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_invalid_delattr(self):
TE = TypeError
try:
@@ -752,8 +743,8 @@ class ExceptionTests(unittest.TestCase):
x = DerivedException(fancy_arg=42)
self.assertEqual(x.fancy_arg, 42)
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; Windows')
@no_tracing
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON Windows')
def testInfiniteRecursion(self):
def f():
return f()
@@ -1161,8 +1152,7 @@ class ExceptionTests(unittest.TestCase):
self.assertIs(c.__context__, b)
self.assertIsNone(b.__context__)
# TODO: RUSTPYTHON
@unittest.skip("Infinite loop")
@unittest.skip("TODO: RUSTPYTHON; Infinite loop")
def test_no_hang_on_context_chain_cycle1(self):
# See issue 25782. Cycle in context chain.
@@ -1218,8 +1208,7 @@ class ExceptionTests(unittest.TestCase):
self.assertIs(b.__context__, a)
self.assertIs(a.__context__, c)
# TODO: RUSTPYTHON
@unittest.skip("Infinite loop")
@unittest.skip("TODO: RUSTPYTHON; Infinite loop")
def test_no_hang_on_context_chain_cycle3(self):
# See issue 25782. Longer context chain with cycle.
@@ -1317,8 +1306,7 @@ class ExceptionTests(unittest.TestCase):
self.assertIs(exc, oe)
self.assertIs(exc.__context__, ve)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_unicode_change_attributes(self):
# See issue 7309. This was a crasher.
@@ -1362,8 +1350,7 @@ class ExceptionTests(unittest.TestCase):
for klass in klasses:
self.assertEqual(str(klass.__new__(klass)), "")
# TODO: RUSTPYTHON; OverflowError: Python int too large to convert to Rust usize
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; OverflowError: Python int too large to convert to Rust usize
def test_unicode_error_str_does_not_crash(self):
# Test that str(UnicodeError(...)) does not crash.
# See https://github.com/python/cpython/issues/123378.
@@ -1387,8 +1374,8 @@ class ExceptionTests(unittest.TestCase):
exc = UnicodeDecodeError('utf-8', encoded, start, end, '')
self.assertIsInstance(str(exc), str)
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; Windows')
@no_tracing
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON Windows')
def test_badisinstance(self):
# Bug #2542: if issubclass(e, MyException) raises an exception,
# it should be ignored
@@ -1669,7 +1656,7 @@ class ExceptionTests(unittest.TestCase):
gc_collect() # For PyPy or other GCs.
self.assertEqual(wr(), None)
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON Windows')
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; Windows')
@no_tracing
def test_recursion_error_cleanup(self):
# Same test as above, but with "recursion exceeded" errors
@@ -1691,7 +1678,7 @@ class ExceptionTests(unittest.TestCase):
gc_collect() # For PyPy or other GCs.
self.assertEqual(wr(), None)
@unittest.skipIf(sys.platform == 'win32', 'error specific to cpython')
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; error specific to cpython')
def test_errno_ENOTDIR(self):
# Issue #12802: "not a directory" errors are ENOTDIR even on Windows
with self.assertRaises(OSError) as cm:
@@ -1714,8 +1701,7 @@ class ExceptionTests(unittest.TestCase):
self.assertEqual(cm.unraisable.object, BrokenDel.__del__)
self.assertIsNotNone(cm.unraisable.exc_traceback)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_unhandled(self):
# Check for sensible reporting of unhandled exceptions
for exc_type in (ValueError, BrokenStrException):
@@ -1814,8 +1800,7 @@ class ExceptionTests(unittest.TestCase):
next(i)
next(i)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.skipUnless(__debug__, "Won't work if __debug__ is False")
def test_assert_shadowing(self):
# Shadowing AssertionError would cause the assert statement to
@@ -1877,6 +1862,38 @@ class ExceptionTests(unittest.TestCase):
rc, _, err = script_helper.assert_python_ok("-c", code)
self.assertIn(b'MemoryError', err)
@cpython_only
# Python built with Py_TRACE_REFS fail with a fatal error in
# _PyRefchain_Trace() on memory allocation error.
@unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build')
def test_exec_set_nomemory_hang(self):
import_module("_testcapi")
# gh-134163: A MemoryError inside code that was wrapped by a try/except
# block would lead to an infinite loop.
# The frame_lasti needs to be greater than 257 to prevent
# PyLong_FromLong() from returning cached integers, which
# don't require a memory allocation. Prepend some dummy code
# to artificially increase the instruction index.
warmup_code = "a = list(range(0, 1))\n" * 20
user_input = warmup_code + dedent("""
try:
import _testcapi
_testcapi.set_nomemory(0)
b = list(range(1000, 2000))
except Exception as e:
import traceback
traceback.print_exc()
""")
with SuppressCrashReport():
with script_helper.spawn_python('-c', user_input) as p:
p.wait()
output = p.stdout.read()
self.assertIn(p.returncode, (0, 1))
self.assertGreater(len(output), 0) # At minimum, should not hang
self.assertIn(b"MemoryError", output)
class NameErrorTests(unittest.TestCase):
def test_name_error_has_name(self):
@@ -1973,8 +1990,7 @@ class AttributeErrorTests(unittest.TestCase):
class ImportErrorTests(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_attributes(self):
# Setting 'name' and 'path' should not be a problem.
exc = ImportError('test')
@@ -2064,8 +2080,7 @@ class AssertionErrorTests(unittest.TestCase):
def tearDown(self):
unlink(TESTFN)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@force_not_colorized
def test_assertion_error_location(self):
cases = [
@@ -2164,8 +2179,7 @@ class AssertionErrorTests(unittest.TestCase):
result = run_script(source)
self.assertEqual(result[-3:], expected)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@force_not_colorized
def test_multiline_not_highlighted(self):
cases = [
@@ -2202,8 +2216,7 @@ class AssertionErrorTests(unittest.TestCase):
class SyntaxErrorTests(unittest.TestCase):
maxDiff = None
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@force_not_colorized
def test_range_of_offsets(self):
cases = [
@@ -2310,8 +2323,7 @@ class SyntaxErrorTests(unittest.TestCase):
^^^^^
""", err.getvalue())
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_encodings(self):
self.addCleanup(unlink, TESTFN)
source = (
@@ -2328,16 +2340,14 @@ class SyntaxErrorTests(unittest.TestCase):
self.assertEqual(err[-3], ' (')
self.assertEqual(err[-2], ' ^')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_non_utf8(self):
# Check non utf-8 characters
self.addCleanup(unlink, TESTFN)
err = run_script(b"\x89")
self.assertIn("SyntaxError: Non-UTF-8 code starting with '\\x89' in file", err[-1])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_string_source(self):
def try_compile(source):
with self.assertRaises(SyntaxError) as cm:
@@ -2380,8 +2390,7 @@ class SyntaxErrorTests(unittest.TestCase):
self.assertEqual(exc.offset, 1)
self.assertEqual(exc.end_offset, 12)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_file_source(self):
self.addCleanup(unlink, TESTFN)
err = run_script('return "ä"')
@@ -2444,8 +2453,7 @@ class SyntaxErrorTests(unittest.TestCase):
self.assertEqual(error, the_exception.text)
self.assertEqual("bad bad", the_exception.msg)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_incorrect_constructor(self):
args = ("bad.py", 1, 2)
self.assertRaises(TypeError, SyntaxError, "bad bad", args)
@@ -2507,8 +2515,7 @@ class PEP626Tests(unittest.TestCase):
pass
self.lineno_after_raise(in_except, 4)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_lineno_after_other_except(self):
def other_except():
try:
@@ -2526,8 +2533,7 @@ class PEP626Tests(unittest.TestCase):
pass
self.lineno_after_raise(in_named_except, 4)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_lineno_in_try(self):
def in_try():
try:
@@ -2554,8 +2560,7 @@ class PEP626Tests(unittest.TestCase):
pass
self.lineno_after_raise(in_finally_except, 4)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_lineno_after_with(self):
class Noop:
def __enter__(self):
@@ -2568,8 +2573,7 @@ class PEP626Tests(unittest.TestCase):
pass
self.lineno_after_raise(after_with, 2)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_missing_lineno_shows_as_none(self):
def f():
1/0

View File

@@ -2,6 +2,7 @@
import unittest
import pickle
from array import array
import copy
from collections import (
defaultdict, deque, OrderedDict, Counter, UserDict, UserList
@@ -11,8 +12,11 @@ from concurrent.futures import Future
from concurrent.futures.thread import _WorkItem
from contextlib import AbstractContextManager, AbstractAsyncContextManager
from contextvars import ContextVar, Token
from csv import DictReader, DictWriter
from dataclasses import Field
from functools import partial, partialmethod, cached_property
from graphlib import TopologicalSorter
from logging import LoggerAdapter, StreamHandler
from mailbox import Mailbox, _PartialFile
try:
import ctypes
@@ -23,29 +27,73 @@ from filecmp import dircmp
from fileinput import FileInput
from itertools import chain
from http.cookies import Morsel
from multiprocessing.managers import ValueProxy
from multiprocessing.pool import ApplyResult
try:
from multiprocessing.managers import ValueProxy, DictProxy, ListProxy
from multiprocessing.pool import ApplyResult
from multiprocessing.queues import SimpleQueue as MPSimpleQueue
from multiprocessing.queues import Queue as MPQueue
from multiprocessing.queues import JoinableQueue as MPJoinableQueue
except ImportError:
# _multiprocessing module is optional
ValueProxy = None
DictProxy = None
ListProxy = None
ApplyResult = None
MPSimpleQueue = None
MPQueue = None
MPJoinableQueue = None
try:
from multiprocessing.shared_memory import ShareableList
except ImportError:
# multiprocessing.shared_memory is not available on e.g. Android
ShareableList = None
from multiprocessing.queues import SimpleQueue as MPSimpleQueue
from os import DirEntry
from re import Pattern, Match
from types import GenericAlias, MappingProxyType, AsyncGeneratorType
from types import GenericAlias, MappingProxyType, AsyncGeneratorType, CoroutineType, GeneratorType
from tempfile import TemporaryDirectory, SpooledTemporaryFile
from urllib.parse import SplitResult, ParseResult
from unittest.case import _AssertRaisesContext
from queue import Queue, SimpleQueue
from weakref import WeakSet, ReferenceType, ref
import typing
from typing import Unpack
from typing import TypeVar
T = TypeVar('T')
K = TypeVar('K')
V = TypeVar('V')
_UNPACKED_TUPLES = [
# Unpacked tuple using `*`
(*tuple[int],)[0],
(*tuple[T],)[0],
(*tuple[int, str],)[0],
(*tuple[int, ...],)[0],
(*tuple[T, ...],)[0],
tuple[*tuple[int, ...]],
tuple[*tuple[T, ...]],
tuple[str, *tuple[int, ...]],
tuple[*tuple[int, ...], str],
tuple[float, *tuple[int, ...], str],
tuple[*tuple[*tuple[int, ...]]],
# Unpacked tuple using `Unpack`
Unpack[tuple[int]],
Unpack[tuple[T]],
Unpack[tuple[int, str]],
Unpack[tuple[int, ...]],
Unpack[tuple[T, ...]],
tuple[Unpack[tuple[int, ...]]],
tuple[Unpack[tuple[T, ...]]],
tuple[str, Unpack[tuple[int, ...]]],
tuple[Unpack[tuple[int, ...]], str],
tuple[float, Unpack[tuple[int, ...]], str],
tuple[Unpack[tuple[Unpack[tuple[int, ...]]]]],
# Unpacked tuple using `*` AND `Unpack`
tuple[Unpack[tuple[*tuple[int, ...]]]],
tuple[*tuple[Unpack[tuple[int, ...]]]],
]
class BaseTest(unittest.TestCase):
"""Test basics."""
generic_types = [type, tuple, list, dict, set, frozenset, enumerate,
@@ -56,6 +104,7 @@ class BaseTest(unittest.TestCase):
OrderedDict, Counter, UserDict, UserList,
Pattern, Match,
partial, partialmethod, cached_property,
TopologicalSorter,
AbstractContextManager, AbstractAsyncContextManager,
Awaitable, Coroutine,
AsyncIterable, AsyncIterator,
@@ -71,19 +120,25 @@ class BaseTest(unittest.TestCase):
KeysView, ItemsView, ValuesView,
Sequence, MutableSequence,
MappingProxyType, AsyncGeneratorType,
GeneratorType, CoroutineType,
DirEntry,
chain,
LoggerAdapter, StreamHandler,
TemporaryDirectory, SpooledTemporaryFile,
Queue, SimpleQueue,
_AssertRaisesContext,
SplitResult, ParseResult,
ValueProxy, ApplyResult,
WeakSet, ReferenceType, ref,
ShareableList, MPSimpleQueue,
ShareableList,
Future, _WorkItem,
Morsel]
Morsel,
DictReader, DictWriter,
array]
if ctypes is not None:
generic_types.extend((ctypes.Array, ctypes.LibraryLoader))
if ValueProxy is not None:
generic_types.extend((ValueProxy, DictProxy, ListProxy, ApplyResult,
MPSimpleQueue, MPQueue, MPJoinableQueue))
def test_subscriptable(self):
for t in self.generic_types:
@@ -96,11 +151,12 @@ class BaseTest(unittest.TestCase):
self.assertEqual(alias.__args__, (int,))
self.assertEqual(alias.__parameters__, ())
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_unsubscriptable(self):
for t in int, str, float, Sized, Hashable:
tname = t.__name__
with self.subTest(f"Testing {tname}"):
with self.assertRaises(TypeError):
with self.assertRaisesRegex(TypeError, tname):
t[int]
def test_instantiate(self):
@@ -154,15 +210,30 @@ class BaseTest(unittest.TestCase):
self.assertEqual(t.__args__, (int,))
self.assertEqual(t.__parameters__, ())
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_repr(self):
class MyList(list):
pass
class MyGeneric:
__class_getitem__ = classmethod(GenericAlias)
self.assertEqual(repr(list[str]), 'list[str]')
self.assertEqual(repr(list[()]), 'list[()]')
self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
x1 = tuple[*tuple[int]]
self.assertEqual(repr(x1), 'tuple[*tuple[int]]')
x2 = tuple[*tuple[int, str]]
self.assertEqual(repr(x2), 'tuple[*tuple[int, str]]')
x3 = tuple[*tuple[int, ...]]
self.assertEqual(repr(x3), 'tuple[*tuple[int, ...]]')
self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
# gh-105488
self.assertTrue(repr(MyGeneric[int]).endswith('MyGeneric[int]'))
self.assertTrue(repr(MyGeneric[[]]).endswith('MyGeneric[[]]'))
self.assertTrue(repr(MyGeneric[[int, str]]).endswith('MyGeneric[[int, str]]'))
def test_exposed_type(self):
import types
a = types.GenericAlias(list, int)
@@ -173,6 +244,7 @@ class BaseTest(unittest.TestCase):
def test_parameters(self):
from typing import List, Dict, Callable
D0 = dict[str, int]
self.assertEqual(D0.__args__, (str, int))
self.assertEqual(D0.__parameters__, ())
@@ -188,6 +260,7 @@ class BaseTest(unittest.TestCase):
D2b = dict[T, T]
self.assertEqual(D2b.__args__, (T, T))
self.assertEqual(D2b.__parameters__, (T,))
L0 = list[str]
self.assertEqual(L0.__args__, (str,))
self.assertEqual(L0.__parameters__, ())
@@ -210,6 +283,27 @@ class BaseTest(unittest.TestCase):
self.assertEqual(L5.__args__, (Callable[[K, V], K],))
self.assertEqual(L5.__parameters__, (K, V))
T1 = tuple[*tuple[int]]
self.assertEqual(
T1.__args__,
(*tuple[int],),
)
self.assertEqual(T1.__parameters__, ())
T2 = tuple[*tuple[T]]
self.assertEqual(
T2.__args__,
(*tuple[T],),
)
self.assertEqual(T2.__parameters__, (T,))
T4 = tuple[*tuple[int, str]]
self.assertEqual(
T4.__args__,
(*tuple[int, str],),
)
self.assertEqual(T4.__parameters__, ())
def test_parameter_chaining(self):
from typing import List, Dict, Union, Callable
self.assertEqual(list[T][int], list[int])
@@ -233,16 +327,24 @@ class BaseTest(unittest.TestCase):
with self.assertRaises(TypeError):
list[int][int]
with self.assertRaises(TypeError):
dict[T, int][str, int]
with self.assertRaises(TypeError):
dict[str, T][str, int]
with self.assertRaises(TypeError):
dict[T, T][str, int]
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_equality(self):
self.assertEqual(list[int], list[int])
self.assertEqual(dict[str, int], dict[str, int])
self.assertEqual((*tuple[int],)[0], (*tuple[int],)[0])
self.assertEqual(tuple[*tuple[int]], tuple[*tuple[int]])
self.assertNotEqual(dict[str, int], dict[str, str])
self.assertNotEqual(list, list[int])
self.assertNotEqual(list[int], list)
self.assertNotEqual(list[int], tuple[int])
self.assertNotEqual((*tuple[int],)[0], tuple[int])
def test_isinstance(self):
self.assertTrue(isinstance([], list))
@@ -263,20 +365,24 @@ class BaseTest(unittest.TestCase):
self.assertEqual(t(test), Test)
self.assertEqual(t(0), int)
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_type_subclass_generic(self):
class MyType(type):
pass
with self.assertRaises(TypeError):
with self.assertRaisesRegex(TypeError, 'MyType'):
MyType[int]
def test_pickle(self):
alias = GenericAlias(list, T)
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
s = pickle.dumps(alias, proto)
loaded = pickle.loads(s)
self.assertEqual(loaded.__origin__, alias.__origin__)
self.assertEqual(loaded.__args__, alias.__args__)
self.assertEqual(loaded.__parameters__, alias.__parameters__)
aliases = [GenericAlias(list, T)] + _UNPACKED_TUPLES
for alias in aliases:
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(alias=alias, proto=proto):
s = pickle.dumps(alias, proto)
loaded = pickle.loads(s)
self.assertEqual(loaded.__origin__, alias.__origin__)
self.assertEqual(loaded.__args__, alias.__args__)
self.assertEqual(loaded.__parameters__, alias.__parameters__)
self.assertEqual(type(loaded), type(alias))
def test_copy(self):
class X(list):
@@ -285,16 +391,30 @@ class BaseTest(unittest.TestCase):
def __deepcopy__(self, memo):
return self
for origin in list, deque, X:
alias = GenericAlias(origin, T)
copied = copy.copy(alias)
self.assertEqual(copied.__origin__, alias.__origin__)
self.assertEqual(copied.__args__, alias.__args__)
self.assertEqual(copied.__parameters__, alias.__parameters__)
copied = copy.deepcopy(alias)
self.assertEqual(copied.__origin__, alias.__origin__)
self.assertEqual(copied.__args__, alias.__args__)
self.assertEqual(copied.__parameters__, alias.__parameters__)
aliases = [
GenericAlias(list, T),
GenericAlias(deque, T),
GenericAlias(X, T),
X[T],
list[T],
deque[T],
] + _UNPACKED_TUPLES
for alias in aliases:
with self.subTest(alias=alias):
copied = copy.copy(alias)
self.assertEqual(copied.__origin__, alias.__origin__)
self.assertEqual(copied.__args__, alias.__args__)
self.assertEqual(copied.__parameters__, alias.__parameters__)
copied = copy.deepcopy(alias)
self.assertEqual(copied.__origin__, alias.__origin__)
self.assertEqual(copied.__args__, alias.__args__)
self.assertEqual(copied.__parameters__, alias.__parameters__)
def test_unpack(self):
alias = tuple[str, ...]
self.assertIs(alias.__unpacked__, False)
unpacked = (*alias,)[0]
self.assertIs(unpacked.__unpacked__, True)
def test_union(self):
a = typing.Union[list[int], list[str]]
@@ -306,11 +426,28 @@ class BaseTest(unittest.TestCase):
self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
self.assertEqual(a.__parameters__, (T,))
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_dir(self):
dir_of_gen_alias = set(dir(list[int]))
ga = list[int]
dir_of_gen_alias = set(dir(ga))
self.assertTrue(dir_of_gen_alias.issuperset(dir(list)))
for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
self.assertIn(generic_alias_property, dir_of_gen_alias)
for generic_alias_property in (
"__origin__", "__args__", "__parameters__",
"__unpacked__",
):
with self.subTest(generic_alias_property=generic_alias_property):
self.assertIn(generic_alias_property, dir_of_gen_alias)
for blocked in (
"__bases__",
"__copy__",
"__deepcopy__",
):
with self.subTest(blocked=blocked):
self.assertNotIn(blocked, dir_of_gen_alias)
for entry in dir_of_gen_alias:
with self.subTest(entry=entry):
getattr(ga, entry) # must not raise `AttributeError`
def test_weakref(self):
for t in self.generic_types:
@@ -337,6 +474,44 @@ class BaseTest(unittest.TestCase):
with self.assertRaises(TypeError):
Bad(list, int, bad=int)
def test_iter_creates_starred_tuple(self):
t = tuple[int, str]
iter_t = iter(t)
x = next(iter_t)
self.assertEqual(repr(x), '*tuple[int, str]')
def test_calling_next_twice_raises_stopiteration(self):
t = tuple[int, str]
iter_t = iter(t)
next(iter_t)
with self.assertRaises(StopIteration):
next(iter_t)
def test_del_iter(self):
t = tuple[int, str]
iter_x = iter(t)
del iter_x
class TypeIterationTests(unittest.TestCase):
_UNITERABLE_TYPES = (list, tuple)
def test_cannot_iterate(self):
for test_type in self._UNITERABLE_TYPES:
with self.subTest(type=test_type):
expected_error_regex = "object is not iterable"
with self.assertRaisesRegex(TypeError, expected_error_regex):
iter(test_type)
with self.assertRaisesRegex(TypeError, expected_error_regex):
list(test_type)
with self.assertRaisesRegex(TypeError, expected_error_regex):
for _ in test_type:
pass
def test_is_not_instance_of_iterable(self):
for type_to_test in self._UNITERABLE_TYPES:
self.assertNotIsInstance(type_to_test, Iterable)
if __name__ == "__main__":
unittest.main()

View File

@@ -10,10 +10,13 @@ from test import support
class EventCollector(html.parser.HTMLParser):
def __init__(self, *args, **kw):
def __init__(self, *args, autocdata=False, **kw):
self.autocdata = autocdata
self.events = []
self.append = self.events.append
html.parser.HTMLParser.__init__(self, *args, **kw)
if autocdata:
self._set_support_cdata(False)
def get_events(self):
# Normalize the list of events so that buffer artefacts don't
@@ -34,12 +37,16 @@ class EventCollector(html.parser.HTMLParser):
def handle_starttag(self, tag, attrs):
self.append(("starttag", tag, attrs))
if self.autocdata and tag == 'svg':
self._set_support_cdata(True)
def handle_startendtag(self, tag, attrs):
self.append(("startendtag", tag, attrs))
def handle_endtag(self, tag):
self.append(("endtag", tag))
if self.autocdata and tag == 'svg':
self._set_support_cdata(False)
# all other markup
@@ -767,10 +774,6 @@ text
('<!', [('comment', '')]),
('<!-', [('comment', '-')]),
('<![', [('comment', '[')]),
('<![CDATA[', [('unknown decl', 'CDATA[')]),
('<![CDATA[x', [('unknown decl', 'CDATA[x')]),
('<![CDATA[x]', [('unknown decl', 'CDATA[x]')]),
('<![CDATA[x]]', [('unknown decl', 'CDATA[x]]')]),
('<!DOCTYPE', [('decl', 'DOCTYPE')]),
('<!DOCTYPE ', [('decl', 'DOCTYPE ')]),
('<!DOCTYPE html', [('decl', 'DOCTYPE html')]),
@@ -783,6 +786,18 @@ text
for html, expected in data:
self._run_check(html, expected)
@support.subTests('content', ['', 'x', 'x]', 'x]]'])
def test_eof_in_cdata(self, content):
self._run_check('<![CDATA[' + content,
[('unknown decl', 'CDATA[' + content)])
self._run_check('<![CDATA[' + content,
[('comment', '[CDATA[' + content)],
collector=EventCollector(autocdata=True))
self._run_check('<svg><text y="100"><![CDATA[' + content,
[('starttag', 'svg', []),
('starttag', 'text', [('y', '100')]),
('unknown decl', 'CDATA[' + content)])
def test_bogus_comments(self):
html = ('<!ELEMENT br EMPTY>'
'<! not really a comment >'
@@ -845,28 +860,53 @@ text
]
self._run_check(html, expected)
def test_cdata_declarations(self):
# More tests should be added. See also "8.2.4.42. Markup
# declaration open state", "8.2.4.69. CDATA section state",
# and issue 32876
html = ('<![CDATA[just some plain text]]>')
expected = [('unknown decl', 'CDATA[just some plain text')]
self._run_check(html, expected)
def test_cdata_declarations_multiline(self):
html = ('<code><![CDATA['
' if (a < b && a > b) {'
' printf("[<marquee>How?</marquee>]");'
' }'
']]></code>')
@support.subTests('content', [
'just some plain text',
'<!-- not a comment -->',
'&not-an-entity-ref;',
"<not a='start tag'>",
'',
'[[I have many brackets]]',
'I have a > in the middle',
'I have a ]] in the middle',
'] ]>',
']] >',
('\n'
' if (a < b && a > b) {\n'
' printf("[<marquee>How?</marquee>]");\n'
' }\n'),
])
def test_cdata_section_content(self, content):
# See "13.2.5.42 Markup declaration open state",
# "13.2.5.69 CDATA section state", and issue bpo-32876.
html = f'<svg><text y="100"><![CDATA[{content}]]></text></svg>'
expected = [
('starttag', 'code', []),
('unknown decl',
'CDATA[ if (a < b && a > b) { '
'printf("[<marquee>How?</marquee>]"); }'),
('endtag', 'code')
('starttag', 'svg', []),
('starttag', 'text', [('y', '100')]),
('unknown decl', 'CDATA[' + content),
('endtag', 'text'),
('endtag', 'svg'),
]
self._run_check(html, expected)
self._run_check(html, expected, collector=EventCollector(autocdata=True))
def test_cdata_section(self):
# See "13.2.5.42 Markup declaration open state".
html = ('<![CDATA[foo<br>bar]]>'
'<svg><text y="100"><![CDATA[foo<br>bar]]></text></svg>'
'<![CDATA[foo<br>bar]]>')
expected = [
('comment', '[CDATA[foo<br'),
('data', 'bar]]>'),
('starttag', 'svg', []),
('starttag', 'text', [('y', '100')]),
('unknown decl', 'CDATA[foo<br>bar'),
('endtag', 'text'),
('endtag', 'svg'),
('comment', '[CDATA[foo<br'),
('data', 'bar]]>'),
]
self._run_check(html, expected, collector=EventCollector(autocdata=True))
def test_convert_charrefs_dropped_text(self):
# #23144: make sure that all the events are triggered when

View File

@@ -345,8 +345,7 @@ class TestEnUSCollation(BaseLocalizedTest, TestCollation):
enc = codecs.lookup(locale.getencoding() or 'ascii').name
if enc not in ('utf-8', 'iso8859-1', 'cp1252'):
raise unittest.SkipTest('encoding not suitable')
if enc != 'iso8859-1' and (sys.platform == 'darwin' or is_android or
sys.platform.startswith('freebsd')):
if enc != 'iso8859-1' and is_android:
raise unittest.SkipTest('wcscoll/wcsxfrm have known bugs')
BaseLocalizedTest.setUp(self)
@@ -512,7 +511,7 @@ class TestRealLocales(unittest.TestCase):
self.skipTest(f"setlocale(LC_CTYPE, {loc!r}) failed: {exc!r}")
self.assertEqual(loc, locale.getlocale(locale.LC_CTYPE))
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; Error not raised")
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; Error not raised')
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
def test_setlocale_long_encoding(self):
with self.assertRaises(locale.Error):

25
Lib/test/test_long.py vendored
View File

@@ -1324,17 +1324,22 @@ class LongTest(unittest.TestCase):
check(tests4, 'little', signed=False)
self.assertRaises(OverflowError, (256).to_bytes, 1, 'big', signed=False)
self.assertRaises(OverflowError, (256).to_bytes, 1, 'big', signed=True)
self.assertRaises(OverflowError, (256).to_bytes, 1, 'little', signed=False)
self.assertRaises(OverflowError, (256).to_bytes, 1, 'little', signed=True)
self.assertRaises(OverflowError, (128).to_bytes, 1, 'big', signed=True)
self.assertRaises(OverflowError, (128).to_bytes, 1, 'little', signed=True)
self.assertRaises(OverflowError, (-129).to_bytes, 1, 'big', signed=True)
self.assertRaises(OverflowError, (-129).to_bytes, 1, 'little', signed=True)
self.assertRaises(OverflowError, (-1).to_bytes, 2, 'big', signed=False)
self.assertRaises(OverflowError, (-1).to_bytes, 2, 'little', signed=False)
self.assertEqual((0).to_bytes(0, 'big'), b'')
self.assertEqual((0).to_bytes(0, 'big', signed=True), b'')
self.assertEqual((1).to_bytes(5, 'big'), b'\x00\x00\x00\x00\x01')
self.assertEqual((0).to_bytes(5, 'big'), b'\x00\x00\x00\x00\x00')
self.assertEqual((-1).to_bytes(5, 'big', signed=True),
b'\xff\xff\xff\xff\xff')
self.assertRaises(OverflowError, (1).to_bytes, 0, 'big')
self.assertRaises(OverflowError, (-1).to_bytes, 0, 'big', signed=True)
self.assertRaises(OverflowError, (-1).to_bytes, 0, 'little', signed=True)
# gh-98783
class SubStr(str):
@@ -1646,5 +1651,21 @@ class LongTest(unittest.TestCase):
# GH-117195 -- This shouldn't crash
object.__sizeof__(1)
def test_hash(self):
# gh-136599
self.assertEqual(hash(-1), -2)
self.assertEqual(hash(0), 0)
self.assertEqual(hash(10), 10)
self.assertEqual(hash(sys.hash_info.modulus - 2), sys.hash_info.modulus - 2)
self.assertEqual(hash(sys.hash_info.modulus - 1), sys.hash_info.modulus - 1)
self.assertEqual(hash(sys.hash_info.modulus), 0)
self.assertEqual(hash(sys.hash_info.modulus + 1), 1)
self.assertEqual(hash(-sys.hash_info.modulus - 2), -2)
self.assertEqual(hash(-sys.hash_info.modulus - 1), -2)
self.assertEqual(hash(-sys.hash_info.modulus), 0)
self.assertEqual(hash(-sys.hash_info.modulus + 1), -sys.hash_info.modulus + 1)
if __name__ == "__main__":
unittest.main()

151
Lib/test/test_posix.py vendored
View File

@@ -1,17 +1,19 @@
"Test posix functions"
from test import support
from test.support import import_helper
from test.support import is_apple
from test.support import os_helper
from test.support import warnings_helper
from test.support.script_helper import assert_python_ok
import copy
import errno
import sys
import signal
import time
import os
import platform
import pickle
import stat
import tempfile
import unittest
@@ -411,8 +413,10 @@ class PosixTester(unittest.TestCase):
# issue33655: Also ignore EINVAL on *BSD since ZFS is also
# often used there.
if inst.errno == errno.EINVAL and sys.platform.startswith(
('sunos', 'freebsd', 'netbsd', 'openbsd', 'gnukfreebsd')):
('sunos', 'freebsd', 'openbsd', 'gnukfreebsd')):
raise unittest.SkipTest("test may fail on ZFS filesystems")
elif inst.errno == errno.EOPNOTSUPP and sys.platform.startswith("netbsd"):
raise unittest.SkipTest("test may fail on FFS filesystems")
else:
raise
finally:
@@ -565,8 +569,38 @@ class PosixTester(unittest.TestCase):
@unittest.skipUnless(hasattr(posix, 'confstr'),
'test needs posix.confstr()')
def test_confstr(self):
self.assertRaises(ValueError, posix.confstr, "CS_garbage")
self.assertEqual(len(posix.confstr("CS_PATH")) > 0, True)
with self.assertRaisesRegex(
ValueError, "unrecognized configuration name"
):
posix.confstr("CS_garbage")
with self.assertRaisesRegex(
TypeError, "configuration names must be strings or integers"
):
posix.confstr(1.23)
path = posix.confstr("CS_PATH")
self.assertGreater(len(path), 0)
self.assertEqual(posix.confstr(posix.confstr_names["CS_PATH"]), path)
@unittest.expectedFailureIf(sys.platform in ('darwin', 'linux'), '''TODO: RUSTPYTHON; AssertionError: "configuration names must be strings or integers" does not match "Expected type 'str' but 'float' found."''')
@unittest.skipUnless(hasattr(posix, 'sysconf'),
'test needs posix.sysconf()')
def test_sysconf(self):
with self.assertRaisesRegex(
ValueError, "unrecognized configuration name"
):
posix.sysconf("SC_garbage")
with self.assertRaisesRegex(
TypeError, "configuration names must be strings or integers"
):
posix.sysconf(1.23)
arg_max = posix.sysconf("SC_ARG_MAX")
self.assertGreater(arg_max, 0)
self.assertEqual(
posix.sysconf(posix.sysconf_names["SC_ARG_MAX"]), arg_max)
@unittest.skipUnless(hasattr(posix, 'dup2'),
'test needs posix.dup2()')
@@ -703,7 +737,8 @@ class PosixTester(unittest.TestCase):
self.assertEqual(posix.major(dev), major)
self.assertRaises(TypeError, posix.major, float(dev))
self.assertRaises(TypeError, posix.major)
self.assertRaises((ValueError, OverflowError), posix.major, -1)
for x in -2, 2**64, -2**63-1:
self.assertRaises((ValueError, OverflowError), posix.major, x)
minor = posix.minor(dev)
self.assertIsInstance(minor, int)
@@ -711,13 +746,23 @@ class PosixTester(unittest.TestCase):
self.assertEqual(posix.minor(dev), minor)
self.assertRaises(TypeError, posix.minor, float(dev))
self.assertRaises(TypeError, posix.minor)
self.assertRaises((ValueError, OverflowError), posix.minor, -1)
for x in -2, 2**64, -2**63-1:
self.assertRaises((ValueError, OverflowError), posix.minor, x)
self.assertEqual(posix.makedev(major, minor), dev)
self.assertRaises(TypeError, posix.makedev, float(major), minor)
self.assertRaises(TypeError, posix.makedev, major, float(minor))
self.assertRaises(TypeError, posix.makedev, major)
self.assertRaises(TypeError, posix.makedev)
for x in -2, 2**32, 2**64, -2**63-1:
self.assertRaises((ValueError, OverflowError), posix.makedev, x, minor)
self.assertRaises((ValueError, OverflowError), posix.makedev, major, x)
if sys.platform == 'linux' and not support.linked_to_musl():
NODEV = -1
self.assertEqual(posix.major(NODEV), NODEV)
self.assertEqual(posix.minor(NODEV), NODEV)
self.assertEqual(posix.makedev(NODEV, NODEV), NODEV)
def _test_all_chown_common(self, chown_func, first_param, stat_func):
"""Common code for chown, fchown and lchown tests."""
@@ -781,9 +826,10 @@ class PosixTester(unittest.TestCase):
check_stat(uid, gid)
self.assertRaises(OSError, chown_func, first_param, 0, -1)
check_stat(uid, gid)
if 0 not in os.getgroups():
self.assertRaises(OSError, chown_func, first_param, -1, 0)
check_stat(uid, gid)
if hasattr(os, 'getgroups'):
if 0 not in os.getgroups():
self.assertRaises(OSError, chown_func, first_param, -1, 0)
check_stat(uid, gid)
# test illegal types
for t in str, float:
self.assertRaises(TypeError, chown_func, first_param, t(uid), gid)
@@ -936,6 +982,7 @@ class PosixTester(unittest.TestCase):
posix.utime(os_helper.TESTFN, (now, now))
def check_chmod(self, chmod_func, target, **kwargs):
closefd = not isinstance(target, int)
mode = os.stat(target).st_mode
try:
new_mode = mode & ~(stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR)
@@ -943,7 +990,7 @@ class PosixTester(unittest.TestCase):
self.assertEqual(os.stat(target).st_mode, new_mode)
if stat.S_ISREG(mode):
try:
with open(target, 'wb+'):
with open(target, 'wb+', closefd=closefd):
pass
except PermissionError:
pass
@@ -951,10 +998,10 @@ class PosixTester(unittest.TestCase):
chmod_func(target, new_mode, **kwargs)
self.assertEqual(os.stat(target).st_mode, new_mode)
if stat.S_ISREG(mode):
with open(target, 'wb+'):
with open(target, 'wb+', closefd=closefd):
pass
finally:
posix.chmod(target, mode)
chmod_func(target, mode)
@os_helper.skip_unless_working_chmod
def test_chmod_file(self):
@@ -971,6 +1018,13 @@ class PosixTester(unittest.TestCase):
target = self.tempdir()
self.check_chmod(posix.chmod, target)
@unittest.skipIf(sys.platform in ('darwin', 'linux'), 'TODO: RUSTPYTHON; crash')
@os_helper.skip_unless_working_chmod
def test_fchmod_file(self):
with open(os_helper.TESTFN, 'wb+') as f:
self.check_chmod(posix.fchmod, f.fileno())
self.check_chmod(posix.chmod, f.fileno())
@unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()')
def test_lchmod_file(self):
self.check_chmod(posix.lchmod, os_helper.TESTFN)
@@ -1009,6 +1063,7 @@ class PosixTester(unittest.TestCase):
self.assertEqual(os.stat(target).st_mode, target_mode)
self.assertEqual(os.lstat(link).st_mode, new_mode)
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON')
@os_helper.skip_unless_symlink
def test_chmod_file_symlink(self):
target = os_helper.TESTFN
@@ -1019,8 +1074,9 @@ class PosixTester(unittest.TestCase):
self.check_lchmod_link(posix.chmod, target, link)
else:
self.check_chmod_link(posix.chmod, target, link)
self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True)
self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True)
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; flaky')
@os_helper.skip_unless_symlink
def test_chmod_dir_symlink(self):
target = self.tempdir()
@@ -1031,7 +1087,7 @@ class PosixTester(unittest.TestCase):
self.check_lchmod_link(posix.chmod, target, link)
else:
self.check_chmod_link(posix.chmod, target, link)
self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True)
self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True)
@unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()')
@os_helper.skip_unless_symlink
@@ -1249,8 +1305,8 @@ class PosixTester(unittest.TestCase):
self.assertIsInstance(lo, int)
self.assertIsInstance(hi, int)
self.assertGreaterEqual(hi, lo)
# OSX evidently just returns 15 without checking the argument.
if sys.platform != "darwin":
# Apple platforms return 15 without checking the argument.
if not is_apple:
self.assertRaises(OSError, posix.sched_get_priority_min, -23)
self.assertRaises(OSError, posix.sched_get_priority_max, -23)
@@ -1262,9 +1318,10 @@ class PosixTester(unittest.TestCase):
self.assertIn(mine, possible_schedulers)
try:
parent = posix.sched_getscheduler(os.getppid())
except OSError as e:
if e.errno != errno.EPERM:
raise
except PermissionError:
# POSIX specifies EPERM, but Android returns EACCES. Both errno
# values are mapped to PermissionError.
pass
else:
self.assertIn(parent, possible_schedulers)
self.assertRaises(OSError, posix.sched_getscheduler, -1)
@@ -1279,9 +1336,8 @@ class PosixTester(unittest.TestCase):
try:
posix.sched_setscheduler(0, mine, param)
posix.sched_setparam(0, param)
except OSError as e:
if e.errno != errno.EPERM:
raise
except PermissionError:
pass
self.assertRaises(OSError, posix.sched_setparam, -1, param)
self.assertRaises(OSError, posix.sched_setscheduler, -1, mine, param)
@@ -1295,6 +1351,26 @@ class PosixTester(unittest.TestCase):
param = posix.sched_param(sched_priority=-large)
self.assertRaises(OverflowError, posix.sched_setparam, 0, param)
@unittest.expectedFailureIf(sys.platform == 'linux', "TODO: RUSTPYTHON; TypeError: cannot pickle 'sched_param' object")
@requires_sched
def test_sched_param(self):
param = posix.sched_param(1)
for proto in range(pickle.HIGHEST_PROTOCOL+1):
newparam = pickle.loads(pickle.dumps(param, proto))
self.assertEqual(newparam, param)
newparam = copy.copy(param)
self.assertIsNot(newparam, param)
self.assertEqual(newparam, param)
newparam = copy.deepcopy(param)
self.assertIsNot(newparam, param)
self.assertEqual(newparam, param)
newparam = copy.replace(param)
self.assertIsNot(newparam, param)
self.assertEqual(newparam, param)
newparam = copy.replace(param, sched_priority=0)
self.assertNotEqual(newparam, param)
self.assertEqual(newparam.sched_priority, 0)
@unittest.skipUnless(hasattr(posix, "sched_rr_get_interval"), "no function")
def test_sched_rr_get_interval(self):
try:
@@ -1495,6 +1571,7 @@ class TestPosixDirFd(unittest.TestCase):
with self.prepare_file() as (dir_fd, name, fullname):
posix.chown(name, os.getuid(), os.getgid(), dir_fd=dir_fd)
@unittest.expectedFailureIf(sys.platform in ('darwin', 'linux'), 'TODO: RUSTPYTHON; AssertionError: RuntimeWarning not triggered')
@unittest.skipUnless(os.stat in os.supports_dir_fd, "test needs dir_fd support in os.stat()")
def test_stat_dir_fd(self):
with self.prepare() as (dir_fd, name, fullname):
@@ -1515,6 +1592,13 @@ class TestPosixDirFd(unittest.TestCase):
self.assertRaises(OverflowError,
posix.stat, name, dir_fd=10**20)
for fd in False, True:
with self.assertWarnsRegex(RuntimeWarning,
'bool is used as a file descriptor') as cm:
with self.assertRaises(OSError):
posix.stat('nonexisting', dir_fd=fd)
self.assertEqual(cm.filename, __file__)
@unittest.skipUnless(os.utime in os.supports_dir_fd, "test needs dir_fd support in os.utime()")
def test_utime_dir_fd(self):
with self.prepare_file() as (dir_fd, name, fullname):
@@ -1890,7 +1974,7 @@ class _PosixSpawnMixin:
[sys.executable, "-c", "pass"],
os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
@unittest.expectedFailure
@unittest.expectedFailureIf(sys.platform in ('darwin', 'linux'), 'TODO: RUSTPYTHON; NotImplementedError: scheduler parameter is not yet implemented')
@requires_sched
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
"bpo-34685: test can fail on BSD")
@@ -1911,10 +1995,15 @@ class _PosixSpawnMixin:
)
support.wait_process(pid, exitcode=0)
@unittest.expectedFailure
@unittest.expectedFailureIf(sys.platform in ('darwin', 'linux'), 'TODO: RUSTPYTHON; NotImplementedError: scheduler parameter is not yet implemented')
@requires_sched
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
"bpo-34685: test can fail on BSD")
@unittest.skipIf(platform.libc_ver()[0] == 'glibc' and
os.sched_getscheduler(0) in [
os.SCHED_BATCH,
os.SCHED_IDLE],
"Skip test due to glibc posix_spawn policy")
def test_setscheduler_with_policy(self):
policy = os.sched_getscheduler(0)
priority = os.sched_get_priority_min(policy)
@@ -1993,10 +2082,7 @@ class _PosixSpawnMixin:
with open(outfile, encoding="utf-8") as f:
self.assertEqual(f.read(), 'hello')
# TODO: RUSTPYTHON: the rust runtime reopens closed stdio fds at startup,
# so this test fails, even though POSIX_SPAWN_CLOSE does
# actually have an effect
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; the rust runtime reopens closed stdio fds at startup, so this test fails, even though POSIX_SPAWN_CLOSE does actually have an effect
def test_close_file(self):
closefile = os_helper.TESTFN
self.addCleanup(os_helper.unlink, closefile)
@@ -2036,11 +2122,13 @@ class _PosixSpawnMixin:
@unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn")
@support.requires_subprocess()
class TestPosixSpawn(unittest.TestCase, _PosixSpawnMixin):
spawn_func = getattr(posix, 'posix_spawn', None)
@unittest.skipUnless(hasattr(os, 'posix_spawnp'), "test needs os.posix_spawnp")
@support.requires_subprocess()
class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin):
spawn_func = getattr(posix, 'posix_spawnp', None)
@@ -2117,6 +2205,13 @@ class TestPosixWeaklinking(unittest.TestCase):
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
os.stat("file", dir_fd=0)
def test_ptsname_r(self):
self._verify_available("HAVE_PTSNAME_R")
if self.mac_ver >= (10, 13, 4):
self.assertIn("HAVE_PTSNAME_R", posix._have_functions)
else:
self.assertNotIn("HAVE_PTSNAME_R", posix._have_functions)
def test_access(self):
self._verify_available("HAVE_FACCESSAT")
if self.mac_ver >= (10, 10):

View File

@@ -1,13 +1,14 @@
# XXX TypeErrors on calling handlers, or on bad return values from a
# handler, are obscure and unhelpful.
from io import BytesIO
import os
import platform
import sys
import sysconfig
import unittest
import traceback
from io import BytesIO
from test import support
from test.support import os_helper
from xml.parsers import expat
from xml.parsers.expat import errors
@@ -19,32 +20,28 @@ class SetAttributeTest(unittest.TestCase):
def setUp(self):
self.parser = expat.ParserCreate(namespace_separator='!')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_buffer_text(self):
self.assertIs(self.parser.buffer_text, False)
for x in 0, 1, 2, 0:
self.parser.buffer_text = x
self.assertIs(self.parser.buffer_text, bool(x))
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_namespace_prefixes(self):
self.assertIs(self.parser.namespace_prefixes, False)
for x in 0, 1, 2, 0:
self.parser.namespace_prefixes = x
self.assertIs(self.parser.namespace_prefixes, bool(x))
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_ordered_attributes(self):
self.assertIs(self.parser.ordered_attributes, False)
for x in 0, 1, 2, 0:
self.parser.ordered_attributes = x
self.assertIs(self.parser.ordered_attributes, bool(x))
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_specified_attributes(self):
self.assertIs(self.parser.specified_attributes, False)
for x in 0, 1, 2, 0:
@@ -234,8 +231,7 @@ class ParseTest(unittest.TestCase):
for operation, expected_operation in zip(operations, expected_operations):
self.assertEqual(operation, expected_operation)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_parse_bytes(self):
out = self.Outputter()
parser = expat.ParserCreate(namespace_separator='!')
@@ -248,8 +244,7 @@ class ParseTest(unittest.TestCase):
# Issue #6697.
self.assertRaises(AttributeError, getattr, parser, '\uD800')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_parse_str(self):
out = self.Outputter()
parser = expat.ParserCreate(namespace_separator='!')
@@ -260,8 +255,7 @@ class ParseTest(unittest.TestCase):
operations = out.out
self._verify_parse_output(operations)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_parse_file(self):
# Try parsing a file
out = self.Outputter()
@@ -274,8 +268,7 @@ class ParseTest(unittest.TestCase):
operations = out.out
self._verify_parse_output(operations)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_parse_again(self):
parser = expat.ParserCreate()
file = BytesIO(data)
@@ -289,8 +282,7 @@ class ParseTest(unittest.TestCase):
expat.errors.XML_ERROR_FINISHED)
class NamespaceSeparatorTest(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_legal(self):
# Tests that make sure we get errors when the namespace_separator value
# is illegal, and that we don't for good values:
@@ -298,15 +290,12 @@ class NamespaceSeparatorTest(unittest.TestCase):
expat.ParserCreate(namespace_separator=None)
expat.ParserCreate(namespace_separator=' ')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_illegal(self):
try:
with self.assertRaisesRegex(TypeError,
r"ParserCreate\(\) argument (2|'namespace_separator') "
r"must be str or None, not int"):
expat.ParserCreate(namespace_separator=42)
self.fail()
except TypeError as e:
self.assertEqual(str(e),
"ParserCreate() argument 'namespace_separator' must be str or None, not int")
try:
expat.ParserCreate(namespace_separator='too long')
@@ -328,9 +317,7 @@ class NamespaceSeparatorTest(unittest.TestCase):
class InterningTest(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test(self):
# Test the interning machinery.
p = expat.ParserCreate()
@@ -346,8 +333,7 @@ class InterningTest(unittest.TestCase):
# L should have the same string repeated over and over.
self.assertTrue(tag is entry)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_issue9402(self):
# create an ExternalEntityParserCreate with buffer text
class ExternalOutputter:
@@ -405,8 +391,7 @@ class BufferTextTest(unittest.TestCase):
parser = expat.ParserCreate()
self.assertFalse(parser.buffer_text)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_buffering_enabled(self):
# Make sure buffering is turned on
self.assertTrue(self.parser.buffer_text)
@@ -414,8 +399,7 @@ class BufferTextTest(unittest.TestCase):
self.assertEqual(self.stuff, ['123'],
"buffered text not properly collapsed")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test1(self):
# XXX This test exposes more detail of Expat's text chunking than we
# XXX like, but it tests what we need to concisely.
@@ -425,23 +409,20 @@ class BufferTextTest(unittest.TestCase):
["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"],
"buffering control not reacting as expected")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test2(self):
self.parser.Parse(b"<a>1<b/>&lt;2&gt;<c/>&#32;\n&#x20;3</a>", True)
self.assertEqual(self.stuff, ["1<2> \n 3"],
"buffered text not properly collapsed")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test3(self):
self.setHandlers(["StartElementHandler"])
self.parser.Parse(b"<a>1<b/>2<c/>3</a>", True)
self.assertEqual(self.stuff, ["<a>", "1", "<b>", "2", "<c>", "3"],
"buffered text not properly split")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test4(self):
self.setHandlers(["StartElementHandler", "EndElementHandler"])
self.parser.CharacterDataHandler = None
@@ -449,16 +430,14 @@ class BufferTextTest(unittest.TestCase):
self.assertEqual(self.stuff,
["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test5(self):
self.setHandlers(["StartElementHandler", "EndElementHandler"])
self.parser.Parse(b"<a>1<b></b>2<c/>3</a>", True)
self.assertEqual(self.stuff,
["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test6(self):
self.setHandlers(["CommentHandler", "EndElementHandler",
"StartElementHandler"])
@@ -467,8 +446,7 @@ class BufferTextTest(unittest.TestCase):
["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"],
"buffered text not properly split")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test7(self):
self.setHandlers(["CommentHandler", "EndElementHandler",
"StartElementHandler"])
@@ -482,35 +460,59 @@ class BufferTextTest(unittest.TestCase):
# Test handling of exception from callback:
class HandlerExceptionTest(unittest.TestCase):
def StartElementHandler(self, name, attrs):
raise RuntimeError(name)
raise RuntimeError(f'StartElementHandler: <{name}>')
def check_traceback_entry(self, entry, filename, funcname):
self.assertEqual(os.path.basename(entry[0]), filename)
self.assertEqual(entry[2], funcname)
self.assertEqual(os.path.basename(entry.filename), filename)
self.assertEqual(entry.name, funcname)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@support.cpython_only
def test_exception(self):
# gh-66652: test _PyTraceback_Add() used by pyexpat.c to inject frames
# Change the current directory to the Python source code directory
# if it is available.
src_dir = sysconfig.get_config_var('abs_builddir')
if src_dir:
have_source = os.path.isdir(src_dir)
else:
have_source = False
if have_source:
with os_helper.change_cwd(src_dir):
self._test_exception(have_source)
else:
self._test_exception(have_source)
def _test_exception(self, have_source):
# Use path relative to the current directory which should be the Python
# source code directory (if it is available).
PYEXPAT_C = os.path.join('Modules', 'pyexpat.c')
parser = expat.ParserCreate()
parser.StartElementHandler = self.StartElementHandler
try:
parser.Parse(b"<a><b><c/></b></a>", True)
self.fail()
except RuntimeError as e:
self.assertEqual(e.args[0], 'a',
"Expected RuntimeError for element 'a', but" + \
" found %r" % e.args[0])
# Check that the traceback contains the relevant line in pyexpat.c
entries = traceback.extract_tb(e.__traceback__)
self.assertEqual(len(entries), 3)
self.check_traceback_entry(entries[0],
"test_pyexpat.py", "test_exception")
self.check_traceback_entry(entries[1],
"pyexpat.c", "StartElement")
self.check_traceback_entry(entries[2],
"test_pyexpat.py", "StartElementHandler")
if sysconfig.is_python_build() and not (sys.platform == 'win32' and platform.machine() == 'ARM'):
self.assertIn('call_with_frame("StartElement"', entries[1][3])
self.fail("the parser did not raise RuntimeError")
except RuntimeError as exc:
self.assertEqual(exc.args[0], 'StartElementHandler: <a>', exc)
entries = traceback.extract_tb(exc.__traceback__)
self.assertEqual(len(entries), 3, entries)
self.check_traceback_entry(entries[0],
"test_pyexpat.py", "_test_exception")
self.check_traceback_entry(entries[1],
os.path.basename(PYEXPAT_C),
"StartElement")
self.check_traceback_entry(entries[2],
"test_pyexpat.py", "StartElementHandler")
# Check that the traceback contains the relevant line in
# Modules/pyexpat.c. Skip the test if Modules/pyexpat.c is not
# available.
if have_source and os.path.exists(PYEXPAT_C):
self.assertIn('call_with_frame("StartElement"',
entries[1].line)
# Test Current* members:
@@ -533,8 +535,7 @@ class PositionTest(unittest.TestCase):
'Expected position %s, got position %s' %(pos, expected))
self.upto += 1
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test(self):
self.parser = expat.ParserCreate()
self.parser.StartElementHandler = self.StartElementHandler
@@ -548,9 +549,9 @@ class PositionTest(unittest.TestCase):
class sf1296433Test(unittest.TestCase):
@unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: Expected type 'str' but 'bytes' found.
def test_parse_only_xml_data(self):
# http://python.org/sf/1296433
# https://bugs.python.org/issue1296433
#
xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025)
# this one doesn't crash
@@ -565,25 +566,22 @@ class sf1296433Test(unittest.TestCase):
parser = expat.ParserCreate()
parser.CharacterDataHandler = handler
self.assertRaises(Exception, parser.Parse, xml.encode('iso8859'))
self.assertRaises(SpecificException, parser.Parse, xml.encode('iso8859'))
class ChardataBufferTest(unittest.TestCase):
"""
test setting of chardata buffer size
"""
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_1025_bytes(self):
self.assertEqual(self.small_buffer_test(1025), 2)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_1000_bytes(self):
self.assertEqual(self.small_buffer_test(1000), 1)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_wrong_size(self):
parser = expat.ParserCreate()
parser.buffer_text = 1
@@ -596,8 +594,7 @@ class ChardataBufferTest(unittest.TestCase):
with self.assertRaises(TypeError):
parser.buffer_size = 512.0
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_unchanged_size(self):
xml1 = b"<?xml version='1.0' encoding='iso8859'?><s>" + b'a' * 512
xml2 = b'a'*512 + b'</s>'
@@ -620,8 +617,8 @@ class ChardataBufferTest(unittest.TestCase):
parser.Parse(xml2)
self.assertEqual(self.n, 2)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_disabling_buffer(self):
xml1 = b"<?xml version='1.0' encoding='iso8859'?><a>" + b'a' * 512
xml2 = b'b' * 1024
@@ -666,8 +663,7 @@ class ChardataBufferTest(unittest.TestCase):
parser.Parse(xml)
return self.n
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_change_size_1(self):
xml1 = b"<?xml version='1.0' encoding='iso8859'?><a><s>" + b'a' * 1024
xml2 = b'aaa</s><s>' + b'a' * 1025 + b'</s></a>'
@@ -684,8 +680,7 @@ class ChardataBufferTest(unittest.TestCase):
parser.Parse(xml2, True)
self.assertEqual(self.n, 2)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_change_size_2(self):
xml1 = b"<?xml version='1.0' encoding='iso8859'?><a>a<s>" + b'a' * 1023
xml2 = b'aaa</s><s>' + b'a' * 1025 + b'</s></a>'
@@ -703,9 +698,7 @@ class ChardataBufferTest(unittest.TestCase):
self.assertEqual(self.n, 4)
class MalformedInputTest(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test1(self):
xml = b"\0\r\n"
parser = expat.ParserCreate()
@@ -715,8 +708,7 @@ class MalformedInputTest(unittest.TestCase):
except expat.ExpatError as e:
self.assertEqual(str(e), 'unclosed token: line 2, column 0')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test2(self):
# \xc2\x85 is UTF-8 encoded U+0085 (NEXT LINE)
xml = b"<?xml version\xc2\x85='1.0'?>\r\n"
@@ -726,16 +718,13 @@ class MalformedInputTest(unittest.TestCase):
parser.Parse(xml, True)
class ErrorMessageTest(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_codes(self):
# verify mapping of errors.codes and errors.messages
self.assertEqual(errors.XML_ERROR_SYNTAX,
errors.messages[errors.codes[errors.XML_ERROR_SYNTAX]])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_expaterror(self):
xml = b'<'
parser = expat.ParserCreate()
@@ -751,9 +740,7 @@ class ForeignDTDTests(unittest.TestCase):
"""
Tests for the UseForeignDTD method of expat parser objects.
"""
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_use_foreign_dtd(self):
"""
If UseForeignDTD is passed True and a document without an external
@@ -782,8 +769,7 @@ class ForeignDTDTests(unittest.TestCase):
parser.Parse(b"<?xml version='1.0'?><element/>")
self.assertEqual(handler_call_args, [(None, None)])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_ignore_use_foreign_dtd(self):
"""
If UseForeignDTD is passed True and a document with an external
@@ -804,5 +790,101 @@ class ForeignDTDTests(unittest.TestCase):
self.assertEqual(handler_call_args, [("bar", "baz")])
class ParentParserLifetimeTest(unittest.TestCase):
"""
Subparsers make use of their parent XML_Parser inside of Expat.
As a result, parent parsers need to outlive subparsers.
See https://github.com/python/cpython/issues/139400.
"""
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'xmlparser' object has no attribute 'ExternalEntityParserCreate'
def test_parent_parser_outlives_its_subparsers__single(self):
parser = expat.ParserCreate()
subparser = parser.ExternalEntityParserCreate(None)
# Now try to cause garbage collection of the parent parser
# while it's still being referenced by a related subparser.
del parser
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'xmlparser' object has no attribute 'ExternalEntityParserCreate'
def test_parent_parser_outlives_its_subparsers__multiple(self):
parser = expat.ParserCreate()
subparser_one = parser.ExternalEntityParserCreate(None)
subparser_two = parser.ExternalEntityParserCreate(None)
# Now try to cause garbage collection of the parent parser
# while it's still being referenced by a related subparser.
del parser
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'xmlparser' object has no attribute 'ExternalEntityParserCreate'
def test_parent_parser_outlives_its_subparsers__chain(self):
parser = expat.ParserCreate()
subparser = parser.ExternalEntityParserCreate(None)
subsubparser = subparser.ExternalEntityParserCreate(None)
# Now try to cause garbage collection of the parent parsers
# while they are still being referenced by a related subparser.
del parser
del subparser
class ReparseDeferralTest(unittest.TestCase):
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'xmlparser' object has no attribute 'GetReparseDeferralEnabled'
def test_getter_setter_round_trip(self):
parser = expat.ParserCreate()
enabled = (expat.version_info >= (2, 6, 0))
self.assertIs(parser.GetReparseDeferralEnabled(), enabled)
parser.SetReparseDeferralEnabled(False)
self.assertIs(parser.GetReparseDeferralEnabled(), False)
parser.SetReparseDeferralEnabled(True)
self.assertIs(parser.GetReparseDeferralEnabled(), enabled)
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'xmlparser' object has no attribute 'GetReparseDeferralEnabled'
def test_reparse_deferral_enabled(self):
if expat.version_info < (2, 6, 0):
self.skipTest(f'Expat {expat.version_info} does not '
'support reparse deferral')
started = []
def start_element(name, _):
started.append(name)
parser = expat.ParserCreate()
parser.StartElementHandler = start_element
self.assertTrue(parser.GetReparseDeferralEnabled())
for chunk in (b'<doc', b'/>'):
parser.Parse(chunk, False)
# The key test: Have handlers already fired? Expecting: no.
self.assertEqual(started, [])
parser.Parse(b'', True)
self.assertEqual(started, ['doc'])
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'xmlparser' object has no attribute 'SetReparseDeferralEnabled'
def test_reparse_deferral_disabled(self):
started = []
def start_element(name, _):
started.append(name)
parser = expat.ParserCreate()
parser.StartElementHandler = start_element
if expat.version_info >= (2, 6, 0):
parser.SetReparseDeferralEnabled(False)
self.assertFalse(parser.GetReparseDeferralEnabled())
for chunk in (b'<doc', b'/>'):
parser.Parse(chunk, False)
# The key test: Have handlers already fired? Expecting: yes.
self.assertEqual(started, ['doc'])
if __name__ == "__main__":
unittest.main()

122
Lib/test/test_site.py vendored
View File

@@ -12,6 +12,7 @@ from test.support import os_helper
from test.support import socket_helper
from test.support import captured_stderr
from test.support.os_helper import TESTFN, EnvironmentVarGuard
from test.support.script_helper import spawn_python, kill_python
import ast
import builtins
import glob
@@ -24,6 +25,7 @@ import subprocess
import sys
import sysconfig
import tempfile
from textwrap import dedent
import urllib.error
import urllib.request
from unittest import mock
@@ -221,8 +223,7 @@ class HelperFunctionsTests(unittest.TestCase):
finally:
pth_file.cleanup()
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.skipUnless(sys.platform == 'win32', 'test needs Windows')
@support.requires_subprocess()
def test_addsitedir_hidden_file_attribute(self):
@@ -581,8 +582,7 @@ class ImportSideEffectTests(unittest.TestCase):
class StartupImportTests(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@support.requires_subprocess()
def test_startup_imports(self):
# Get sys.path in isolated mode (python3 -I)
@@ -715,8 +715,7 @@ class _pthFileTests(unittest.TestCase):
pth_lines.append('import site')
return pth_lines
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@support.requires_subprocess()
def test_underpth_basic(self):
pth_lines = ['#.', '# ..', *sys.path, '.', '..']
@@ -736,8 +735,7 @@ class _pthFileTests(unittest.TestCase):
"sys.path is incorrect"
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@support.requires_subprocess()
def test_underpth_nosite_file(self):
libpath = test.support.STDLIB_DIR
@@ -762,8 +760,7 @@ class _pthFileTests(unittest.TestCase):
"sys.path is incorrect"
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@support.requires_subprocess()
def test_underpth_file(self):
libpath = test.support.STDLIB_DIR
@@ -784,8 +781,7 @@ class _pthFileTests(unittest.TestCase):
)], env=env)
self.assertTrue(rc, "sys.path is incorrect")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@support.requires_subprocess()
def test_underpth_dll_file(self):
libpath = test.support.STDLIB_DIR
@@ -807,5 +803,107 @@ class _pthFileTests(unittest.TestCase):
self.assertTrue(rc, "sys.path is incorrect")
class CommandLineTests(unittest.TestCase):
def exists(self, path):
if path is not None and os.path.isdir(path):
return "exists"
else:
return "doesn't exist"
def get_excepted_output(self, *args):
if len(args) == 0:
user_base = site.getuserbase()
user_site = site.getusersitepackages()
output = io.StringIO()
output.write("sys.path = [\n")
for dir in sys.path:
output.write(" %r,\n" % (dir,))
output.write("]\n")
output.write(f"USER_BASE: {user_base} ({self.exists(user_base)})\n")
output.write(f"USER_SITE: {user_site} ({self.exists(user_site)})\n")
output.write(f"ENABLE_USER_SITE: {site.ENABLE_USER_SITE}\n")
return 0, dedent(output.getvalue()).strip()
buffer = []
if '--user-base' in args:
buffer.append(site.getuserbase())
if '--user-site' in args:
buffer.append(site.getusersitepackages())
if buffer:
return_code = 3
if site.ENABLE_USER_SITE:
return_code = 0
elif site.ENABLE_USER_SITE is False:
return_code = 1
elif site.ENABLE_USER_SITE is None:
return_code = 2
output = os.pathsep.join(buffer)
return return_code, os.path.normpath(dedent(output).strip())
else:
return 10, None
def invoke_command_line(self, *args):
args = ["-m", "site", *args]
with EnvironmentVarGuard() as env:
env["PYTHONUTF8"] = "1"
env["PYTHONIOENCODING"] = "utf-8"
proc = spawn_python(*args, text=True, env=env,
encoding='utf-8', errors='replace')
output = kill_python(proc)
return_code = proc.returncode
return return_code, os.path.normpath(dedent(output).strip())
@support.requires_subprocess()
def test_no_args(self):
return_code, output = self.invoke_command_line()
excepted_return_code, _ = self.get_excepted_output()
self.assertEqual(return_code, excepted_return_code)
lines = output.splitlines()
self.assertEqual(lines[0], "sys.path = [")
self.assertEqual(lines[-4], "]")
excepted_base = f"USER_BASE: '{site.getuserbase()}'" +\
f" ({self.exists(site.getuserbase())})"
self.assertEqual(lines[-3], excepted_base)
excepted_site = f"USER_SITE: '{site.getusersitepackages()}'" +\
f" ({self.exists(site.getusersitepackages())})"
self.assertEqual(lines[-2], excepted_site)
self.assertEqual(lines[-1], f"ENABLE_USER_SITE: {site.ENABLE_USER_SITE}")
@support.requires_subprocess()
def test_unknown_args(self):
return_code, output = self.invoke_command_line("--unknown-arg")
excepted_return_code, _ = self.get_excepted_output("--unknown-arg")
self.assertEqual(return_code, excepted_return_code)
self.assertIn('[--user-base] [--user-site]', output)
@support.requires_subprocess()
def test_base_arg(self):
return_code, output = self.invoke_command_line("--user-base")
excepted = self.get_excepted_output("--user-base")
excepted_return_code, excepted_output = excepted
self.assertEqual(return_code, excepted_return_code)
self.assertEqual(output, excepted_output)
@support.requires_subprocess()
def test_site_arg(self):
return_code, output = self.invoke_command_line("--user-site")
excepted = self.get_excepted_output("--user-site")
excepted_return_code, excepted_output = excepted
self.assertEqual(return_code, excepted_return_code)
self.assertEqual(output, excepted_output)
@support.requires_subprocess()
def test_both_args(self):
return_code, output = self.invoke_command_line("--user-base",
"--user-site")
excepted = self.get_excepted_output("--user-base", "--user-site")
excepted_return_code, excepted_output = excepted
self.assertEqual(return_code, excepted_return_code)
self.assertEqual(output, excepted_output)
if __name__ == "__main__":
unittest.main()

View File

@@ -166,7 +166,7 @@ class TestSysConfig(unittest.TestCase):
binpath = 'bin'
incpath = 'include'
libpath = os.path.join('lib',
# XXX: RUSTPYTHON
# XXX: RUSTPYTHON
f'rustpython{sysconfig._get_python_version_abi()}',
'site-packages')
@@ -352,6 +352,13 @@ class TestSysConfig(unittest.TestCase):
self.assertEqual(get_platform(), 'macosx-10.4-%s' % arch)
for macver in range(11, 16):
_osx_support._remove_original_values(get_config_vars())
get_config_vars()['CFLAGS'] = ('-fno-strict-overflow -Wsign-compare -Wunreachable-code'
'-arch arm64 -fno-common -dynamic -DNDEBUG -g -O3 -Wall')
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = f"{macver}.0"
self.assertEqual(get_platform(), 'macosx-%d.0-arm64' % macver)
# linux debian sarge
os.name = 'posix'
sys.version = ('2.3.5 (#1, Jul 4 2007, 17:28:59) '
@@ -379,8 +386,7 @@ class TestSysConfig(unittest.TestCase):
# XXX more platforms to tests here
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
@unittest.skipIf(is_apple_mobile,
f"{sys.platform} doesn't distribute header files in the runtime environment")
@@ -441,8 +447,7 @@ class TestSysConfig(unittest.TestCase):
_main()
self.assertTrue(len(output.getvalue().split('\n')) > 0)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.skipIf(sys.platform == "win32", "Does not apply to Windows")
def test_ldshared_value(self):
ldflags = sysconfig.get_config_var('LDFLAGS')
@@ -455,8 +460,7 @@ class TestSysConfig(unittest.TestCase):
soabi = sysconfig.get_config_var('SOABI')
self.assertIn(soabi, _imp.extension_suffixes()[0])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_library(self):
library = sysconfig.get_config_var('LIBRARY')
ldlibrary = sysconfig.get_config_var('LDLIBRARY')
@@ -520,7 +524,7 @@ class TestSysConfig(unittest.TestCase):
self.assertEqual(status, 0)
self.assertEqual(my_platform, test_platform)
@unittest.expectedFailureIf(sys.platform != "win32", "TODO: RUSTPYTHON")
@unittest.expectedFailureIf(sys.platform != 'win32', 'TODO: RUSTPYTHON')
@unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
@unittest.skipIf(is_apple_mobile,
f"{sys.platform} doesn't include config folder at runtime")
@@ -581,8 +585,7 @@ class TestSysConfig(unittest.TestCase):
self.assertTrue(suffix.endswith(expected_suffixes),
f'unexpected suffix {suffix!r}')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.skipUnless(sys.platform == 'android', 'Android-specific test')
def test_android_ext_suffix(self):
machine = platform.machine()
@@ -602,8 +605,7 @@ class TestSysConfig(unittest.TestCase):
suffix = sysconfig.get_config_var('EXT_SUFFIX')
self.assertTrue(suffix.endswith('-darwin.so'), suffix)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@requires_subprocess()
def test_config_vars_depend_on_site_initialization(self):
script = textwrap.dedent("""
@@ -628,8 +630,7 @@ class TestSysConfig(unittest.TestCase):
self.assertEqual(no_site_config_vars['base'], site_config_vars['installed_base'])
self.assertEqual(no_site_config_vars['platbase'], site_config_vars['installed_platbase'])
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@requires_subprocess()
def test_config_vars_recalculation_after_site_initialization(self):
script = textwrap.dedent("""
@@ -654,8 +655,7 @@ class TestSysConfig(unittest.TestCase):
#self.assertEqual(config_vars['after']['prefix'], venv.prefix) # FIXME: prefix gets overwriten by _init_posix
#self.assertEqual(config_vars['after']['exec_prefix'], venv.prefix) # FIXME: exec_prefix gets overwriten by _init_posix
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@requires_subprocess()
def test_paths_depend_on_site_initialization(self):
script = textwrap.dedent("""
@@ -676,8 +676,7 @@ class TestSysConfig(unittest.TestCase):
class MakefileTests(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.skipIf(sys.platform.startswith('win'),
'Test is not Windows compatible')
@unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")

View File

@@ -49,8 +49,8 @@ from test.support import captured_stderr, cpython_only, infinite_recursion, requ
from test.support.testcase import ExtraAssertions
from test.typinganndata import ann_module695, mod_generics_cache, _typed_dict_helper
# TODO: RUSTPYTHON
import unittest
import unittest # XXX: RUSTPYTHON
CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes'
NOT_A_BASE_TYPE = "type 'typing.%s' is not an acceptable base type"
@@ -966,8 +966,7 @@ class GenericAliasSubstitutionTests(BaseTestCase):
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_two_parameters(self):
T1 = TypeVar('T1')
T2 = TypeVar('T2')
@@ -1065,8 +1064,7 @@ class GenericAliasSubstitutionTests(BaseTestCase):
eval(expected_str)
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_variadic_parameters(self):
T1 = TypeVar('T1')
T2 = TypeVar('T2')
@@ -3231,8 +3229,7 @@ class ProtocolTests(BaseTestCase):
self.assertIsSubclass(NotAProtocolButAnImplicitSubclass2, CallableMembersProto)
self.assertIsSubclass(NotAProtocolButAnImplicitSubclass3, CallableMembersProto)
# TODO: RUSTPYTHON
@unittest.skip("TODO: RUSTPYTHON (no gc)")
@unittest.skip('TODO: RUSTPYTHON; (no gc)')
def test_isinstance_checks_not_at_whim_of_gc(self):
self.addCleanup(gc.enable)
gc.disable()
@@ -4175,8 +4172,7 @@ class ProtocolTests(BaseTestCase):
Alias2 = typing.Union[P, typing.Iterable]
self.assertEqual(Alias, Alias2)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_protocols_pickleable(self):
global P, CP # pickle wants to reference the class by name
T = TypeVar('T')
@@ -5151,8 +5147,7 @@ class GenericTests(BaseTestCase):
self.assertNotEqual(repr(base), '')
self.assertEqual(base, base)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_pickle(self):
global C # pickle wants to reference the class by name
T = TypeVar('T')
@@ -5274,8 +5269,7 @@ class GenericTests(BaseTestCase):
for t in things:
self.assertEqual(weakref.ref(t)(), t)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_parameterized_slots(self):
T = TypeVar('T')
class C(Generic[T]):
@@ -5295,8 +5289,7 @@ class GenericTests(BaseTestCase):
self.assertEqual(get_type_hints(foo, globals(), locals())['x'], C[C])
self.assertEqual(copy(C[int]), deepcopy(C[int]))
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_parameterized_slots_dict(self):
T = TypeVar('T')
class D(Generic[T]):
@@ -5722,6 +5715,24 @@ class GenericTests(BaseTestCase):
with self.assertRaises(TypeError):
a[int]
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: ".+__typing_subst__.+tuple.+int.*" does not match "'TypeAliasType' object is not subscriptable"
def test_return_non_tuple_while_unpacking(self):
# GH-138497: GenericAlias objects didn't ensure that __typing_subst__ actually
# returned a tuple
class EvilTypeVar:
__typing_is_unpacked_typevartuple__ = True
def __typing_prepare_subst__(*_):
return None # any value
def __typing_subst__(*_):
return 42 # not tuple
evil = EvilTypeVar()
# Create a dummy TypeAlias that will be given the evil generic from
# above.
type type_alias[*_] = 0
with self.assertRaisesRegex(TypeError, ".+__typing_subst__.+tuple.+int.*"):
type_alias[evil][0]
class ClassVarTests(BaseTestCase):
@@ -5824,8 +5835,7 @@ class FinalDecoratorTests(BaseTestCase):
def func(x): ...
self.assertIs(func, final(func))
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_dunder_final(self):
@final
def func(): ...
@@ -6844,8 +6854,7 @@ class GetTypeHintTests(BaseTestCase):
with self.assertRaises(TypeError):
gth(None)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_get_type_hints_modules(self):
ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str, 'u': int | float}
self.assertEqual(gth(ann_module), ann_module_type_hints)
@@ -7096,8 +7105,7 @@ class GetTypeHintTests(BaseTestCase):
):
get_type_hints(ann_module6)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_get_type_hints_typeddict(self):
self.assertEqual(get_type_hints(TotalMovie), {'title': str, 'year': int})
self.assertEqual(get_type_hints(TotalMovie, include_extras=True), {
@@ -8138,8 +8146,7 @@ class NamedTupleTests(BaseTestCase):
self.assertEqual(struct.__annotations__, {})
self.assertIsInstance(struct(), struct)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_namedtuple_errors(self):
with self.assertRaises(TypeError):
NamedTuple.__new__()
@@ -8227,8 +8234,7 @@ class NamedTupleTests(BaseTestCase):
self.assertIsInstance(bar.attr, Vanilla)
self.assertEqual(bar.attr.name, "attr")
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_setname_raises_the_same_as_on_other_classes(self):
class CustomException(BaseException): pass
@@ -8644,16 +8650,14 @@ class TypedDictTests(BaseTestCase):
# The TypedDict constructor is not itself a TypedDict
self.assertIs(is_typeddict(TypedDict), False)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_get_type_hints(self):
self.assertEqual(
get_type_hints(Bar),
{'a': typing.Optional[int], 'b': int}
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_get_type_hints_generic(self):
self.assertEqual(
get_type_hints(BarGeneric),
@@ -8786,8 +8790,7 @@ class TypedDictTests(BaseTestCase):
with self.assertRaises(TypeError):
WithImplicitAny[str]
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_non_generic_subscript(self):
# For backward compatibility, subscription works
# on arbitrary TypedDict types.
@@ -8915,8 +8918,7 @@ class TypedDictTests(BaseTestCase):
self.assertEqual(Child.__readonly_keys__, frozenset())
self.assertEqual(Child.__mutable_keys__, frozenset({'a'}))
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_combine_qualifiers(self):
class AllTheThings(TypedDict):
a: Annotated[Required[ReadOnly[int]], "why not"]
@@ -9110,8 +9112,7 @@ class RETests(BaseTestCase):
self.assertEqual(repr(Match[str]), 'typing.Match[str]')
self.assertEqual(repr(Match[bytes]), 'typing.Match[bytes]')
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_cannot_subclass(self):
with self.assertRaisesRegex(
TypeError,
@@ -10330,8 +10331,7 @@ class SpecialAttrsTests(BaseTestCase):
TypeName = typing.NewType('SpecialAttrsTests.TypeName', Any)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_special_attrs2(self):
# Forward refs provide a different introspection API. __name__ and
# __qualname__ make little sense for forward refs as they can store
@@ -10498,8 +10498,7 @@ class DataclassTransformTests(BaseTestCase):
class NoDefaultTests(BaseTestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_pickling(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
s = pickle.dumps(NoDefault, proto)
@@ -10525,8 +10524,7 @@ class NoDefaultTests(BaseTestCase):
with self.assertRaises(TypeError):
NoDefault()
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_no_attributes(self):
with self.assertRaises(AttributeError):
NoDefault.foo = 3
@@ -10602,8 +10600,7 @@ class TypeIterationTests(BaseTestCase):
Annotated[T, ''],
)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_cannot_iterate(self):
expected_error_regex = "object is not iterable"
for test_type in self._UNITERABLE_TYPES: