Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Lib/test/test_asyncio/test_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@ def test_future_cancel_message_setter(self):
f.cancel('my message')
f._cancel_message = 'my new message'
self.assertEqual(f._cancel_message, 'my new message')
f._cancel_message = None
self.assertIsNone(f._cancel_message)
f._cancel_message = 'my new message'
if not isinstance(f, futures._PyFuture):
# The C implementation does not support deletion.
with self.assertRaises(AttributeError):
del f._cancel_message
self.assertEqual(f._cancel_message, 'my new message')

# Also check that the value is used for cancel().
with self.assertRaises(asyncio.CancelledError):
Expand Down
22 changes: 21 additions & 1 deletion Lib/test/test_ctypes/test_delattr.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import unittest
from ctypes import Structure, c_char, c_int
from ctypes import CDLL, Structure, c_char, c_int
from test.support import import_helper


class X(Structure):
Expand All @@ -21,6 +22,25 @@ def test_struct(self):
with self.assertRaises(TypeError):
del struct.foo

def test_raw(self):
chararray = (c_char * 5)()
with self.assertRaises(AttributeError):
del chararray.raw

def test_func_pointer(self):
# Deleting these attributes restores the default.
dll = CDLL(import_helper.import_module('_ctypes_test').__file__)
func = dll._testfunc_i_bhilfd
func.argtypes = [c_int]
func.restype = c_int
func.errcheck = lambda *args: None
del func.argtypes
self.assertIsNone(func.argtypes)
del func.errcheck
self.assertIsNone(func.errcheck)
del func.restype
self.assertIs(func.restype, c_int)


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion Lib/test/test_decimal.py
Original file line number Diff line number Diff line change
Expand Up @@ -4331,7 +4331,7 @@ def test_invalid_context(self):

# Attributes cannot be deleted
for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
'flags', 'traps']:
'flags', 'traps', '_allcr', '_flags', '_traps']:
self.assertRaises(AttributeError, c.__delattr__, attr)

# Invalid attributes
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_defaultdict.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ def test_basic(self):
self.assertIn(42, d2.keys())
self.assertNotIn(12, d2)
self.assertNotIn(12, d2.keys())
d2.default_factory = list
del d2.default_factory
self.assertEqual(d2.default_factory, None)
d2.default_factory = None
self.assertEqual(d2.default_factory, None)
try:
Expand Down
45 changes: 45 additions & 0 deletions Lib/test/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,44 @@ def test_invalid_setattr(self):
msg = "exception context must be None or derive from BaseException"
self.assertRaisesRegex(TE, msg, setattr, exc, '__context__', 1)

def test_object_attributes(self):
# These attributes are implemented as plain object members:
# they accept any object and are reset to None when deleted.
cases = [
(SyntaxError('msgStr'), 'msg'),
(SyntaxError('msgStr'), 'filename'),
(SyntaxError('msgStr'), 'lineno'),
(SyntaxError('msgStr'), 'offset'),
(SyntaxError('msgStr'), 'end_lineno'),
(SyntaxError('msgStr'), 'end_offset'),
(SyntaxError('msgStr'), 'text'),
(SyntaxError('msgStr'), 'print_file_and_line'),
(SyntaxError('msgStr'), '_metadata'),
(ImportError('msgStr'), 'msg'),
(ImportError('msgStr'), 'name'),
(ImportError('msgStr'), 'path'),
(ImportError('msgStr'), 'name_from'),
(SystemExit(1), 'code'),
(StopIteration(), 'value'),
(NameError('msgStr'), 'name'),
(AttributeError('msgStr'), 'name'),
(AttributeError('msgStr'), 'obj'),
(OSError(2, 'msgStr'), 'errno'),
(OSError(2, 'msgStr'), 'strerror'),
(OSError(2, 'msgStr'), 'filename'),
(OSError(2, 'msgStr'), 'filename2'),
(UnicodeDecodeError('utf-8', b'\xff', 0, 1, 'reasonStr'), 'reason'),
]
if sys.platform == 'win32':
cases.append((OSError(2, 'msgStr'), 'winerror'))
for exc, name in cases:
with self.subTest(exc=type(exc).__name__, name=name):
for value in 'strValue', 42, [1, 2], None:
setattr(exc, name, value)
self.assertEqual(getattr(exc, name), value)
delattr(exc, name)
self.assertIsNone(getattr(exc, name))

