Trash: Cookbook Adding support for ipipe - ShuaiYAN/ipython GitHub Wiki
You can add support for ipipe to your own classes too. Anything that is
iterable can be displayed by piping it into an ipipe enabled object, but
if you want an ipipe display to automatically display your object, you have
to subclass ipipe.Table
and implement an __iter__
method. For example an
ipipe enabled version of range might look like this:
class irange(ipipe.Table): def __init__(self, *args): self.args = args def __iter__(self): return iter(xrange(*self.args))
If you want to implement a "filter" (i.e. something that transforms an input
pipe), you have to subclass ipipe.Pipe
. This gives you automatic handling
of the | operator. In your __iter__
method you can access the input pipe
as the input
attribute. For example the following pipe will skip every second
item:
class ieven(ipipe.Pipe): def __iter__(self): for (i, item) in enumerate(self.input): if not i % 2: yield item
Now you can user your new classes like this:
In [1:] irange(100) | ieven
You can specify which attributes should be displayed in an ipipe listing by implementing the __xattrs__
method:
def __xattrs__(self, mode="default"): return ("firstname", "lastname")
(If __xattrs__()
isn't defined the ipipe display will simply use the repr()
result for the object itself)
The `mode` attribute has two possible values:
- "default": The default list mode of the ibrowse display;
- "detail": The detail mode, where each attribute of an object is displayed as a separate row (activated by pressing the `d` key in `ibrowse`).
__xattrs__()
must return an iterable with "attribute descriptors". These attribute descriptors can be:
-
None
: this will display the object itself; - "foo": this will display the attribute named "foo";
- "foo()": this will call the method foo and will display the return value;
- "-foo": The attribute named "foo" must be iterable. It's value will not be displayed, but it can be entered;
- "-foo()": The foo method must return an iterable. The return value will not be displayed, but it can be entered;
- Instances of the `ipipe.Descriptor` class.
ipipe.Descriptor
implementing the specific behaviour: SelfDescriptor()
is the same as None
, AttributeDescriptor("foo")
the same as "foo", IterAttributeDescriptor("foo")
the same as "-foo", MethodDescriptor("foo")
the same as "foo()" and IterMethodDescriptor("foo")
the same as "-foo()". Finally there's FunctionDescriptor(foo)
, where foo must be callable (with the object as an argument) that returns the attribute value.
For example we can add contact information to the above Person
class:
def addcontact(self, type, value): self.contacts.append(Contact(type, value)) def __xattrs__(self, mode="default"): if mode == "detail": return ("firstname", "lastname", "-contacts") else: return ("firstname", "lastname") class Contact: def __init__(self, type, value): self.type = type self.value = value def __xattrs__(self, mode="default"): return ("type", "value") p1 = Person("John", "Doe") p1.addcontact("email", "[email protected]") p1.addcontact("phone", "555-0123") p2 = Person("Jane", "Doe") p2.addcontact("email", "[email protected]") p2.addcontact("phone", "555-0321") persons = [p1, p2]
With these objects you can then browse them like this:
In [1]: persons | ibrowse