Last active
August 29, 2015 14:28
-
-
Save solidsnack/76ce7f4ae91e589774cc to your computer and use it in GitHub Desktop.
Namedtuple annotation for Python -- derive namedtuple definition from the signature of __init__()!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """Namedtuple annotation. | |
| Creates a namedtuple out of a class, based on the signature of that class's | |
| __init__ function. Defaults are respected. After namedtuple's initializer is | |
| run, the original __init__ is run as well, allowing one to assign synthetic | |
| parameters and internal book-keeping variables. (Note that the original | |
| __init__ may not assign to the variables in its signature, because these | |
| variables are made immutable by namedtuple). | |
| The class must not have varargs or keyword args. | |
| Thanks to @mjpieters: http://stackoverflow.com/a/32171046/48251 | |
| """ | |
| import collections | |
| import inspect | |
| def namedtuple(cls): | |
| argspec = inspect.getargspec(cls.__init__) | |
| assert argspec.varargs is None | |
| assert argspec.keywords is None | |
| non_self_args = argspec.args[1:] | |
| # Now we can create the new class definition, based on a namedtuple. | |
| bases = (collections.namedtuple(cls.__name__, non_self_args), cls) | |
| namespace = {'__doc__': cls.__doc__} | |
| newcls = type(cls.__name__, bases, namespace) | |
| # Here we set up the new class's __new__, which hands off to namedtuple's | |
| # after setting defaults. | |
| @staticmethod | |
| def new(*args, **kwargs): | |
| kls = args[0] | |
| # Resolve default assignments with this utility from inspect. | |
| values = inspect.getcallargs(cls.__init__, None, *args[1:], **kwargs) | |
| values = [values[_] for _ in non_self_args] | |
| obj = super(newcls, kls).__new__(kls, *values) | |
| cls.__init__(obj, *values) # Allow initialization to occur | |
| return obj | |
| newcls.__new__ = new | |
| return newcls |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment