Last active
August 29, 2015 14:18
-
-
Save karanlyons/a53eaa7a26f1bddbae83 to your computer and use it in GitHub Desktop.
PartialObject (as functools.partial is to functions)
This file contains 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
#!/usr/bin/env python2.7 | |
# -*- coding: utf-8 -*- | |
from __future__ import division, absolute_import, print_function, unicode_literals | |
import inspect | |
from collections import OrderedDict | |
class PartialManager(type): | |
def __call__(cls, *args, **kwargs): | |
signature = inspect.getargspec(cls.__init__) | |
arg_names = signature.args[1:] | |
if signature.defaults: | |
arg_names = arg_names[:-len(signature.defaults)] | |
if (len(args) + sum(arg in kwargs for arg in arg_names)) >= len(arg_names): | |
return super(PartialManager, cls).__call__(*args, **kwargs) | |
else: | |
return getattr(cls, '__partialclass__', PartialObject)(cls, *args, **kwargs) | |
class PartialObject(object): | |
def __init__(self, cls, *args, **kwargs): | |
self.cls = cls | |
self.args = args | |
self.kwargs = kwargs | |
self.args, self.kwargs = self.modify(self.args, self.kwargs) | |
signature = inspect.getargspec(self.cls.__init__) | |
self.arg_names = signature.args[1:] | |
if signature.defaults: | |
self.arg_names = self.arg_names[:-len(signature.defaults)] | |
self.default_kwargs = OrderedDict(zip(signature.args[-len(signature.defaults):], signature.defaults)) | |
else: | |
self.default_kwargs = OrderedDict() | |
def __call__(self, *args, **kwargs): | |
new_args = self.args + args | |
new_kwargs = self.kwargs.copy() | |
new_kwargs.update(kwargs) | |
new_args, new_kwargs = self.modify(new_args, new_kwargs) | |
return self.cls(*new_args, **new_kwargs) | |
def modify(self, args, kwargs): | |
return (args, kwargs) | |
def __unicode__(self): | |
applied = list(self.arg_names)[:len(self.args)] | |
kwargs = self.kwargs.copy() | |
for arg_name in self.arg_names: | |
if arg_name in kwargs: | |
del(kwargs[arg_name]) | |
applied.append(arg_name) | |
for kwarg, default in self.default_kwargs.iteritems(): | |
if kwarg in kwargs: | |
if kwargs[kwarg] != default: | |
applied.append(kwarg) | |
del(kwargs[kwarg]) | |
applied.extend(kwargs.iterkeys()) | |
return 'Partial %s (Applied: %s)' % (self.cls.__name__, ', '.join(applied) if applied else None) | |
def __str__(self): | |
return unicode(self).encode('utf-8') | |
def __repr__(self): | |
args = self.args[:] | |
kwargs = self.kwargs.copy() | |
args += tuple((kwargs.pop(arg_name) for arg_name in self.arg_names if arg_name in kwargs)) | |
args = ( | |
['%s' % repr(arg) for arg in args] + | |
['%s=%s' % (kwarg, repr(kwargs[kwarg])) for kwarg, default in self.default_kwargs.iteritems() if kwarg in kwargs and kwargs[kwarg] != default] + | |
['%s=%s' % (kwarg, repr(value)) for kwarg, value in kwargs.iteritems() if kwarg not in self.default_kwargs] | |
) | |
return '%s(%s%s)' % (self.__class__.__name__, self.cls.__name__, ', %s' % ', '.join(args) if args else '') |
This file contains 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
#!/usr/bin/env python2.7 | |
# -*- coding: utf-8 -*- | |
from __future__ import division, absolute_import, print_function, unicode_literals | |
from partial_object import PartialManager, PartialObject | |
class PartialTest(PartialObject): | |
def modify(self, args, kwargs): | |
''' | |
Allows supplying arguments out of order. | |
''' | |
if args and isinstance(args[0], int) and 'count' not in kwargs: | |
args = list(args) | |
kwargs['count'] = args.pop(0) | |
args = tuple(args) | |
return (args, kwargs) | |
class Test(object): | |
__metaclass__ = PartialManager | |
__partialclass__ = PartialTest | |
def __init__(self, name, count): | |
for i in xrange(count): | |
print(name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment