Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Update test/test_contextlib.py from CPython 3.11.2 #4649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 233 additions & 17 deletions 250 Lib/test/test_contextlib.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Unit tests for contextlib.py, and other context managers."""

import io
import os
import sys
import tempfile
import threading
import traceback
import unittest
from contextlib import * # Tests __all__
from test import support
Expand Down Expand Up @@ -86,6 +88,58 @@ def woohoo():
raise ZeroDivisionError()
self.assertEqual(state, [1, 42, 999])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_contextmanager_traceback(self):
@contextmanager
def f():
yield

try:
with f():
1/0
except ZeroDivisionError as e:
frames = traceback.extract_tb(e.__traceback__)

self.assertEqual(len(frames), 1)
self.assertEqual(frames[0].name, 'test_contextmanager_traceback')
self.assertEqual(frames[0].line, '1/0')

# Repeat with RuntimeError (which goes through a different code path)
class RuntimeErrorSubclass(RuntimeError):
pass

try:
with f():
raise RuntimeErrorSubclass(42)
except RuntimeErrorSubclass as e:
frames = traceback.extract_tb(e.__traceback__)

self.assertEqual(len(frames), 1)
self.assertEqual(frames[0].name, 'test_contextmanager_traceback')
self.assertEqual(frames[0].line, 'raise RuntimeErrorSubclass(42)')

class StopIterationSubclass(StopIteration):
pass

for stop_exc in (
StopIteration('spam'),
StopIterationSubclass('spam'),
):
with self.subTest(type=type(stop_exc)):
try:
with f():
raise stop_exc
except type(stop_exc) as e:
self.assertIs(e, stop_exc)
frames = traceback.extract_tb(e.__traceback__)
else:
self.fail(f'{stop_exc} was suppressed')

self.assertEqual(len(frames), 1)
self.assertEqual(frames[0].name, 'test_contextmanager_traceback')
self.assertEqual(frames[0].line, 'raise stop_exc')

def test_contextmanager_no_reraise(self):
@contextmanager
def whee():
Expand Down Expand Up @@ -126,19 +180,22 @@ def woohoo():
self.assertEqual(state, [1, 42, 999])

def test_contextmanager_except_stopiter(self):
stop_exc = StopIteration('spam')
@contextmanager
def woohoo():
yield
try:
with self.assertWarnsRegex(DeprecationWarning,
"StopIteration"):
with woohoo():
raise stop_exc
except Exception as ex:
self.assertIs(ex, stop_exc)
else:
self.fail('StopIteration was suppressed')

class StopIterationSubclass(StopIteration):
pass

for stop_exc in (StopIteration('spam'), StopIterationSubclass('spam')):
with self.subTest(type=type(stop_exc)):
try:
with woohoo():
raise stop_exc
except Exception as ex:
self.assertIs(ex, stop_exc)
else:
self.fail(f'{stop_exc} was suppressed')

# TODO: RUSTPYTHON
@unittest.expectedFailure
Expand Down Expand Up @@ -230,6 +287,8 @@ class A:
def woohoo(a, b):
a = weakref.ref(a)
b = weakref.ref(b)
# Allow test to work with a non-refcounted GC
support.gc_collect()
self.assertIsNone(a())
self.assertIsNone(b())
yield
Expand Down Expand Up @@ -318,13 +377,13 @@ def testWithOpen(self):
tfn = tempfile.mktemp()
try:
f = None
with open(tfn, "w") as f:
with open(tfn, "w", encoding="utf-8") as f:
self.assertFalse(f.closed)
f.write("Booh\n")
self.assertTrue(f.closed)
f = None
with self.assertRaises(ZeroDivisionError):
with open(tfn, "r") as f:
with open(tfn, "r", encoding="utf-8") as f:
self.assertFalse(f.closed)
self.assertEqual(f.read(), "Booh\n")
1 / 0
Expand Down Expand Up @@ -486,26 +545,30 @@ def method(self, a, b, c=None):
self.assertEqual(test.b, 2)


# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_typo_enter(self):
class mycontext(ContextDecorator):
def __unter__(self):
pass
def __exit__(self, *exc):
pass

with self.assertRaises(AttributeError):
with self.assertRaisesRegex(TypeError, 'the context manager'):
with mycontext():
pass


# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_typo_exit(self):
class mycontext(ContextDecorator):
def __enter__(self):
pass
def __uxit__(self, *exc):
pass

with self.assertRaises(AttributeError):
with self.assertRaisesRegex(TypeError, 'the context manager.*__exit__'):
with mycontext():
pass

Expand Down Expand Up @@ -608,9 +671,9 @@ def _exit(*args, **kwds):
stack.callback(arg=1)
with self.assertRaises(TypeError):
self.exit_stack.callback(arg=2)
with self.assertWarns(DeprecationWarning):
with self.assertRaises(TypeError):
stack.callback(callback=_exit, arg=3)
self.assertEqual(result, [((), {'arg': 3})])
self.assertEqual(result, [])

def test_push(self):
exc_raised = ZeroDivisionError
Expand Down Expand Up @@ -665,6 +728,27 @@ def _exit():
result.append(2)
self.assertEqual(result, [1, 2, 3, 4])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_enter_context_errors(self):
class LacksEnterAndExit:
pass
class LacksEnter:
def __exit__(self, *exc_info):
pass
class LacksExit:
def __enter__(self):
pass

