mirror of https://github.com/python/cpython
Add tests for _source to importable and exec'able.
Move __name__ back out of the template; the responsibility for setting __name__ lies with the caller (which knows something about the new namespace), not with the class definition (which doesn't know about the namespace it is being built in).
This commit is contained in:
parent
5d43cff623
commit
f6d3e8eaef
|
@ -234,8 +234,6 @@ class OrderedDict(dict):
|
|||
################################################################################
|
||||
|
||||
_class_template = '''\
|
||||
__name__ = 'namedtuple_{typename}'
|
||||
|
||||
from builtins import property as _property, tuple as _tuple
|
||||
from operator import itemgetter as _itemgetter
|
||||
from collections import OrderedDict
|
||||
|
@ -353,8 +351,9 @@ def namedtuple(typename, field_names, verbose=False, rename=False):
|
|||
for index, name in enumerate(field_names))
|
||||
)
|
||||
|
||||
# Execute the class definition string in a temporary namespace
|
||||
namespace = {}
|
||||
# Execute the template string in a temporary namespace and
|
||||
# support tracing utilities by setting a value for frame.f_globals['__name__']
|
||||
namespace = dict(__name__='namedtuple_%s' % typename)
|
||||
try:
|
||||
exec(class_definition, namespace)
|
||||
except SyntaxError as e:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Unit tests for collections.py."""
|
||||
|
||||
import unittest, doctest, operator
|
||||
from test.support import TESTFN, forget, unlink
|
||||
import inspect
|
||||
from test import support
|
||||
from collections import namedtuple, Counter, OrderedDict, _count_elements
|
||||
|
@ -327,6 +328,39 @@ class TestNamedTuple(unittest.TestCase):
|
|||
pass
|
||||
self.assertEqual(repr(B(1)), 'B(x=1)')
|
||||
|
||||
def test_source(self):
|
||||
# verify that _source can be run through exec()
|
||||
tmp = namedtuple('Color', 'red green blue')
|
||||
self.assertNotIn('Color', globals())
|
||||
exec(tmp._source, globals())
|
||||
self.assertIn('Color', globals())
|
||||
c = Color(10, 20, 30)
|
||||
self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
|
||||
self.assertEqual(Color._fields, ('red', 'green', 'blue'))
|
||||
|
||||
def test_source_importable(self):
|
||||
tmp = namedtuple('Color', 'hue sat val')
|
||||
|
||||
compiled = None
|
||||
source = TESTFN + '.py'
|
||||
with open(source, 'w') as f:
|
||||
print(tmp._source, file=f)
|
||||
|
||||
if TESTFN in sys.modules:
|
||||
del sys.modules[TESTFN]
|
||||
try:
|
||||
mod = __import__(TESTFN)
|
||||
compiled = mod.__file__
|
||||
Color = mod.Color
|
||||
c = Color(10, 20, 30)
|
||||
self.assertEqual((c.hue, c.sat, c.val), (10, 20, 30))
|
||||
self.assertEqual(Color._fields, ('hue', 'sat', 'val'))
|
||||
finally:
|
||||
forget(TESTFN)
|
||||
if compiled:
|
||||
unlink(compiled)
|
||||
unlink(source)
|
||||
|
||||
|
||||
################################################################################
|
||||
### Abstract Base Classes
|
||||
|
|
Loading…
Reference in New Issue