File: weakutil.py

package info (click to toggle)
python-pyutil 3.3.2-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 884 kB
  • sloc: python: 7,198; makefile: 6
file content (47 lines) | stat: -rw-r--r-- 1,431 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# -*- coding: utf-8; fill-column: 77 -*-
# -*- indent-tabs-mode: nil -*-

#  This file is part of pyutil; see README.rst for licensing terms.

import warnings

# from the Python Standard Library
from weakref import ref
import types

# from the pyutil library
from .assertutil import precondition

def is_bound_method(fn):
    if hasattr(types, 'UnboundMethodType'): # PY2
        return hasattr(fn, 'im_self')
    else: # PY3
        return isinstance(fn, types.MethodType)

class WeakMethod:
    """ Wraps a function or, more importantly, a bound method, in
    a way that allows a bound method's object to be GC'd """
    def __init__(self, fn, callback=None):
        warnings.warn("deprecated", DeprecationWarning)
        precondition(is_bound_method(fn), "fn is required to be a bound method.")
        self._cleanupcallback = callback
        self._obj = ref(fn.__self__, self.call_cleanup_cb)
        self._meth = fn.__func__

    def __call__(self, *args, **kws):
        s = self._obj()
        if s:
            return self._meth(s, *args,**kws)

    def __repr__(self):
        return "<%s %s %s>" % (self.__class__.__name__, self._obj, self._meth,)

    def call_cleanup_cb(self, thedeadweakref):
        if self._cleanupcallback is not None:
            self._cleanupcallback(self, thedeadweakref)

def factory_function_name_here(o):
    if is_bound_method(o):
        return WeakMethod(o)
    else:
        return o