Get information about the arguments accepted by a code object. Three things are returned: (args, varargs, varkw), where 'args' is a list of argument names (possibly containing nested lists), and 'varargs' and 'varkw' are the names of the * and ** arguments or None.
(co)
| 239 | # https://github.com/ipython/ipython/issues/8205 and |
| 240 | # https://github.com/ipython/ipython/issues/8293 |
| 241 | def getargs(co): |
| 242 | """Get information about the arguments accepted by a code object. |
| 243 | |
| 244 | Three things are returned: (args, varargs, varkw), where 'args' is |
| 245 | a list of argument names (possibly containing nested lists), and |
| 246 | 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" |
| 247 | if not iscode(co): |
| 248 | raise TypeError('{!r} is not a code object'.format(co)) |
| 249 | |
| 250 | nargs = co.co_argcount |
| 251 | names = co.co_varnames |
| 252 | args = list(names[:nargs]) |
| 253 | step = 0 |
| 254 | |
| 255 | # The following acrobatics are for anonymous (tuple) arguments. |
| 256 | for i in range(nargs): |
| 257 | if args[i][:1] in ('', '.'): |
| 258 | stack, remain, count = [], [], [] |
| 259 | while step < len(co.co_code): |
| 260 | op = ord(co.co_code[step]) |
| 261 | step = step + 1 |
| 262 | if op >= dis.HAVE_ARGUMENT: |
| 263 | opname = dis.opname[op] |
| 264 | value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 |
| 265 | step = step + 2 |
| 266 | if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): |
| 267 | remain.append(value) |
| 268 | count.append(value) |
| 269 | elif opname in ('STORE_FAST', 'STORE_DEREF'): |
| 270 | if op in dis.haslocal: |
| 271 | stack.append(co.co_varnames[value]) |
| 272 | elif op in dis.hasfree: |
| 273 | stack.append((co.co_cellvars + co.co_freevars)[value]) |
| 274 | # Special case for sublists of length 1: def foo((bar)) |
| 275 | # doesn't generate the UNPACK_TUPLE bytecode, so if |
| 276 | # `remain` is empty here, we have such a sublist. |
| 277 | if not remain: |
| 278 | stack[0] = [stack[0]] |
| 279 | break |
| 280 | else: |
| 281 | remain[-1] = remain[-1] - 1 |
| 282 | while remain[-1] == 0: |
| 283 | remain.pop() |
| 284 | size = count.pop() |
| 285 | stack[-size:] = [stack[-size:]] |
| 286 | if not remain: |
| 287 | break |
| 288 | remain[-1] = remain[-1] - 1 |
| 289 | if not remain: |
| 290 | break |
| 291 | args[i] = stack[0] |
| 292 | |
| 293 | varargs = None |
| 294 | if co.co_flags & inspect.CO_VARARGS: |
| 295 | varargs = co.co_varnames[nargs] |
| 296 | nargs = nargs + 1 |
| 297 | varkw = None |
| 298 | if co.co_flags & inspect.CO_VARKEYWORDS: |