3
3
import collections
4
4
import copy
5
5
import doctest
6
+ import inspect
6
7
import operator
7
8
import pickle
8
9
from random import choice , randrange
@@ -281,20 +282,50 @@ def test_defaults(self):
281
282
self .assertEqual (Point (1 ), (1 , 20 ))
282
283
self .assertEqual (Point (), (10 , 20 ))
283
284
285
+ def test_readonly (self ):
286
+ Point = namedtuple ('Point' , 'x y' )
287
+ p = Point (11 , 22 )
288
+ with self .assertRaises (AttributeError ):
289
+ p .x = 33
290
+ with self .assertRaises (AttributeError ):
291
+ del p .x
292
+ with self .assertRaises (TypeError ):
293
+ p [0 ] = 33
294
+ with self .assertRaises (TypeError ):
295
+ del p [0 ]
296
+ self .assertEqual (p .x , 11 )
297
+ self .assertEqual (p [0 ], 11 )
284
298
285
299
@unittest .skipIf (sys .flags .optimize >= 2 ,
286
300
"Docstrings are omitted with -O2 and above" )
287
301
def test_factory_doc_attr (self ):
288
302
Point = namedtuple ('Point' , 'x y' )
289
303
self .assertEqual (Point .__doc__ , 'Point(x, y)' )
304
+ Point .__doc__ = '2D point'
305
+ self .assertEqual (Point .__doc__ , '2D point' )
290
306
291
307
@unittest .skipIf (sys .flags .optimize >= 2 ,
292
308
"Docstrings are omitted with -O2 and above" )
293
- def test_doc_writable (self ):
309
+ def test_field_doc (self ):
294
310
Point = namedtuple ('Point' , 'x y' )
295
311
self .assertEqual (Point .x .__doc__ , 'Alias for field number 0' )
312
+ self .assertEqual (Point .y .__doc__ , 'Alias for field number 1' )
296
313
Point .x .__doc__ = 'docstring for Point.x'
297
314
self .assertEqual (Point .x .__doc__ , 'docstring for Point.x' )
315
+ # namedtuple can mutate doc of descriptors independently
316
+ Vector = namedtuple ('Vector' , 'x y' )
317
+ self .assertEqual (Vector .x .__doc__ , 'Alias for field number 0' )
318
+ Vector .x .__doc__ = 'docstring for Vector.x'
319
+ self .assertEqual (Vector .x .__doc__ , 'docstring for Vector.x' )
320
+
321
+ @support .cpython_only
322
+ @unittest .skipIf (sys .flags .optimize >= 2 ,
323
+ "Docstrings are omitted with -O2 and above" )
324
+ def test_field_doc_reuse (self ):
325
+ P = namedtuple ('P' , ['m' , 'n' ])
326
+ Q = namedtuple ('Q' , ['o' , 'p' ])
327
+ self .assertIs (P .m .__doc__ , Q .o .__doc__ )
328
+ self .assertIs (P .n .__doc__ , Q .p .__doc__ )
298
329
299
330
def test_name_fixer (self ):
300
331
for spec , renamed in [
@@ -319,16 +350,18 @@ def test_instance(self):
319
350
self .assertEqual (p , Point (y = 22 , x = 11 ))
320
351
self .assertEqual (p , Point (* (11 , 22 )))
321
352
self .assertEqual (p , Point (** dict (x = 11 , y = 22 )))
322
- self .assertRaises (TypeError , Point , 1 ) # too few args
323
- self .assertRaises (TypeError , Point , 1 , 2 , 3 ) # too many args
324
- self .assertRaises (TypeError , eval , 'Point(XXX=1, y=2)' , locals ()) # wrong keyword argument
325
- self .assertRaises (TypeError , eval , 'Point(x=1)' , locals ()) # missing keyword argument
353
+ self .assertRaises (TypeError , Point , 1 ) # too few args
354
+ self .assertRaises (TypeError , Point , 1 , 2 , 3 ) # too many args
355
+ with self .assertRaises (TypeError ): # wrong keyword argument
356
+ Point (XXX = 1 , y = 2 )
357
+ with self .assertRaises (TypeError ): # missing keyword argument
358
+ Point (x = 1 )
326
359
self .assertEqual (repr (p ), 'Point(x=11, y=22)' )
327
360
self .assertNotIn ('__weakref__' , dir (p ))
328
- self .assertEqual (p , Point ._make ([11 , 22 ])) # test _make classmethod
329
- self .assertEqual (p ._fields , ('x' , 'y' )) # test _fields attribute
330
- self .assertEqual (p ._replace (x = 1 ), (1 , 22 )) # test _replace method
331
- self .assertEqual (p ._asdict (), dict (x = 11 , y = 22 )) # test _asdict method
361
+ self .assertEqual (p , Point ._make ([11 , 22 ])) # test _make classmethod
362
+ self .assertEqual (p ._fields , ('x' , 'y' )) # test _fields attribute
363
+ self .assertEqual (p ._replace (x = 1 ), (1 , 22 )) # test _replace method
364
+ self .assertEqual (p ._asdict (), dict (x = 11 , y = 22 )) # test _asdict method
332
365
333
366
try :
334
367
p ._replace (x = 1 , error = 2 )
@@ -360,11 +393,15 @@ def test_tupleness(self):
360
393
x , y = p
361
394
self .assertEqual (p , (x , y )) # unpacks like a tuple
362
395
self .assertEqual ((p [0 ], p [1 ]), (11 , 22 )) # indexable like a tuple
363
- self .assertRaises (IndexError , p .__getitem__ , 3 )
396
+ with self .assertRaises (IndexError ):
397
+ p [3 ]
398
+ self .assertEqual (p [- 1 ], 22 )
399
+ self .assertEqual (hash (p ), hash ((11 , 22 )))
364
400
365
401
self .assertEqual (p .x , x )
366
402
self .assertEqual (p .y , y )
367
- self .assertRaises (AttributeError , eval , 'p.z' , locals ())
403
+ with self .assertRaises (AttributeError ):
404
+ p .z
368
405
369
406
def test_odd_sizes (self ):
370
407
Zero = namedtuple ('Zero' , '' )
@@ -514,13 +551,13 @@ class Point(namedtuple('_Point', ['x', 'y'])):
514
551
a .w = 5
515
552
self .assertEqual (a .__dict__ , {'w' : 5 })
516
553
517
- def test_namedtuple_can_mutate_doc_of_descriptors_independently (self ):
518
- A = namedtuple ('A ' , 'x y' )
519
- B = namedtuple ( 'B' , 'x y' )
520
- A . x . __doc__ = 'foo'
521
- B . x . __doc__ = 'bar'
522
- self .assertEqual ( A .x .__doc__ , 'foo' )
523
- self .assertEqual ( B .x .__doc__ , 'bar' )
554
+ def test_field_descriptor (self ):
555
+ Point = namedtuple ('Point ' , 'x y' )
556
+ p = Point ( 11 , 22 )
557
+ self . assertTrue ( inspect . isdatadescriptor ( Point . x ))
558
+ self . assertEqual ( Point . x . __get__ ( p ), 11 )
559
+ self .assertRaises ( AttributeError , Point .x .__set__ , p , 33 )
560
+ self .assertRaises ( AttributeError , Point .x .__delete__ , p )
524
561
525
562
526
563
################################################################################
0 commit comments