with self.exit_stack() as stack:
with self.assertRaisesRegex(TypeError, 'the context manager'):
stack.enter_context(LacksEnterAndExit())
with self.assertRaisesRegex(TypeError, 'the context manager'):
stack.enter_context(LacksEnter())
with self.assertRaisesRegex(TypeError, 'the context manager'):
stack.enter_context(LacksExit())
self.assertFalse(stack._exit_callbacks)

def test_close(self):
result = []
with self.exit_stack() as stack:
Expand Down Expand Up @@ -700,6 +784,40 @@ def test_exit_suppress(self):
stack.push(lambda *exc: True)
1/0

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_exit_exception_traceback(self):
# This test captures the current behavior of ExitStack so that we know
# if we ever unintendedly change it. It is not a statement of what the
# desired behavior is (for instance, we may want to remove some of the
# internal contextlib frames).

def raise_exc(exc):
raise exc

try:
with self.exit_stack() as stack:
stack.callback(raise_exc, ValueError)
1/0
except ValueError as e:
exc = e

self.assertIsInstance(exc, ValueError)
ve_frames = traceback.extract_tb(exc.__traceback__)
expected = \
[('test_exit_exception_traceback', 'with self.exit_stack() as stack:')] + \
self.callback_error_internal_frames + \
[('_exit_wrapper', 'callback(*args, **kwds)'),
('raise_exc', 'raise exc')]

self.assertEqual(
[(f.name, f.line) for f in ve_frames], expected)

self.assertIsInstance(exc.__context__, ZeroDivisionError)
zde_frames = traceback.extract_tb(exc.__context__.__traceback__)
self.assertEqual([(f.name, f.line) for f in zde_frames],
[('test_exit_exception_traceback', '1/0')])

def test_exit_exception_chaining_reference(self):
# Sanity check to make sure that ExitStack chaining matches
# actual nested with statements
Expand Down Expand Up @@ -781,6 +899,42 @@ def suppress_exc(*exc_details):
self.assertIsInstance(inner_exc, ValueError)
self.assertIsInstance(inner_exc.__context__, ZeroDivisionError)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_exit_exception_explicit_none_context(self):
# Ensure ExitStack chaining matches actual nested `with` statements
# regarding explicit __context__ = None.

class MyException(Exception):
pass

@contextmanager
def my_cm():
try:
yield
except BaseException:
exc = MyException()
try:
raise exc
finally:
exc.__context__ = None

@contextmanager
def my_cm_with_exit_stack():
with self.exit_stack() as stack:
stack.enter_context(my_cm())
yield stack

for cm in (my_cm, my_cm_with_exit_stack):
with self.subTest():
try:
with cm():
raise IndexError()
except MyException as exc:
self.assertIsNone(exc.__context__)
else:
self.fail("Expected IndexError, but no exception was raised")

def test_exit_exception_non_suppressing(self):
# http://bugs.python.org/issue19092
def raise_exc(exc):
Expand Down Expand Up @@ -893,12 +1047,16 @@ def test_excessive_nesting(self):
for i in range(10000):
stack.callback(int)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_instance_bypass(self):
class Example(object): pass
cm = Example()
cm.__enter__ = object()
cm.__exit__ = object()
stack = self.exit_stack()
self.assertRaises(AttributeError, stack.enter_context, cm)
with self.assertRaisesRegex(TypeError, 'the context manager'):
stack.enter_context(cm)
stack.push(cm)
self.assertIs(stack._exit_callbacks[-1][1], cm)

Expand Down Expand Up @@ -939,6 +1097,10 @@ def first():

class TestExitStack(TestBaseExitStack, unittest.TestCase):
exit_stack = ExitStack
callback_error_internal_frames = [
('__exit__', 'raise exc_details[1]'),
('__exit__', 'if cb(*exc_details):'),
]


class TestRedirectStream:
Expand Down Expand Up @@ -1064,5 +1226,59 @@ def test_cm_is_reentrant(self):
1/0
self.assertTrue(outer_continued)


class TestChdir(unittest.TestCase):
def make_relative_path(self, *parts):
return os.path.join(
os.path.dirname(os.path.realpath(__file__)),
*parts,
)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_simple(self):
old_cwd = os.getcwd()
target = self.make_relative_path('data')
self.assertNotEqual(old_cwd, target)

with chdir(target):
self.assertEqual(os.getcwd(), target)
self.assertEqual(os.getcwd(), old_cwd)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_reentrant(self):
old_cwd = os.getcwd()
target1 = self.make_relative_path('data')
target2 = self.make_relative_path('ziptestdata')
self.assertNotIn(old_cwd, (target1, target2))
chdir1, chdir2 = chdir(target1), chdir(target2)

with chdir1:
self.assertEqual(os.getcwd(), target1)
with chdir2:
self.assertEqual(os.getcwd(), target2)
with chdir1:
self.assertEqual(os.getcwd(), target1)
self.assertEqual(os.getcwd(), target2)
self.assertEqual(os.getcwd(), target1)
self.assertEqual(os.getcwd(), old_cwd)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_exception(self):
old_cwd = os.getcwd()
target = self.make_relative_path('data')
self.assertNotEqual(old_cwd, target)

try:
with chdir(target):
self.assertEqual(os.getcwd(), target)
raise RuntimeError("boom")
except RuntimeError as re:
self.assertEqual(str(re), "boom")
self.assertEqual(os.getcwd(), old_cwd)


if __name__ == "__main__":
unittest.main()
Morty Proxy This is a proxified and sanitized view of the page, visit original site.