def test_invalid_delattr(self):
TE = TypeError
try:
Expand Down Expand Up @@ -739,6 +777,13 @@ def testChainingDescriptors(self):
self.assertTrue(e.__suppress_context__)
e.__suppress_context__ = False
self.assertFalse(e.__suppress_context__)
with self.assertRaisesRegex(TypeError,
'attribute value type must be bool'):
e.__suppress_context__ = 1
with self.assertRaisesRegex(TypeError,
"can't delete numeric/char attribute"):
del e.__suppress_context__
self.assertFalse(e.__suppress_context__)

def testKeywordArgs(self):
# test that builtin exception don't take keyword args,
Expand Down
27 changes: 27 additions & 0 deletions Lib/test/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,33 @@ def test_f_lineno_del_segfault(self):
with self.assertRaises(AttributeError):
del f.f_lineno

def test_f_trace(self):
f, _, _ = self.make_frames()
def tracer(*args):
pass
for value in tracer, 42, None:
f.f_trace = value
self.assertEqual(f.f_trace, value)
f.f_trace = tracer
del f.f_trace
self.assertIsNone(f.f_trace)

def test_f_trace_lines_and_opcodes(self):
f, _, _ = self.make_frames()
for name in 'f_trace_lines', 'f_trace_opcodes':
with self.subTest(name=name):
for value in False, True:
setattr(f, name, value)
self.assertEqual(getattr(f, name), value)
with self.assertRaisesRegex(TypeError,
'attribute value type must be bool'):
setattr(f, name, 1)
with self.assertRaisesRegex(TypeError,
"can't delete numeric/char attribute"):
del f.f_trace_lines
with self.assertRaisesRegex(AttributeError, 'cannot be deleted'):
del f.f_trace_opcodes

def test_f_generator(self):
# Test f_generator in different contexts.

Expand Down
35 changes: 35 additions & 0 deletions Lib/test/test_funcattrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,41 @@ def e(): return num_one, num_two
self.fail("__code__ with different numbers of free vars should "
"not be possible")

def test___kwdefaults__(self):
def func(a=1, *, b=2, c=3):
return a, b, c
self.assertEqual(func.__kwdefaults__, {'b': 2, 'c': 3})
func.__kwdefaults__ = {'b': 4}
self.assertEqual(func.__kwdefaults__, {'b': 4})
self.assertEqual(func(c=5), (1, 4, 5))
func.__kwdefaults__ = None
self.assertIsNone(func.__kwdefaults__)
self.assertRaises(TypeError, func)
with self.assertRaisesRegex(TypeError,
'__kwdefaults__ must be set to a dict object'):
func.__kwdefaults__ = [('b', 4)]
del func.__kwdefaults__
self.assertIsNone(func.__kwdefaults__)

def test_invalid___code___deletion(self):
def func(): pass
with self.assertRaisesRegex(TypeError,
'__code__ must be set to a code object'):
func.__code__ = None
with self.assertRaisesRegex(TypeError,
'__code__ must be set to a code object'):
del func.__code__

def test___doc__(self):
def func():
"docstring"
self.assertEqual(func.__doc__, 'docstring')
for value in 'other', 42, None:
func.__doc__ = value
self.assertEqual(func.__doc__, value)
del func.__doc__
self.assertIsNone(func.__doc__)

