variadic

variadic is a Python (2.7+ and 3.4+) function decorator to write variadic functions accepting a mix of arguments and iterables of those arguments. Oh, and they keep their argspec, so tools doing introspection (Sphinx doc, IDEs, etc.) will work well. No ugly f(*args, **kwds) in your doc!

Note that PEP 448 makes variadic obsolete: if you’re using Python 3.5+, you should keep plain variadic functions and call them with several argument unpackings.

It’s licensed under the MIT license. It’s available on the Python package index. Its documentation and its source code are on GitHub.

Questions? Remarks? Bugs? Want to contribute? Open an issue!

https://img.shields.io/travis/jacquev6/variadic/master.svg https://img.shields.io/coveralls/jacquev6/variadic/master.svg https://img.shields.io/codeclimate/github/jacquev6/variadic.svg https://img.shields.io/scrutinizer/g/jacquev6/variadic.svg https://img.shields.io/pypi/dm/variadic.svg https://img.shields.io/pypi/l/variadic.svg https://img.shields.io/pypi/v/variadic.svg https://img.shields.io/pypi/pyversions/variadic.svg https://img.shields.io/pypi/status/variadic.svg https://img.shields.io/github/issues/jacquev6/variadic.svg https://img.shields.io/github/forks/jacquev6/variadic.svg https://img.shields.io/github/stars/jacquev6/variadic.svg

Quick start

Install from PyPI:

$ pip install variadic

Import:

>>> from variadic import variadic

Define a function:

>>> @variadic(int)
... def f(*args):
...   return args
>>> f(1, 2, [3, 4], xrange(5, 8))
(1, 2, 3, 4, 5, 6, 7)

User guide

Introduction

Define a variadic function:

>>> @variadic(int)
... def f(*xs):
...   return xs

It can be called with a variable number of arguments:

>>> f()
()
>>> f(1, 2, 3, 4)
(1, 2, 3, 4)

So far, no change, but it can also be called with lists (any iterable, in fact) of arguments:

>>> f([])
()
>>> f([1, 2, 3], (4, 5, 6))
(1, 2, 3, 4, 5, 6)
>>> f(xrange(1, 4))
(1, 2, 3)

And you can even mix them:

>>> f(1, [2, 3], (4, 5), xrange(6, 8))
(1, 2, 3, 4, 5, 6, 7)

Positional arguments, default values and keyword arguments are OK as well:

>>> @variadic(int)
... def f(a, b=None, *cs, **kwds):
...   return a, b, cs, kwds
>>> f(1)
(1, None, (), {})
>>> f(1, d=4)
(1, None, (), {'d': 4})
>>> f(1, 2, (3, 4), 5, d=6)
(1, 2, (3, 4, 5), {'d': 6})

Pearls

Documentation generated by Sphinx for decorated functions

It looks like a regular variadic function:

demo(a, b=None, *xs, **kwds)

Demo function.

Parameters:
  • a – A
  • b – B
  • xs – Xs
  • kwds – keywords

TypeError raised when calling with bad arguments

Exactly as if it was not decorated:

>>> @variadic(int)
... def f(*xs):
...   pass
>>> f(a=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'a'

Exception raised by the decorated function

@variadic adds just one stack frame with the same name as the decorated function:

>>> @variadic(int)
... def f(*xs):
...   raise Exception
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<ast_in_variadic_py>", line 1, in f
  File "<stdin>", line 3, in f
Exception

Reference

variadic(typ)

Decorator taking a variadic function and making a very-variadic function from it: a function that can be called with a variable number of iterables of arguments.

Parameters:typ – the type (or tuple of types) of arguments expected. Variadic arguments that are instances of this type will be passed to the decorated function as-is. Others will be iterated and their contents will be passed.