mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
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:
16
Lib/_android_support.py
vendored
16
Lib/_android_support.py
vendored
@@ -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.
|
||||
|
||||
14
Lib/_collections_abc.py
vendored
14
Lib/_collections_abc.py
vendored
@@ -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
24
Lib/html/parser.py
vendored
@@ -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)
|
||||
|
||||
15
Lib/multiprocessing/forkserver.py
vendored
15
Lib/multiprocessing/forkserver.py
vendored
@@ -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()
|
||||
|
||||
4
Lib/multiprocessing/popen_spawn_posix.py
vendored
4
Lib/multiprocessing/popen_spawn_posix.py
vendored
@@ -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())
|
||||
|
||||
22
Lib/sysconfig/__init__.py
vendored
22
Lib/sysconfig/__init__.py
vendored
@@ -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'
|
||||
|
||||
41
Lib/test/_test_multiprocessing.py
vendored
41
Lib/test/_test_multiprocessing.py
vendored
@@ -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
|
||||
|
||||
27
Lib/test/list_tests.py
vendored
27
Lib/test/list_tests.py
vendored
@@ -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
14
Lib/test/mp_preload_main.py
vendored
Normal 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()
|
||||
7
Lib/test/seq_tests.py
vendored
7
Lib/test/seq_tests.py
vendored
@@ -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)
|
||||
|
||||
48
Lib/test/support/__init__.py
vendored
48
Lib/test/support/__init__.py
vendored
@@ -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
110
Lib/test/test_bytes.py
vendored
@@ -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__')
|
||||
|
||||
39
Lib/test/test_difflib.py
vendored
39
Lib/test/test_difflib.py
vendored
@@ -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('ımplıcı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
|
||||
|
||||
|
||||
124
Lib/test/test_exceptions.py
vendored
124
Lib/test/test_exceptions.py
vendored
@@ -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
|
||||
|
||||
233
Lib/test/test_genericalias.py
vendored
233
Lib/test/test_genericalias.py
vendored
@@ -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()
|
||||
|
||||
88
Lib/test/test_htmlparser.py
vendored
88
Lib/test/test_htmlparser.py
vendored
@@ -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 -->',
|
||||
'¬-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
|
||||
|
||||
5
Lib/test/test_locale.py
vendored
5
Lib/test/test_locale.py
vendored
@@ -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
25
Lib/test/test_long.py
vendored
@@ -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
151
Lib/test/test_posix.py
vendored
@@ -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):
|
||||
|
||||
288
Lib/test/test_pyexpat.py
vendored
288
Lib/test/test_pyexpat.py
vendored
@@ -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/><2><c/> \n 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
122
Lib/test/test_site.py
vendored
@@ -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()
|
||||
|
||||
35
Lib/test/test_sysconfig.py
vendored
35
Lib/test/test_sysconfig.py
vendored
@@ -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")
|
||||
|
||||
85
Lib/test/test_typing.py
vendored
85
Lib/test/test_typing.py
vendored
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user