def test_blank_func_defaults(self):
self.assertEqual(self.b.__defaults__, None)
del self.b.__defaults__
Expand Down
21 changes: 21 additions & 0 deletions Lib/test/test_io/test_fileio.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ def testBlksize(self):
fst = os.fstat(self.f.fileno())
blksize = getattr(fst, 'st_blksize', blksize)
self.assertEqual(self.f._blksize, blksize)
# it is read-only
with self.assertRaises(AttributeError):
self.f._blksize = blksize
with self.assertRaises(AttributeError):
del self.f._blksize


# verify readinto
def testReadintoByteArray(self):
Expand Down Expand Up @@ -503,6 +509,21 @@ class CAutoFileTests(AutoFileTests, unittest.TestCase):
FileIO = _io.FileIO
modulename = '_io'

def testFinalizing(self):
# test the private _finalizing attribute
self.assertIs(self.f._finalizing, False)
self.f._finalizing = True
self.assertIs(self.f._finalizing, True)
with self.assertRaisesRegex(TypeError,
'attribute value type must be bool'):
self.f._finalizing = 1
with self.assertRaisesRegex(TypeError,
"can't delete numeric/char attribute"):
del self.f._finalizing
# closing a file which is being finalized emits a ResourceWarning
self.f._finalizing = False


class PyAutoFileTests(AutoFileTests, unittest.TestCase):
FileIO = _pyio.FileIO
modulename = '_pyio'
Expand Down
23 changes: 23 additions & 0 deletions Lib/test/test_io/test_textio.py
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,29 @@ def _to_memoryview(buf):
class CTextIOWrapperTest(TextIOWrapperTest, CTestCase):
shutdown_error = "LookupError: unknown encoding: ascii"

def test_chunk_size(self):
t = self.TextIOWrapper(self.BytesIO(), encoding="utf-8")
self.assertGreater(t._CHUNK_SIZE, 0)
t._CHUNK_SIZE = 1024
self.assertEqual(t._CHUNK_SIZE, 1024)
with self.assertRaisesRegex(ValueError,
'a strictly positive integer is required'):
t._CHUNK_SIZE = 0
with self.assertRaises(TypeError):
t._CHUNK_SIZE = 'x'
with self.assertRaises(ValueError):
t._CHUNK_SIZE = sys.maxsize + 1
with self.assertRaises(ValueError):
t._CHUNK_SIZE = -sys.maxsize - 2
with self.assertRaises(ValueError):
t._CHUNK_SIZE = 2**1000
with self.assertRaises(ValueError):
t._CHUNK_SIZE = -2**1000
with self.assertRaisesRegex(AttributeError, 'cannot be deleted'):
del t._CHUNK_SIZE
# a failed assignment does not change the value
self.assertEqual(t._CHUNK_SIZE, 1024)

def test_initialization(self):
r = self.BytesIO(b"\xc3\xa9\n\n")
b = self.BufferedReader(r, 1000)
Expand Down
25 changes: 25 additions & 0 deletions Lib/test/test_kqueue.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,31 @@ def test_create_event(self):
self.assertNotEqual(ev, other)


def test_event_attributes(self):
fd = os.open(os.devnull, os.O_WRONLY)
self.addCleanup(os.close, fd)

ev = select.kevent(fd)
# All attributes are numeric members: they can be set and cannot be
# deleted.
for name, value in (('ident', 1), ('filter', select.KQ_FILTER_WRITE),
('flags', select.KQ_EV_DELETE), ('fflags', 2),
('data', 3), ('udata', 4)):
with self.subTest(name=name):
setattr(ev, name, value)
self.assertEqual(getattr(ev, name), value)
with self.assertRaises(TypeError):
setattr(ev, name, 'not a number')
with self.assertRaises(OverflowError):
setattr(ev, name, 2**1000)
with self.assertRaises(OverflowError):
setattr(ev, name, -2**1000)
with self.assertRaisesRegex(
TypeError, "can't delete numeric/char attribute"):
delattr(ev, name)
# a failed assignment does not change the value
self.assertEqual(getattr(ev, name), value)

