Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/14492.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed ``Code.getargs()`` incorrectly including local variable names in the returned argument tuple for functions with ``*args`` and/or ``**kwargs``. The method was using ``co_flags`` bitmask values (``4`` and ``8``) directly as counts instead of converting them to ``1`` via ``bool()``.
5 changes: 3 additions & 2 deletions src/_pytest/_code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ def getargs(self, var: bool = False) -> tuple[str, ...]:
raw = self.raw
argcount = raw.co_argcount
if var:
argcount += raw.co_flags & CO_VARARGS
argcount += raw.co_flags & CO_VARKEYWORDS
argcount += raw.co_kwonlyargcount
argcount += bool(raw.co_flags & CO_VARARGS)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fear this may get confused by mixing in kwonly args

argcount += bool(raw.co_flags & CO_VARKEYWORDS)
return raw.co_varnames[:argcount]


Expand Down
14 changes: 14 additions & 0 deletions testing/code/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ def f4(x, *y, **z):
c4 = Code.from_function(f4)
assert c4.getargs(var=True) == ("x", "y", "z")

def f5(x, *y, **z):
a1 = a2 = a3 = a4 = a5 = a6 = 1 # noqa: F841

c5 = Code.from_function(f5)
f5(1, 2, 3, z=4) # cover function body
assert c5.getargs(var=True) == ("x", "y", "z")

def f6(x, *y, kw=1, **z):
a1 = a2 = a3 = a4 = a5 = a6 = 1 # noqa: F841

c6 = Code.from_function(f6)
f6(1, 2, kw=3, z=4) # cover function body
assert c6.getargs(var=True) == ("x", "kw", "y", "z")


def test_frame_getargs() -> None:
def f1(x) -> FrameType:
Expand Down
Loading