Commit 993f2f72 authored by Jeroen Demeyer's avatar Jeroen Demeyer Committed by Stefan Behnel

Test that *args tuple is not copied if possible (GH-3086)

parent 1e7550c7
__doc__ = u""" cdef sorteditems(d):
return tuple(sorted(d.items()))
cdef class Silly:
def __init__(self, *a):
"""
>>> s = Silly(1,2,3, 'test') >>> s = Silly(1,2,3, 'test')
>>> (spam,grail,swallow,creosote,onlyt,onlyk,tk) = ( """
... s.spam,s.grail,s.swallow,s.creosote,s.onlyt,s.onlyk,s.tk)
>>> spam(1,2,3) def spam(self, x, y, z):
"""
>>> s = Silly()
>>> s.spam(1,2,3)
(1, 2, 3) (1, 2, 3)
>>> spam(1,2) >>> s.spam(1,2)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: spam() takes exactly 3 positional arguments (2 given) TypeError: spam() takes exactly 3 positional arguments (2 given)
>>> spam(1,2,3,4) >>> s.spam(1,2,3,4)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: spam() takes exactly 3 positional arguments (4 given) TypeError: spam() takes exactly 3 positional arguments (4 given)
>>> spam(1,2,3, a=1) #doctest: +ELLIPSIS >>> s.spam(1,2,3, a=1)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: spam() got an unexpected keyword argument 'a' TypeError: spam() got an unexpected keyword argument 'a'
"""
return (x, y, z)
>>> grail(1,2,3) def grail(self, x, y, z, *a):
"""
>>> s = Silly()
>>> s.grail(1,2,3)
(1, 2, 3, ()) (1, 2, 3, ())
>>> grail(1,2,3,4) >>> s.grail(1,2,3,4)
(1, 2, 3, (4,)) (1, 2, 3, (4,))
>>> grail(1,2,3,4,5,6,7,8,9) >>> s.grail(1,2,3,4,5,6,7,8,9)
(1, 2, 3, (4, 5, 6, 7, 8, 9)) (1, 2, 3, (4, 5, 6, 7, 8, 9))
>>> grail(1,2) >>> s.grail(1,2)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: grail() takes at least 3 positional arguments (2 given) TypeError: grail() takes at least 3 positional arguments (2 given)
>>> grail(1,2,3, a=1) #doctest: +ELLIPSIS >>> s.grail(1,2,3, a=1)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: grail() got an unexpected keyword argument 'a' TypeError: grail() got an unexpected keyword argument 'a'
"""
return (x, y, z, a)
>>> swallow(1,2,3) def swallow(self, x, y, z, **k):
"""
>>> s = Silly()
>>> s.swallow(1,2,3)
(1, 2, 3, ()) (1, 2, 3, ())
>>> swallow(1,2,3,4) >>> s.swallow(1,2,3,4)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: swallow() takes exactly 3 positional arguments (4 given) TypeError: swallow() takes exactly 3 positional arguments (4 given)
>>> swallow(1,2,3, a=1, b=2) >>> s.swallow(1,2,3, a=1, b=2)
(1, 2, 3, (('a', 1), ('b', 2))) (1, 2, 3, (('a', 1), ('b', 2)))
>>> swallow(1,2,3, x=1) >>> s.swallow(1,2,3, x=1)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: swallow() got multiple values for keyword argument 'x' TypeError: swallow() got multiple values for keyword argument 'x'
"""
return (x, y, z, sorteditems(k))
>>> creosote(1,2,3) def creosote(self, x, y, z, *a, **k):
"""
>>> s = Silly()
>>> s.creosote(1,2,3)
(1, 2, 3, (), ()) (1, 2, 3, (), ())
>>> creosote(1,2,3,4) >>> s.creosote(1,2,3,4)
(1, 2, 3, (4,), ()) (1, 2, 3, (4,), ())
>>> creosote(1,2,3, a=1) >>> s.creosote(1,2,3, a=1)
(1, 2, 3, (), (('a', 1),)) (1, 2, 3, (), (('a', 1),))
>>> creosote(1,2,3,4, a=1, b=2) >>> s.creosote(1,2,3,4, a=1, b=2)
(1, 2, 3, (4,), (('a', 1), ('b', 2))) (1, 2, 3, (4,), (('a', 1), ('b', 2)))
>>> creosote(1,2,3,4, x=1) >>> s.creosote(1,2,3,4, x=1)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: creosote() got multiple values for keyword argument 'x' TypeError: creosote() got multiple values for keyword argument 'x'
"""
return (x, y, z, a, sorteditems(k))
>>> onlyt(1) def onlyt(self, *a):
"""
>>> s = Silly()
>>> s.onlyt(1)
(1,) (1,)
>>> onlyt(1,2) >>> s.onlyt(1,2)
(1, 2) (1, 2)
>>> onlyt(a=1) >>> s.onlyt(a=1)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: onlyt() got an unexpected keyword argument 'a' TypeError: onlyt() got an unexpected keyword argument 'a'
>>> onlyt(1, a=2) >>> s.onlyt(1, a=2)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: onlyt() got an unexpected keyword argument 'a' TypeError: onlyt() got an unexpected keyword argument 'a'
>>> test_no_copy_args(s.onlyt)
True
"""
return a
>>> onlyk(a=1) def onlyk(self, **k):
"""
>>> s = Silly()
>>> s.onlyk(a=1)
(('a', 1),) (('a', 1),)
>>> onlyk(a=1, b=2) >>> s.onlyk(a=1, b=2)
(('a', 1), ('b', 2)) (('a', 1), ('b', 2))
>>> onlyk(1) >>> s.onlyk(1)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: onlyk() takes exactly 0 positional arguments (1 given) TypeError: onlyk() takes exactly 0 positional arguments (1 given)
>>> onlyk(1, 2) >>> s.onlyk(1, 2)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: onlyk() takes exactly 0 positional arguments (2 given) TypeError: onlyk() takes exactly 0 positional arguments (2 given)
>>> onlyk(1, a=1, b=2) >>> s.onlyk(1, a=1, b=2)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: onlyk() takes exactly 0 positional arguments (1 given) TypeError: onlyk() takes exactly 0 positional arguments (1 given)
"""
return sorteditems(k)
>>> tk(a=1) def tk(self, *a, **k):
"""
>>> s = Silly()
>>> s.tk(a=1)
(('a', 1),) (('a', 1),)
>>> tk(a=1, b=2) >>> s.tk(a=1, b=2)
(('a', 1), ('b', 2)) (('a', 1), ('b', 2))
>>> tk(1) >>> s.tk(1)
(1,) (1,)
>>> tk(1, 2) >>> s.tk(1, 2)
(1, 2) (1, 2)
>>> tk(1, a=1, b=2) >>> s.tk(1, a=1, b=2)
(1, ('a', 1), ('b', 2)) (1, ('a', 1), ('b', 2))
""" """
return a + sorteditems(k)
cdef sorteditems(d):
l = list(d.items())
l.sort()
return tuple(l)
cdef class Silly:
def __init__(self, *a):
pass
def spam(self, x, y, z):
return (x, y, z)
def grail(self, x, y, z, *a):
return (x, y, z, a)
def swallow(self, x, y, z, **k):
return (x, y, z, sorteditems(k))
def creosote(self, x, y, z, *a, **k):
return (x, y, z, a, sorteditems(k))
def onlyt(self, *a): def t_kwonly(self, *a, k):
"""
>>> s = Silly()
>>> test_no_copy_args(s.t_kwonly, k=None)
True
"""
return a return a
def onlyk(self, **k):
return sorteditems(k)
def tk(self, *a, **k): def test_no_copy_args(func, **kw):
return a + sorteditems(k) """
func is a function such that func(*args, **kw) returns args.
We test that no copy is made of the args tuple.
This tests both the caller side and the callee side.
"""
args = (1, 2, 3)
return func(*args, **kw) is args
cdef sorteditems(d): cdef sorteditems(d):
l = list(d.items()) return tuple(sorted(d.items()))
l.sort()
return tuple(l)
def spam(x, y, z): def spam(x, y, z):
""" """
...@@ -79,6 +78,8 @@ def onlyt(*a): ...@@ -79,6 +78,8 @@ def onlyt(*a):
>>> onlyt(1, a=2) >>> onlyt(1, a=2)
Traceback (most recent call last): Traceback (most recent call last):
TypeError: onlyt() got an unexpected keyword argument 'a' TypeError: onlyt() got an unexpected keyword argument 'a'
>>> test_no_copy_args(onlyt)
True
""" """
return a return a
...@@ -114,3 +115,20 @@ def tk(*a, **k): ...@@ -114,3 +115,20 @@ def tk(*a, **k):
(1, ('a', 1), ('b', 2)) (1, ('a', 1), ('b', 2))
""" """
return a + sorteditems(k) return a + sorteditems(k)
def t_kwonly(*a, k):
"""
>>> test_no_copy_args(t_kwonly, k=None)
True
"""
return a
def test_no_copy_args(func, **kw):
"""
func is a function such that func(*args, **kw) returns args.
We test that no copy is made of the args tuple.
This tests both the caller side and the callee side.
"""
args = (1, 2, 3)
return func(*args, **kw) is args
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment