summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/contextlib.py2
-rw-r--r--Lib/doctest.py4
-rw-r--r--Lib/os.py8
-rw-r--r--Lib/test/test_ast.py4
-rw-r--r--Lib/test/test_exceptions.py60
-rw-r--r--Lib/test/test_grammar.py2
-rw-r--r--Lib/test/test_opcodes.py12
-rw-r--r--Lib/test/test_raise.py417
-rw-r--r--Lib/test/test_syntax.py10
-rw-r--r--Lib/test/test_sys.py5
-rw-r--r--Lib/test/test_with.py2
-rw-r--r--Lib/test/test_zipimport.py2
-rw-r--r--Lib/urllib.py8
-rw-r--r--Lib/urllib2.py2
-rw-r--r--Lib/wsgiref/handlers.py2
15 files changed, 507 insertions, 33 deletions
diff --git a/Lib/contextlib.py b/Lib/contextlib.py
index bc810b0..38ec577 100644
--- a/Lib/contextlib.py
+++ b/Lib/contextlib.py
@@ -125,7 +125,7 @@ def nested(*managers):
# Don't rely on sys.exc_info() still containing
# the right information. Another exception may
# have been raised and caught by an exit method
- raise exc[0], exc[1], exc[2]
+ raise exc[0](exc[1]).with_traceback(exc[2])
class closing(object):
diff --git a/Lib/doctest.py b/Lib/doctest.py
index 2374d44..395f8b6 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -1608,7 +1608,7 @@ class DebugRunner(DocTestRunner):
'42\n'
>>> exc_info = failure.exc_info
- >>> raise exc_info[0], exc_info[1], exc_info[2]
+ >>> raise exc_info[1] # Already has the traceback
Traceback (most recent call last):
...
KeyError
@@ -2146,7 +2146,7 @@ class DocTestCase(unittest.TestCase):
'42\n'
>>> exc_info = failure.exc_info
- >>> raise exc_info[0], exc_info[1], exc_info[2]
+ >>> raise exc_info[1] # Already has the traceback
Traceback (most recent call last):
...
KeyError
diff --git a/Lib/os.py b/Lib/os.py
index b8d7a0f..727d0cb 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -113,7 +113,7 @@ elif 'ce' in _names:
del ce
else:
- raise ImportError, 'no os specific module found'
+ raise ImportError('no os specific module found')
sys.modules['os.path'] = path
from os.path import curdir, pardir, sep, pathsep, defpath, altsep, devnull
@@ -386,8 +386,8 @@ def _execvpe(file, args, env=None):
saved_exc = e
saved_tb = tb
if saved_exc:
- raise error, saved_exc, saved_tb
- raise error, last_exc, tb
+ raise error(saved_exc).with_traceback(saved_tb)
+ raise error(last_exc).with_traceback(tb)
# Change environ to automatically call putenv(), unsetenv if they exist.
@@ -492,7 +492,7 @@ if _exists("fork") and not _exists("spawnv") and _exists("execv"):
elif WIFEXITED(sts):
return WEXITSTATUS(sts)
else:
- raise error, "Not stopped, signaled or exited???"
+ raise error("Not stopped, signaled or exited???")
def spawnv(mode, file, args):
"""spawnv(mode, file, args) -> integer
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
index b8c1ed9..6299123 100644
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -37,7 +37,7 @@ exec_tests = [
# If
"if v:pass",
# Raise
- "raise Exception, 'string'",
+ "raise Exception('string')",
# TryExcept
"try:\n pass\nexcept Exception:\n pass",
# TryFinally
@@ -160,7 +160,7 @@ exec_results = [
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]),
('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]),
('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]),
-('Module', [('Raise', (1, 0), ('Name', (1, 6), 'Exception', ('Load',)), ('Str', (1, 17), 'string'), None)]),
+('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], [], None, None), None)]),
('Module', [('TryExcept', (1, 0), [('Pass', (2, 2))], [('excepthandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))], 3, 0)], [])]),
('Module', [('TryFinally', (1, 0), [('Pass', (2, 2))], [('Pass', (4, 2))])]),
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]),
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 90f6ae7..d2a2191 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -13,7 +13,7 @@ class ExceptionTests(unittest.TestCase):
def raise_catch(self, exc, excname):
try:
- raise exc, "spam"
+ raise exc("spam")
except exc as err:
buf1 = str(err)
try:
@@ -141,7 +141,7 @@ class ExceptionTests(unittest.TestCase):
class BadException(Exception):
def __init__(self_):
- raise RuntimeError, "can't instantiate BadException"
+ raise RuntimeError("can't instantiate BadException")
class InvalidException:
pass
@@ -305,6 +305,62 @@ class ExceptionTests(unittest.TestCase):
'pickled "%r", attribute "%s' %
(e, checkArgName))
+ def testWithTraceback(self):
+ try:
+ raise IndexError(4)
+ except:
+ tb = sys.exc_info()[2]
+
+ e = BaseException().with_traceback(tb)
+ self.failUnless(isinstance(e, BaseException))
+ self.assertEqual(e.__traceback__, tb)
+
+ e = IndexError(5).with_traceback(tb)
+ self.failUnless(isinstance(e, IndexError))
+ self.assertEqual(e.__traceback__, tb)
+
+ class MyException(Exception):
+ pass
+
+ e = MyException().with_traceback(tb)
+ self.failUnless(isinstance(e, MyException))
+ self.assertEqual(e.__traceback__, tb)
+
+ def testInvalidTraceback(self):
+ try:
+ Exception().__traceback__ = 5
+ except TypeError as e:
+ self.failUnless("__traceback__ must be a traceback" in str(e))
+ else:
+ self.fail("No exception raised")
+
+ def testNoneClearsTracebackAttr(self):
+ try:
+ raise IndexError(4)
+ except:
+ tb = sys.exc_info()[2]
+
+ e = Exception()
+ e.__traceback__ = tb
+ e.__traceback__ = None
+ self.assertEqual(e.__traceback__, None)
+
+ def testChainingAttrs(self):
+ e = Exception()
+ self.assertEqual(e.__context__, None)
+ self.assertEqual(e.__cause__, None)
+
+ e = TypeError()
+ self.assertEqual(e.__context__, None)
+ self.assertEqual(e.__cause__, None)
+
+ class MyException(EnvironmentError):
+ pass
+
+ e = MyException()
+ self.assertEqual(e.__context__, None)
+ self.assertEqual(e.__cause__, None)
+
def testKeywordArgs(self):
# test that builtin exception don't take keyword args,
# but user-defined subclasses can if they want
diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py
index bfc77fe..ee3ffc7 100644
--- a/Lib/test/test_grammar.py
+++ b/Lib/test/test_grammar.py
@@ -438,7 +438,7 @@ class GrammarTests(unittest.TestCase):
def testRaise(self):
# 'raise' test [',' test]
- try: raise RuntimeError, 'just testing'
+ try: raise RuntimeError('just testing')
except RuntimeError: pass
try: raise KeyboardInterrupt
except KeyboardInterrupt: pass
diff --git a/Lib/test/test_opcodes.py b/Lib/test/test_opcodes.py
index 0ee51a8..d65c5cc 100644
--- a/Lib/test/test_opcodes.py
+++ b/Lib/test/test_opcodes.py
@@ -46,14 +46,10 @@ class OpcodeTest(unittest.TestCase):
a = AClass()
b = BClass()
- try: raise AClass, b
- except BClass as v:
- if v != b: self.fail("v!=b")
- else: self.fail("no exception")
-
- try: raise b
+ try:
+ raise b
except AClass as v:
- if v != b: self.fail("v!=b AClass")
+ self.assertEqual(v, b)
else:
self.fail("no exception")
@@ -62,7 +58,7 @@ class OpcodeTest(unittest.TestCase):
##except TypeError: pass
##else: self.fail("no exception")
- try: raise DClass, a
+ try: raise DClass(a)
except DClass as v:
self.assert_(isinstance(v, DClass))
else:
diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py
new file mode 100644
index 0000000..ac0a32b
--- /dev/null
+++ b/Lib/test/test_raise.py
@@ -0,0 +1,417 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Tests for the raise statement."""
+
+from test import test_support
+import sys
+import types
+import unittest
+
+
+def get_tb():
+ try:
+ raise OSError()
+ except:
+ return sys.exc_info()[2]
+
+
+class TestRaise(unittest.TestCase):
+ def test_invalid_reraise(self):
+ try:
+ raise
+ except RuntimeError as e:
+ self.failUnless("No active exception" in str(e))
+ else:
+ self.fail("No exception raised")
+
+ def test_reraise(self):
+ try:
+ try:
+ raise IndexError()
+ except IndexError as e:
+ exc1 = e
+ raise
+ except IndexError as exc2:
+ self.failUnless(exc1 is exc2)
+ else:
+ self.fail("No exception raised")
+
+
+class TestCause(unittest.TestCase):
+ def test_invalid_cause(self):
+ try:
+ raise IndexError from 5
+ except TypeError as e:
+ self.failUnless("exception cause" in str(e))
+ else:
+ self.fail("No exception raised")
+
+ def test_class_cause(self):
+ try:
+ raise IndexError from KeyError
+ except IndexError as e:
+ self.failUnless(isinstance(e.__cause__, KeyError))
+ else:
+ self.fail("No exception raised")
+
+ def test_instance_cause(self):
+ cause = KeyError()
+ try:
+ raise IndexError from cause
+ except IndexError as e:
+ self.failUnless(e.__cause__ is cause)
+ else:
+ self.fail("No exception raised")
+
+
+class TestTraceback(unittest.TestCase):
+ def test_sets_traceback(self):
+ try:
+ raise IndexError()
+ except IndexError as e:
+ self.failUnless(isinstance(e.__traceback__, types.TracebackType))
+ else:
+ self.fail("No exception raised")
+
+ def test_accepts_traceback(self):
+ tb = get_tb()
+ try:
+ raise IndexError().with_traceback(tb)
+ except IndexError as e:
+ self.assertNotEqual(e.__traceback__, tb)
+ self.assertEqual(e.__traceback__.tb_next, tb)
+ else:
+ self.fail("No exception raised")
+
+
+# Disabled until context is implemented
+# class TestContext(object):
+# def test_instance_context_bare_raise(self):
+# context = IndexError()
+# try:
+# try:
+# raise context
+# except:
+# raise OSError()
+# except OSError as e:
+# self.assertEqual(e.__context__, context)
+# else:
+# self.fail("No exception raised")
+#
+# def test_class_context_bare_raise(self):
+# context = IndexError
+# try:
+# try:
+# raise context
+# except:
+# raise OSError()
+# except OSError as e:
+# self.assertNotEqual(e.__context__, context)
+# self.failUnless(isinstance(e.__context__, context))
+# else:
+# self.fail("No exception raised")
+
+
+class TestRemovedFunctionality(unittest.TestCase):
+ def test_tuples(self):
+ try:
+ raise (IndexError, KeyError) # This should be a tuple!
+ except TypeError:
+ pass
+ else:
+ self.fail("No exception raised")
+
+ def test_strings(self):
+ try:
+ raise "foo"
+ except TypeError:
+ pass
+ else:
+ self.fail("No exception raised")
+
+
+def test_main():
+ test_support.run_unittest(__name__)
+
+
+if __name__ == "__main__":
+ unittest.main()
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Tests for the raise statement."""
+
+from test import test_support
+import sys
+import types
+import unittest
+
+
+def get_tb():
+ try:
+ raise OSError()
+ except:
+ return sys.exc_info()[2]
+
+
+class TestRaise(unittest.TestCase):
+ def test_invalid_reraise(self):
+ try:
+ raise
+ except RuntimeError as e:
+ self.failUnless("No active exception" in str(e))
+ else:
+ self.fail("No exception raised")
+
+ def test_reraise(self):
+ try:
+ try:
+ raise IndexError()
+ except IndexError as e:
+ exc1 = e
+ raise
+ except IndexError as exc2:
+ self.failUnless(exc1 is exc2)
+ else:
+ self.fail("No exception raised")
+
+
+class TestCause(unittest.TestCase):
+ def test_invalid_cause(self):
+ try:
+ raise IndexError from 5
+ except TypeError as e:
+ self.failUnless("exception cause" in str(e))
+ else:
+ self.fail("No exception raised")
+
+ def test_class_cause(self):
+ try:
+ raise IndexError from KeyError
+ except IndexError as e:
+ self.failUnless(isinstance(e.__cause__, KeyError))
+ else:
+ self.fail("No exception raised")
+
+ def test_instance_cause(self):
+ cause = KeyError()
+ try:
+ raise IndexError from cause
+ except IndexError as e:
+ self.failUnless(e.__cause__ is cause)
+ else:
+ self.fail("No exception raised")
+
+
+class TestTraceback(unittest.TestCase):
+ def test_sets_traceback(self):
+ try:
+ raise IndexError()
+ except IndexError as e:
+ self.failUnless(isinstance(e.__traceback__, types.TracebackType))
+ else:
+ self.fail("No exception raised")
+
+ def test_accepts_traceback(self):
+ tb = get_tb()
+ try:
+ raise IndexError().with_traceback(tb)
+ except IndexError as e:
+ self.assertNotEqual(e.__traceback__, tb)
+ self.assertEqual(e.__traceback__.tb_next, tb)
+ else:
+ self.fail("No exception raised")
+
+
+# Disabled until context is implemented
+# class TestContext(object):
+# def test_instance_context_bare_raise(self):
+# context = IndexError()
+# try:
+# try:
+# raise context
+# except:
+# raise OSError()
+# except OSError as e:
+# self.assertEqual(e.__context__, context)
+# else:
+# self.fail("No exception raised")
+#
+# def test_class_context_bare_raise(self):
+# context = IndexError
+# try:
+# try:
+# raise context
+# except:
+# raise OSError()
+# except OSError as e:
+# self.assertNotEqual(e.__context__, context)
+# self.failUnless(isinstance(e.__context__, context))
+# else:
+# self.fail("No exception raised")
+
+
+class TestRemovedFunctionality(unittest.TestCase):
+ def test_tuples(self):
+ try:
+ raise (IndexError, KeyError) # This should be a tuple!
+ except TypeError:
+ pass
+ else:
+ self.fail("No exception raised")
+
+ def test_strings(self):
+ try:
+ raise "foo"
+ except TypeError:
+ pass
+ else:
+ self.fail("No exception raised")
+
+
+def test_main():
+ test_support.run_unittest(__name__)
+
+
+if __name__ == "__main__":
+ unittest.main()
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Tests for the raise statement."""
+
+from test import test_support
+import sys
+import types
+import unittest
+
+
+def get_tb():
+ try:
+ raise OSError()
+ except:
+ return sys.exc_info()[2]
+
+
+class TestRaise(unittest.TestCase):
+ def test_invalid_reraise(self):
+ try:
+ raise
+ except RuntimeError as e:
+ self.failUnless("No active exception" in str(e))
+ else:
+ self.fail("No exception raised")
+
+ def test_reraise(self):
+ try:
+ try:
+ raise IndexError()
+ except IndexError as e:
+ exc1 = e
+ raise
+ except IndexError as exc2:
+ self.failUnless(exc1 is exc2)
+ else:
+ self.fail("No exception raised")
+
+
+class TestCause(unittest.TestCase):
+ def test_invalid_cause(self):
+ try:
+ raise IndexError from 5
+ except TypeError as e:
+ self.failUnless("exception cause" in str(e))
+ else:
+ self.fail("No exception raised")
+
+ def test_class_cause(self):
+ try:
+ raise IndexError from KeyError
+ except IndexError as e:
+ self.failUnless(isinstance(e.__cause__, KeyError))
+ else:
+ self.fail("No exception raised")
+
+ def test_instance_cause(self):
+ cause = KeyError()
+ try:
+ raise IndexError from cause
+ except IndexError as e:
+ self.failUnless(e.__cause__ is cause)
+ else:
+ self.fail("No exception raised")
+
+
+class TestTraceback(unittest.TestCase):
+ def test_sets_traceback(self):
+ try:
+ raise IndexError()
+ except IndexError as e:
+ self.failUnless(isinstance(e.__traceback__, types.TracebackType))
+ else:
+ self.fail("No exception raised")
+
+ def test_accepts_traceback(self):
+ tb = get_tb()
+ try:
+ raise IndexError().with_traceback(tb)
+ except IndexError as e:
+ self.assertNotEqual(e.__traceback__, tb)
+ self.assertEqual(e.__traceback__.tb_next, tb)
+ else:
+ self.fail("No exception raised")
+
+
+# Disabled until context is implemented
+# class TestContext(object):
+# def test_instance_context_bare_raise(self):
+# context = IndexError()
+# try:
+# try:
+# raise context
+# except:
+# raise OSError()
+# except OSError as e:
+# self.assertEqual(e.__context__, context)
+# else:
+# self.fail("No exception raised")
+#
+# def test_class_context_bare_raise(self):
+# context = IndexError
+# try:
+# try:
+# raise context
+# except:
+# raise OSError()
+# except OSError as e:
+# self.assertNotEqual(e.__context__, context)
+# self.failUnless(isinstance(e.__context__, context))
+# else:
+# self.fail("No exception raised")
+
+
+class TestRemovedFunctionality(unittest.TestCase):
+ def test_tuples(self):
+ try:
+ raise (IndexError, KeyError) # This should be a tuple!
+ except TypeError:
+ pass
+ else:
+ self.fail("No exception raised")
+
+ def test_strings(self):
+ try:
+ raise "foo"
+ except TypeError:
+ pass
+ else:
+ self.fail("No exception raised")
+
+
+def test_main():
+ test_support.run_unittest(__name__)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index 4297d22..546f7a8 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -460,6 +460,16 @@ leading to spurious errors.
...
SyntaxError: can't assign to function call
+Make sure that the old "raise X, Y[, Z]" form is gone:
+ >>> raise X, Y
+ Traceback (most recent call last):
+ ...
+ SyntaxError: invalid syntax
+ >>> raise X, Y, Z
+ Traceback (most recent call last):
+ ...
+ SyntaxError: invalid syntax
+
"""
import re
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index d9adf02..e737047 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -119,11 +119,6 @@ class SysModuleTest(unittest.TestCase):
# test that the exit machinery handles SystemExits properly
import subprocess
- # both unnormalized...
- rc = subprocess.call([sys.executable, "-c",
- "raise SystemExit, 46"])
- self.assertEqual(rc, 46)
- # ... and normalized
rc = subprocess.call([sys.executable, "-c",
"raise SystemExit(47)"])
self.assertEqual(rc, 47)
diff --git a/Lib/test/test_with.py b/Lib/test/test_with.py
index 3f1d358..4fc8fe9 100644
--- a/Lib/test/test_with.py
+++ b/Lib/test/test_with.py
@@ -87,7 +87,7 @@ class Nested(object):
ex = sys.exc_info()
self.entered = None
if ex is not exc_info:
- raise ex[0], ex[1], ex[2]
+ raise ex[0](ex[1]).with_traceback(ex[2])
class MockNested(Nested):
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py
index f38983f..58935b7 100644
--- a/Lib/test/test_zipimport.py
+++ b/Lib/test/test_zipimport.py
@@ -244,7 +244,7 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
def get_file():
return __file__
if __loader__.get_data("some.data") != b"some data":
- raise AssertionError, "bad data"\n"""
+ raise AssertionError("bad data")\n"""
pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
files = {TESTMOD + pyc_ext: (NOW, pyc),
"some.data": (NOW, "some data")}
diff --git a/Lib/urllib.py b/Lib/urllib.py
index 67f457d..a1e26f0 100644
--- a/Lib/urllib.py
+++ b/Lib/urllib.py
@@ -199,7 +199,7 @@ class URLopener:
else:
return getattr(self, name)(url, data)
except socket.error as msg:
- raise IOError, ('socket error', msg), sys.exc_info()[2]
+ raise IOError('socket error', msg).with_traceback(sys.exc_info()[2])
def open_unknown(self, fullurl, data=None):
"""Overridable interface to open unknown URL type."""
@@ -498,7 +498,7 @@ class URLopener:
headers = mimetools.Message(StringIO(headers))
return addinfourl(fp, headers, "ftp:" + url)
except ftperrors() as msg:
- raise IOError, ('ftp error', msg), sys.exc_info()[2]
+ raise IOError('ftp error', msg).with_traceback(sys.exc_info()[2])
def open_data(self, url, data=None):
"""Use "data" URL."""
@@ -809,7 +809,7 @@ class ftpwrapper:
conn = self.ftp.ntransfercmd(cmd)
except ftplib.error_perm as reason:
if str(reason)[:3] != '550':
- raise IOError, ('ftp error', reason), sys.exc_info()[2]
+ raise IOError('ftp error', reason).with_traceback(sys.exc_info()[2])
if not conn:
# Set transfer mode to ASCII!
self.ftp.voidcmd('TYPE A')
@@ -1186,7 +1186,7 @@ def urlencode(query,doseq=0):
# preserved for consistency
except TypeError:
ty,va,tb = sys.exc_info()
- raise TypeError, "not a valid non-string sequence or mapping object", tb
+ raise TypeError("not a valid non-string sequence or mapping object").with_traceback(tb)
l = []
if not doseq:
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index 72e2899..58e0153 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -1286,7 +1286,7 @@ class FTPHandler(BaseHandler):
headers = mimetools.Message(sf)
return addinfourl(fp, headers, req.get_full_url())
except ftplib.all_errors as msg:
- raise IOError, ('ftp error', msg), sys.exc_info()[2]
+ raise IOError('ftp error', msg).with_traceback(sys.exc_info()[2])
def connect_ftp(self, user, passwd, host, port, dirs, timeout):
fw = ftpwrapper(user, passwd, host, port, dirs, timeout)
diff --git a/Lib/wsgiref/handlers.py b/Lib/wsgiref/handlers.py
index d9347e5..8231620 100644
--- a/Lib/wsgiref/handlers.py
+++ b/Lib/wsgiref/handlers.py
@@ -151,7 +151,7 @@ class BaseHandler:
try:
if self.headers_sent:
# Re-raise original exception if headers sent
- raise exc_info[0], exc_info[1], exc_info[2]
+ raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
finally:
exc_info = None # avoid dangling circular ref
elif self.headers is not None: