~ubuntu-branches/ubuntu/saucy/coherence/saucy

« back to all changes in this revision

Viewing changes to coherence/extern/louie/saferef.py

  • Committer: Bazaar Package Importer
  • Author(s): Charlie Smotherman
  • Date: 2010-01-02 10:57:15 UTC
  • mfrom: (1.1.7 upstream) (3.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20100102105715-sghzl2nw4lr5b1ob
Tags: 0.6.6.2-1
*  New  upstream release, summary of changes:
    - adding all necessary files to MANIFEST.in, to compensate for the
      gone 'auto-include-all-files-under-version-control' setuptools
      feature.
    - rearranging genre and genres attribute in DIDLLite - thx Caleb  
    - fix face_path typo, fixes #275.   

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""Refactored 'safe reference from dispatcher.py"""
2
 
 
3
 
import weakref
4
 
import traceback
5
 
 
6
 
 
7
 
def safe_ref(target, on_delete=None):
8
 
    """Return a *safe* weak reference to a callable target.
9
 
 
10
 
    - ``target``: The object to be weakly referenced, if it's a bound
11
 
      method reference, will create a BoundMethodWeakref, otherwise
12
 
      creates a simple weakref.
13
 
        
14
 
    - ``on_delete``: If provided, will have a hard reference stored to
15
 
      the callable to be called after the safe reference goes out of
16
 
      scope with the reference object, (either a weakref or a
17
 
      BoundMethodWeakref) as argument.
18
 
    """
19
 
    if hasattr(target, 'im_self'):
20
 
        if target.im_self is not None:
21
 
            # Turn a bound method into a BoundMethodWeakref instance.
22
 
            # Keep track of these instances for lookup by disconnect().
23
 
            assert hasattr(target, 'im_func'), (
24
 
                "safe_ref target %r has im_self, but no im_func, "
25
 
                "don't know how to create reference"
26
 
                % target
27
 
                )
28
 
            reference = BoundMethodWeakref(target=target, on_delete=on_delete)
29
 
            return reference
30
 
    if callable(on_delete):
31
 
        return weakref.ref(target, on_delete)
32
 
    else:
33
 
        return weakref.ref(target)
34
 
    
35
 
 
36
 
class BoundMethodWeakref(object):
37
 
    """'Safe' and reusable weak references to instance methods.
38
 
 
39
 
    BoundMethodWeakref objects provide a mechanism for referencing a
40
 
    bound method without requiring that the method object itself
41
 
    (which is normally a transient object) is kept alive.  Instead,
42
 
    the BoundMethodWeakref object keeps weak references to both the
43
 
    object and the function which together define the instance method.
44
 
 
45
 
    Attributes:
46
 
    
47
 
    - ``key``: The identity key for the reference, calculated by the
48
 
      class's calculate_key method applied to the target instance method.
49
 
 
50
 
    - ``deletion_methods``: Sequence of callable objects taking single
51
 
      argument, a reference to this object which will be called when
52
 
      *either* the target object or target function is garbage
53
 
      collected (i.e. when this object becomes invalid).  These are
54
 
      specified as the on_delete parameters of safe_ref calls.
55
 
 
56
 
    - ``weak_self``: Weak reference to the target object.
57
 
 
58
 
    - ``weak_func``: Weak reference to the target function.
59
 
 
60
 
    Class Attributes:
61
 
        
62
 
    - ``_all_instances``: Class attribute pointing to all live
63
 
      BoundMethodWeakref objects indexed by the class's
64
 
      calculate_key(target) method applied to the target objects.
65
 
      This weak value dictionary is used to short-circuit creation so
66
 
      that multiple references to the same (object, function) pair
67
 
      produce the same BoundMethodWeakref instance.
68
 
    """
69
 
    
70
 
    _all_instances = weakref.WeakValueDictionary()
71
 
    
72
 
    def __new__(cls, target, on_delete=None, *arguments, **named):
73
 
        """Create new instance or return current instance.
74
 
 
75
 
        Basically this method of construction allows us to
76
 
        short-circuit creation of references to already- referenced
77
 
        instance methods.  The key corresponding to the target is
78
 
        calculated, and if there is already an existing reference,
79
 
        that is returned, with its deletion_methods attribute updated.
80
 
        Otherwise the new instance is created and registered in the
81
 
        table of already-referenced methods.
82
 
        """
83
 
        key = cls.calculate_key(target)
84
 
        current = cls._all_instances.get(key)
85
 
        if current is not None:
86
 
            current.deletion_methods.append(on_delete)
87
 
            return current
88
 
        else:
89
 
            base = super(BoundMethodWeakref, cls).__new__(cls)
90
 
            cls._all_instances[key] = base
91
 
            base.__init__(target, on_delete, *arguments, **named)
92
 
            return base
93
 
 
94
 
    def __init__(self, target, on_delete=None):
95
 
        """Return a weak-reference-like instance for a bound method.
96
 
 
97
 
        - ``target``: The instance-method target for the weak reference,
98
 
          must have im_self and im_func attributes and be
99
 
          reconstructable via the following, which is true of built-in
100
 
          instance methods::
101
 
            
102
 
            target.im_func.__get__( target.im_self )
103
 
 
104
 
        - ``on_delete``: Optional callback which will be called when
105
 
          this weak reference ceases to be valid (i.e. either the
106
 
          object or the function is garbage collected).  Should take a
107
 
          single argument, which will be passed a pointer to this
108
 
          object.
109
 
        """
110
 
        def remove(weak, self=self):
111
 
            """Set self.isDead to True when method or instance is destroyed."""
112
 
            methods = self.deletion_methods[:]
113
 
            del self.deletion_methods[:]
114
 
            try:
115
 
                del self.__class__._all_instances[self.key]
116
 
            except KeyError:
117
 
                pass
118
 
            for function in methods:
119
 
                try:
120
 
                    if callable(function):
121
 
                        function(self)
122
 
                except Exception:
123
 
                    try:
124
 
                        traceback.print_exc()
125
 
                    except AttributeError, e:
126
 
                        print ('Exception during saferef %s '
127
 
                               'cleanup function %s: %s' % (self, function, e))
128
 
        self.deletion_methods = [on_delete]
129
 
        self.key = self.calculate_key(target)
130
 
        self.weak_self = weakref.ref(target.im_self, remove)
131
 
        self.weak_func = weakref.ref(target.im_func, remove)
132
 
        self.self_name = str(target.im_self)
133
 
        self.func_name = str(target.im_func.__name__)
134
 
        
135
 
    def calculate_key(cls, target):
136
 
        """Calculate the reference key for this reference.
137
 
 
138
 
        Currently this is a two-tuple of the id()'s of the target
139
 
        object and the target function respectively.
140
 
        """
141
 
        return (id(target.im_self), id(target.im_func))
142
 
    calculate_key = classmethod(calculate_key)
143
 
    
144
 
    def __str__(self):
145
 
        """Give a friendly representation of the object."""
146
 
        return "%s(%s.%s)" % (
147
 
            self.__class__.__name__,
148
 
            self.self_name,
149
 
            self.func_name,
150
 
            )
151
 
    
152
 
    __repr__ = __str__
153
 
    
154
 
    def __nonzero__(self):
155
 
        """Whether we are still a valid reference."""
156
 
        return self() is not None
157
 
 
158
 
    def __cmp__(self, other):
159
 
        """Compare with another reference."""
160
 
        if not isinstance(other, self.__class__):
161
 
            return cmp(self.__class__, type(other))
162
 
        return cmp(self.key, other.key)
163
 
 
164
 
    def __call__(self):
165
 
        """Return a strong reference to the bound method.
166
 
 
167
 
        If the target cannot be retrieved, then will return None,
168
 
        otherwise returns a bound instance method for our object and
169
 
        function.
170
 
 
171
 
        Note: You may call this method any number of times, as it does
172
 
        not invalidate the reference.
173
 
        """
174
 
        target = self.weak_self()
175
 
        if target is not None:
176
 
            function = self.weak_func()
177
 
            if function is not None:
178
 
                return function.__get__(target)
179
 
        return None