Source code for qarbon.util

# ----------------------------------------------------------------------------
# This file is part of qarbon (http://qarbon.rtfd.org/)
#
# Copyright (c) 2013 European Synchrotron Radiation Facility, Grenoble, France
#
# Distributed under the terms of the GNU Lesser General Public License,
# either version 3 of the License, or (at your option) any later version.
# See LICENSE.txt for more info.
# ----------------------------------------------------------------------------

"""Helper functions."""

__all__ = ['is_string', 'is_sequence', 'module_directory',
           'import_module', 'callable_weakref']

import os
import sys
import inspect
import weakref
import collections


__str_klasses = [str]
__seq_klasses = [collections.Sequence, bytearray]

# some versions of python don't have unicode (python [3.0, 3.3])
try:
    unicode
    __str_klasses.append(unicode)
except:
    pass

# some versions of python don't have basestring (python [3.0, inf[)
try:
    basestring
    __str_klasses.insert(0, basestring)
except:
    pass

__str_klasses = tuple(__str_klasses)
__seq_klasses = tuple(__seq_klasses)


[docs]def is_string(obj): """Determines if the given object is a string. :param obj: the object to be analysed :type obj: object :return: True if the given object is a string or False otherwise :rtype: bool""" return isinstance(obj, __str_klasses)
[docs]def is_sequence(obj, inc_string=False): """Determines if the given object is a sequence. :param obj: the object to be analysed :type obj: object :param inc_string: if False, exclude str/unicode objects from the list of possible sequence objects :type inc_string: bool :return: True if the given object is a sequence or False otherwise :rtype: bool""" if inc_string: return isinstance(obj, __seq_klasses) else: return isinstance(obj, __seq_klasses) and not is_string(obj)
def __import_module(name): """Import module, returning the module after the last dot. :param name: name of the module to be imported :type name: str :return: the imported module :rtype: module""" __import__(name) return sys.modules[name]
[docs]def module_directory(module): """Returns the location of a given module. :param module: the module object :type module: module :return: the directory where the module is located :rtype: str""" return os.path.dirname(os.path.abspath(module.__file__))
def __resolve_name(name, package, level): """Return the absolute name of the module to be imported.""" if not hasattr(package, 'rindex'): raise ValueError("'package' not set to a string") dot = len(package) for x in xrange(level, 1, -1): try: dot = package.rindex('.', 0, dot) except ValueError: raise ValueError("attempted relative import beyond top-level " "package") return "%s.%s" % (package[:dot], name)
[docs]def import_module(name, package=None): """Import a module. The 'package' argument is required when performing a relative import. It specifies the package to use as the anchor point from which to resolve the relative import to an absolute import. """ if name.startswith('.'): if not package: raise TypeError("relative imports require the 'package' argument") level = 0 for character in name: if character != '.': break level += 1 name = __resolve_name(name[level:], package, level) return __import_module(name)
class _MethodWeakref(object): """This class represents a weak reference to a method of an object since weak references to methods don't work by themselves""" def __init__(self, method, del_cb=None): cb = del_cb and self.__on_deleted self.__func = weakref.ref(method.im_func, cb) self.__obj = weakref.ref(method.im_self, cb) if cb: self.__del_cb = callable_weakref(del_cb) self.__deleted = 0 def __on_deleted(self, obj): if not self.__deleted: del_cb = self.__del_cb() if del_cb is not None: del_cb(self) self.__deleted = 1 def __call__(self): obj = self.__obj() if obj is not None: func = self.__func() if func is not None: return func.__get__(obj) def __hash__(self): return id(self) def __cmp__(self, other): if other.__class__ == self.__class__: ret = cmp((self.__func, self.__obj), (other.__func, other.__obj)) return ret return 1 def __repr__(self): return '_MethodWeakRef()' #obj, f_name = self.__obj(), self.__func().__name__ #return '_MethodWeakRef(obj={0}, func={1})'.format % (obj, f_name)
[docs]def callable_weakref(obj, del_cb=None): """This function returns a callable weak reference to a callable object. Object can be a callable object, a function or a method. :param object: a callable object :type object: callable object :param del_cb: calback function. Default is None meaning to callback. :type del_cb: callable object or None :return: a weak reference for the given callable :rtype: BoundMethodWeakref or weakref.ref""" if inspect.ismethod(obj): return _MethodWeakref(obj, del_cb) return weakref.ref(obj, del_cb)