Home | History | Annotate | Download | only in test
      1 
      2 """Doctest for method/function calls.
      3 
      4 We're going the use these types for extra testing
      5 
      6     >>> from collections import UserList
      7     >>> from collections import UserDict
      8 
      9 We're defining four helper functions
     10 
     11     >>> def e(a,b):
     12     ...     print(a, b)
     13 
     14     >>> def f(*a, **k):
     15     ...     print(a, support.sortdict(k))
     16 
     17     >>> def g(x, *y, **z):
     18     ...     print(x, y, support.sortdict(z))
     19 
     20     >>> def h(j=1, a=2, h=3):
     21     ...     print(j, a, h)
     22 
     23 Argument list examples
     24 
     25     >>> f()
     26     () {}
     27     >>> f(1)
     28     (1,) {}
     29     >>> f(1, 2)
     30     (1, 2) {}
     31     >>> f(1, 2, 3)
     32     (1, 2, 3) {}
     33     >>> f(1, 2, 3, *(4, 5))
     34     (1, 2, 3, 4, 5) {}
     35     >>> f(1, 2, 3, *[4, 5])
     36     (1, 2, 3, 4, 5) {}
     37     >>> f(*[1, 2, 3], 4, 5)
     38     (1, 2, 3, 4, 5) {}
     39     >>> f(1, 2, 3, *UserList([4, 5]))
     40     (1, 2, 3, 4, 5) {}
     41     >>> f(1, 2, 3, *[4, 5], *[6, 7])
     42     (1, 2, 3, 4, 5, 6, 7) {}
     43     >>> f(1, *[2, 3], 4, *[5, 6], 7)
     44     (1, 2, 3, 4, 5, 6, 7) {}
     45     >>> f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7]))
     46     (1, 2, 3, 4, 5, 6, 7) {}
     47 
     48 Here we add keyword arguments
     49 
     50     >>> f(1, 2, 3, **{'a':4, 'b':5})
     51     (1, 2, 3) {'a': 4, 'b': 5}
     52     >>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
     53     Traceback (most recent call last):
     54         ...
     55     TypeError: f() got multiple values for keyword argument 'a'
     56     >>> f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)
     57     Traceback (most recent call last):
     58         ...
     59     TypeError: f() got multiple values for keyword argument 'a'
     60     >>> f(1, 2, a=3, **{'a': 4}, **{'a': 5})
     61     Traceback (most recent call last):
     62         ...
     63     TypeError: f() got multiple values for keyword argument 'a'
     64     >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
     65     (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
     66     >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
     67     (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
     68     >>> f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7})
     69     (1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8}
     70     >>> f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9})
     71     (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
     72 
     73     >>> f(1, 2, 3, **UserDict(a=4, b=5))
     74     (1, 2, 3) {'a': 4, 'b': 5}
     75     >>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
     76     (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
     77     >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
     78     (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
     79     >>> f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9))
     80     (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
     81 
     82 Examples with invalid arguments (TypeErrors). We're also testing the function
     83 names in the exception messages.
     84 
     85 Verify clearing of SF bug #733667
     86 
     87     >>> e(c=4)
     88     Traceback (most recent call last):
     89       ...
     90     TypeError: e() got an unexpected keyword argument 'c'
     91 
     92     >>> g()
     93     Traceback (most recent call last):
     94       ...
     95     TypeError: g() missing 1 required positional argument: 'x'
     96 
     97     >>> g(*())
     98     Traceback (most recent call last):
     99       ...
    100     TypeError: g() missing 1 required positional argument: 'x'
    101 
    102     >>> g(*(), **{})
    103     Traceback (most recent call last):
    104       ...
    105     TypeError: g() missing 1 required positional argument: 'x'
    106 
    107     >>> g(1)
    108     1 () {}
    109     >>> g(1, 2)
    110     1 (2,) {}
    111     >>> g(1, 2, 3)
    112     1 (2, 3) {}
    113     >>> g(1, 2, 3, *(4, 5))
    114     1 (2, 3, 4, 5) {}
    115 
    116     >>> class Nothing: pass
    117     ...
    118     >>> g(*Nothing())
    119     Traceback (most recent call last):
    120       ...
    121     TypeError: g() argument after * must be an iterable, not Nothing
    122 
    123     >>> class Nothing:
    124     ...     def __len__(self): return 5
    125     ...
    126 
    127     >>> g(*Nothing())
    128     Traceback (most recent call last):
    129       ...
    130     TypeError: g() argument after * must be an iterable, not Nothing
    131 
    132     >>> class Nothing():
    133     ...     def __len__(self): return 5
    134     ...     def __getitem__(self, i):
    135     ...         if i<3: return i
    136     ...         else: raise IndexError(i)
    137     ...
    138 
    139     >>> g(*Nothing())
    140     0 (1, 2) {}
    141 
    142     >>> class Nothing:
    143     ...     def __init__(self): self.c = 0
    144     ...     def __iter__(self): return self
    145     ...     def __next__(self):
    146     ...         if self.c == 4:
    147     ...             raise StopIteration
    148     ...         c = self.c
    149     ...         self.c += 1
    150     ...         return c
    151     ...
    152 
    153     >>> g(*Nothing())
    154     0 (1, 2, 3) {}
    155 
    156 Check for issue #4806: Does a TypeError in a generator get propagated with the
    157 right error message? (Also check with other iterables.)
    158 
    159     >>> def broken(): raise TypeError("myerror")
    160     ...
    161 
    162     >>> g(*(broken() for i in range(1)))
    163     Traceback (most recent call last):
    164       ...
    165     TypeError: myerror
    166 
    167     >>> class BrokenIterable1:
    168     ...     def __iter__(self):
    169     ...         raise TypeError('myerror')
    170     ...
    171     >>> g(*BrokenIterable1())
    172     Traceback (most recent call last):
    173       ...
    174     TypeError: myerror
    175 
    176     >>> class BrokenIterable2:
    177     ...     def __iter__(self):
    178     ...         yield 0
    179     ...         raise TypeError('myerror')
    180     ...
    181     >>> g(*BrokenIterable2())
    182     Traceback (most recent call last):
    183       ...
    184     TypeError: myerror
    185 
    186     >>> class BrokenSequence:
    187     ...     def __getitem__(self, idx):
    188     ...         raise TypeError('myerror')
    189     ...
    190     >>> g(*BrokenSequence())
    191     Traceback (most recent call last):
    192       ...
    193     TypeError: myerror
    194 
    195 Make sure that the function doesn't stomp the dictionary
    196 
    197     >>> d = {'a': 1, 'b': 2, 'c': 3}
    198     >>> d2 = d.copy()
    199     >>> g(1, d=4, **d)
    200     1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    201     >>> d == d2
    202     True
    203 
    204 What about willful misconduct?
    205 
    206     >>> def saboteur(**kw):
    207     ...     kw['x'] = 'm'
    208     ...     return kw
    209 
    210     >>> d = {}
    211     >>> kw = saboteur(a=1, **d)
    212     >>> d
    213     {}
    214 
    215 
    216     >>> g(1, 2, 3, **{'x': 4, 'y': 5})
    217     Traceback (most recent call last):
    218       ...
    219     TypeError: g() got multiple values for argument 'x'
    220 
    221     >>> f(**{1:2})
    222     Traceback (most recent call last):
    223       ...
    224     TypeError: f() keywords must be strings
    225 
    226     >>> h(**{'e': 2})
    227     Traceback (most recent call last):
    228       ...
    229     TypeError: h() got an unexpected keyword argument 'e'
    230 
    231     >>> h(*h)
    232     Traceback (most recent call last):
    233       ...
    234     TypeError: h() argument after * must be an iterable, not function
    235 
    236     >>> h(1, *h)
    237     Traceback (most recent call last):
    238       ...
    239     TypeError: h() argument after * must be an iterable, not function
    240 
    241     >>> h(*[1], *h)
    242     Traceback (most recent call last):
    243       ...
    244     TypeError: h() argument after * must be an iterable, not function
    245 
    246     >>> dir(*h)
    247     Traceback (most recent call last):
    248       ...
    249     TypeError: dir() argument after * must be an iterable, not function
    250 
    251     >>> None(*h)
    252     Traceback (most recent call last):
    253       ...
    254     TypeError: NoneType object argument after * must be an iterable, \
    255 not function
    256 
    257     >>> h(**h)
    258     Traceback (most recent call last):
    259       ...
    260     TypeError: h() argument after ** must be a mapping, not function
    261 
    262     >>> h(**[])
    263     Traceback (most recent call last):
    264       ...
    265     TypeError: h() argument after ** must be a mapping, not list
    266 
    267     >>> h(a=1, **h)
    268     Traceback (most recent call last):
    269       ...
    270     TypeError: h() argument after ** must be a mapping, not function
    271 
    272     >>> h(a=1, **[])
    273     Traceback (most recent call last):
    274       ...
    275     TypeError: h() argument after ** must be a mapping, not list
    276 
    277     >>> h(**{'a': 1}, **h)
    278     Traceback (most recent call last):
    279       ...
    280     TypeError: h() argument after ** must be a mapping, not function
    281 
    282     >>> h(**{'a': 1}, **[])
    283     Traceback (most recent call last):
    284       ...
    285     TypeError: h() argument after ** must be a mapping, not list
    286 
    287     >>> dir(**h)
    288     Traceback (most recent call last):
    289       ...
    290     TypeError: dir() argument after ** must be a mapping, not function
    291 
    292     >>> None(**h)
    293     Traceback (most recent call last):
    294       ...
    295     TypeError: NoneType object argument after ** must be a mapping, \
    296 not function
    297 
    298     >>> dir(b=1, **{'b': 1})
    299     Traceback (most recent call last):
    300       ...
    301     TypeError: dir() got multiple values for keyword argument 'b'
    302 
    303 Another helper function
    304 
    305     >>> def f2(*a, **b):
    306     ...     return a, b
    307 
    308 
    309     >>> d = {}
    310     >>> for i in range(512):
    311     ...     key = 'k%d' % i
    312     ...     d[key] = i
    313     >>> a, b = f2(1, *(2,3), **d)
    314     >>> len(a), len(b), b == d
    315     (3, 512, True)
    316 
    317     >>> class Foo:
    318     ...     def method(self, arg1, arg2):
    319     ...         return arg1+arg2
    320 
    321     >>> x = Foo()
    322     >>> Foo.method(*(x, 1, 2))
    323     3
    324     >>> Foo.method(x, *(1, 2))
    325     3
    326     >>> Foo.method(*(1, 2, 3))
    327     5
    328     >>> Foo.method(1, *[2, 3])
    329     5
    330 
    331 A PyCFunction that takes only positional parameters should allow an
    332 empty keyword dictionary to pass without a complaint, but raise a
    333 TypeError if te dictionary is not empty
    334 
    335     >>> try:
    336     ...     silence = id(1, *{})
    337     ...     True
    338     ... except:
    339     ...     False
    340     True
    341 
    342     >>> id(1, **{'foo': 1})
    343     Traceback (most recent call last):
    344       ...
    345     TypeError: id() takes no keyword arguments
    346 
    347 A corner case of keyword dictionary items being deleted during
    348 the function call setup. See <http://bugs.python.org/issue2016>.
    349 
    350     >>> class Name(str):
    351     ...     def __eq__(self, other):
    352     ...         try:
    353     ...              del x[self]
    354     ...         except KeyError:
    355     ...              pass
    356     ...         return str.__eq__(self, other)
    357     ...     def __hash__(self):
    358     ...         return str.__hash__(self)
    359 
    360     >>> x = {Name("a"):1, Name("b"):2}
    361     >>> def f(a, b):
    362     ...     print(a,b)
    363     >>> f(**x)
    364     1 2
    365 
    366 Too many arguments:
    367 
    368     >>> def f(): pass
    369     >>> f(1)
    370     Traceback (most recent call last):
    371       ...
    372     TypeError: f() takes 0 positional arguments but 1 was given
    373     >>> def f(a): pass
    374     >>> f(1, 2)
    375     Traceback (most recent call last):
    376       ...
    377     TypeError: f() takes 1 positional argument but 2 were given
    378     >>> def f(a, b=1): pass
    379     >>> f(1, 2, 3)
    380     Traceback (most recent call last):
    381       ...
    382     TypeError: f() takes from 1 to 2 positional arguments but 3 were given
    383     >>> def f(*, kw): pass
    384     >>> f(1, kw=3)
    385     Traceback (most recent call last):
    386       ...
    387     TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
    388     >>> def f(*, kw, b): pass
    389     >>> f(1, 2, 3, b=3, kw=3)
    390     Traceback (most recent call last):
    391       ...
    392     TypeError: f() takes 0 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given
    393     >>> def f(a, b=2, *, kw): pass
    394     >>> f(2, 3, 4, kw=4)
    395     Traceback (most recent call last):
    396       ...
    397     TypeError: f() takes from 1 to 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given
    398 
    399 Too few and missing arguments:
    400 
    401     >>> def f(a): pass
    402     >>> f()
    403     Traceback (most recent call last):
    404       ...
    405     TypeError: f() missing 1 required positional argument: 'a'
    406     >>> def f(a, b): pass
    407     >>> f()
    408     Traceback (most recent call last):
    409       ...
    410     TypeError: f() missing 2 required positional arguments: 'a' and 'b'
    411     >>> def f(a, b, c): pass
    412     >>> f()
    413     Traceback (most recent call last):
    414       ...
    415     TypeError: f() missing 3 required positional arguments: 'a', 'b', and 'c'
    416     >>> def f(a, b, c, d, e): pass
    417     >>> f()
    418     Traceback (most recent call last):
    419       ...
    420     TypeError: f() missing 5 required positional arguments: 'a', 'b', 'c', 'd', and 'e'
    421     >>> def f(a, b=4, c=5, d=5): pass
    422     >>> f(c=12, b=9)
    423     Traceback (most recent call last):
    424       ...
    425     TypeError: f() missing 1 required positional argument: 'a'
    426 
    427 Same with keyword only args:
    428 
    429     >>> def f(*, w): pass
    430     >>> f()
    431     Traceback (most recent call last):
    432       ...
    433     TypeError: f() missing 1 required keyword-only argument: 'w'
    434     >>> def f(*, a, b, c, d, e): pass
    435     >>> f()
    436     Traceback (most recent call last):
    437       ...
    438     TypeError: f() missing 5 required keyword-only arguments: 'a', 'b', 'c', 'd', and 'e'
    439 
    440 """
    441 
    442 import sys
    443 from test import support
    444 
    445 def test_main():
    446     support.run_doctest(sys.modules[__name__], True)
    447 
    448 if __name__ == '__main__':
    449     test_main()
    450