В peewee скорее всего реализовано так:
class Entry(object):
def select(self):
print('do select')
return self
def join(self):
print('do join')
return self
def where(self):
print('do where')
return self
def order_by(self):
print('do order_by')
return self
>>> entry = Entry()
>>> entry.select().join().where().order_by()
do select
do join
do where
do order_by
<Entry object at ...>
Если использовать только как затычку, то можно извратиться так:
class A(object):
def __init__(self):
self.stack = []
def __getattr__(self, name):
def wrap(*args, **kwargs):
self.stack.append('name: {} args: {} kwargs: {}'
.format(name, args, kwargs))
return self
return wrap
def __repr__(self):
for call in self.stack:
print(call)
self.stack = []
return super().__repr__()
>>> a = A()
>>> a.foo(123, func='321')
name: foo args: (123,) kwargs: {'func': '321'}
<A object at ...>
>>> a.foo(123, func='321').bar(111).baz('string')
name: foo args: (123,) kwargs: {'func': '321'}
name: bar args: (111,) kwargs: {}
name: bazz args: ('string',) kwargs: {}
<A object at ...>