def test_queue_event(self):
serverSocket = socket.create_server(('127.0.0.1', 0))
client = socket.socket()
Expand Down
51 changes: 51 additions & 0 deletions Lib/test/test_pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,57 @@ class CPicklerTests(PyPicklerTests):
pickler = _pickle.Pickler
unpickler = _pickle.Unpickler

def test_c_pickler_attributes(self):
pickler = _pickle.Pickler(io.BytesIO())
for name in 'bin', 'fast':
with self.subTest(name=name):
for value in 0, 1, True:
setattr(pickler, name, value)
self.assertEqual(getattr(pickler, name), int(value))
with self.assertRaises(TypeError):
setattr(pickler, name, 'x')
with self.assertRaises(OverflowError):
setattr(pickler, name, sys.maxsize + 1)
with self.assertRaises(OverflowError):
setattr(pickler, name, -sys.maxsize - 2)
with self.assertRaises(OverflowError):
setattr(pickler, name, 2**1000)
with self.assertRaises(OverflowError):
setattr(pickler, name, -2**1000)
with self.assertRaisesRegex(
TypeError, "can't delete numeric/char attribute"):
delattr(pickler, name)
# a failed assignment does not change the value
self.assertEqual(getattr(pickler, name), 1)

self.assertRaises(AttributeError, getattr, pickler,
'dispatch_table')
table = {}
pickler.dispatch_table = table
self.assertIs(pickler.dispatch_table, table)
del pickler.dispatch_table
self.assertRaises(AttributeError, getattr, pickler,
'dispatch_table')

pickler.memo = {}
self.assertEqual(pickler.memo.copy(), {})
with self.assertRaisesRegex(TypeError, 'must be a PicklerMemoProxy'):
pickler.memo = None
with self.assertRaisesRegex(TypeError,
'attribute deletion is not supported'):
del pickler.memo

def test_c_unpickler_attributes(self):
unpickler = _pickle.Unpickler(io.BytesIO(b'.'))
unpickler.memo = {}
self.assertEqual(unpickler.memo.copy(), {})
with self.assertRaisesRegex(TypeError,
'must be an UnpicklerMemoProxy'):
unpickler.memo = None
with self.assertRaisesRegex(TypeError,
'attribute deletion is not supported'):
del unpickler.memo

class CPersPicklerTests(PyPersPicklerTests):
pickler = _pickle.Pickler
unpickler = _pickle.Unpickler
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_sqlite3/test_dbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,13 @@ def test_connection_init_good_isolation_levels(self):
cx.isolation_level = level
self.assertEqual(cx.isolation_level, level)

def test_connection_delete_isolation_level(self):
with memory_database() as cx:
with self.assertRaisesRegex(AttributeError,
"cannot delete attribute"):
del cx.isolation_level
self.assertEqual(cx.isolation_level, "")

def test_connection_reinit(self):
with memory_database() as cx:
cx.text_factory = bytes
Expand Down Expand Up @@ -1078,6 +1085,8 @@ def test_invalid_array_size(self):
self.assertRaises(TypeError, setter, 1.0)
self.assertRaises(ValueError, setter, -3)
self.assertRaises(OverflowError, setter, UINT32_MAX + 1)
self.assertRaisesRegex(AttributeError, 'cannot be deleted',
delattr, self.cu, 'arraysize')

def test_fetchmany(self):
# no active SQL statement
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_sqlite3/test_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@ def test_autocommit_setget_invalid(self):
with self.subTest(mode=mode):
with self.assertRaisesRegex(ValueError, msg):
sqlite.connect(":memory:", autocommit=mode)
with memory_database() as cx:
with self.assertRaisesRegex(ValueError, msg):
cx.autocommit = mode

def test_autocommit_disabled(self):
expected = [
Expand Down
Loading
Loading