Skip to content

Instantly share code, notes, and snippets.

@jepio
Created September 10, 2015 13:20
Show Gist options
  • Save jepio/89f1d8db9e3745721f4f to your computer and use it in GitHub Desktop.
Save jepio/89f1d8db9e3745721f4f to your computer and use it in GitHub Desktop.
chain method calls in python
class chain:
"""
A class that allows the chaining of function/method calls on objects
and modules.
To use create chain an object and then go crazy calling methods one
after the other.
>>> import curses
>>> _ = chain(curses).initscr().noecho().cbreak().nocbreak().echo()\
.endwin()
"""
def __init__(self, obj):
"""
Create a chain on `obj` object. All subsequent method calls will
be executed on this object.
"""
self.obj = obj
self.next_fun = obj
self.last_return = None
def __getattr__(self, name):
def _wrapper(*args):
self.last_return = getattr(self.obj, name)(*args)
return self
return _wrapper
def call_next(self, fun):
"""
Queue function to be called next instead of looking it up inside
self.obj.
This allows to execute a function within the chain without
interrupting it.
>>> _ = chain(open('/dev/urandom', 'rb')).call_next(print)("woohooo!")\
.close()
woohooo!
"""
self.next_fun = fun
return self
def __call__(self, *args):
self.next_fun(*args)
if self.next_fun is not self.obj:
self.next_fun = None
return self
def then(self, fun):
"""
Execute a function using the last returned value.
This only executes properly with 1 argument functions. The chain
is not interrupted.
>>> _ = chain(open('/dev/urandom', 'rb')).read(5).then(type)\
.then(print).close()
<class 'bytes'>
"""
self.last_return = fun(self.last_return)
return self
if __name__ == "__main__":
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment