]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - contrib/fuse/impl_b/pyfuse/pairtype.py
bde2913f14e20a52d6083eb71dca07ea631b619e
[tahoe-lafs/tahoe-lafs.git] / contrib / fuse / impl_b / pyfuse / pairtype.py
1 """
2 Two magic tricks for classes:
3
4     class X:
5         __metaclass__ = extendabletype
6         ...
7
8     # in some other file...
9     class __extend__(X):
10         ...      # and here you can add new methods and class attributes to X
11
12 Mostly useful together with the second trick, which lets you build
13 methods whose 'self' is a pair of objects instead of just one:
14
15     class __extend__(pairtype(X, Y)):
16         attribute = 42
17         def method((x, y), other, arguments):
18             ...
19
20     pair(x, y).attribute
21     pair(x, y).method(other, arguments)
22
23 This finds methods and class attributes based on the actual
24 class of both objects that go into the pair(), with the usual
25 rules of method/attribute overriding in (pairs of) subclasses.
26
27 For more information, see test_pairtype.
28 """
29
30 class extendabletype(type):
31     """A type with a syntax trick: 'class __extend__(t)' actually extends
32     the definition of 't' instead of creating a new subclass."""
33     def __new__(cls, name, bases, dict):
34         if name == '__extend__':
35             for cls in bases:
36                 for key, value in dict.items():
37                     if key == '__module__':
38                         continue
39                     # XXX do we need to provide something more for pickling?
40                     setattr(cls, key, value)
41             return None
42         else:
43             return super(extendabletype, cls).__new__(cls, name, bases, dict)
44
45
46 def pair(a, b):
47     """Return a pair object."""
48     tp = pairtype(a.__class__, b.__class__)
49     return tp((a, b))   # tp is a subclass of tuple
50
51 pairtypecache = {}
52
53 def pairtype(cls1, cls2):
54     """type(pair(a,b)) is pairtype(a.__class__, b.__class__)."""
55     try:
56         pair = pairtypecache[cls1, cls2]
57     except KeyError:
58         name = 'pairtype(%s, %s)' % (cls1.__name__, cls2.__name__)
59         bases1 = [pairtype(base1, cls2) for base1 in cls1.__bases__]
60         bases2 = [pairtype(cls1, base2) for base2 in cls2.__bases__]
61         bases = tuple(bases1 + bases2) or (tuple,)  # 'tuple': ultimate base
62         pair = pairtypecache[cls1, cls2] = extendabletype(name, bases, {})
63     return pair