HEX
Server: Apache
System: Linux sg241.singhost.net 2.6.32-896.16.1.lve1.4.51.el6.x86_64 #1 SMP Wed Jan 17 13:19:23 EST 2018 x86_64
User: honghock (909)
PHP: 8.0.30
Disabled: passthru,system,shell_exec,show_source,exec,popen,proc_open
Upload Files
File: //usr/lib/python2.6/site-packages/nose/util.py
"""Utility functions and classes used by nose internally.
"""
import inspect
import itertools
import logging
import os
import re
import sys
import types
import unittest
from compiler.consts import CO_GENERATOR
from types import ClassType, TypeType

log = logging.getLogger('nose')

ident_re = re.compile(r'^[A-Za-z_][A-Za-z0-9_.]*$')
class_types = (ClassType, TypeType)
skip_pattern = r"(?:\.svn)|(?:[^.]+\.py[co])|(?:.*~)|(?:.*\$py\.class)"

def ls_tree(dir_path="",
            skip_pattern=skip_pattern,
            indent="|-- ", branch_indent="|   ",
            last_indent="`-- ", last_branch_indent="    "):
    # TODO: empty directories look like non-directory files
    return "\n".join(_ls_tree_lines(dir_path, skip_pattern,
                                    indent, branch_indent,
                                    last_indent, last_branch_indent))


def _ls_tree_lines(dir_path, skip_pattern,
                   indent, branch_indent, last_indent, last_branch_indent):
    if dir_path == "":
        dir_path = os.getcwd()

    lines = []

    names = os.listdir(dir_path)
    names.sort()
    dirs, nondirs = [], []
    for name in names:
        if re.match(skip_pattern, name):
            continue
        if os.path.isdir(os.path.join(dir_path, name)):
            dirs.append(name)
        else:
            nondirs.append(name)

    # list non-directories first
    entries = list(itertools.chain([(name, False) for name in nondirs],
                                   [(name, True) for name in dirs]))
    def ls_entry(name, is_dir, ind, branch_ind):
        if not is_dir:
            yield ind + name
        else:
            path = os.path.join(dir_path, name)
            if not os.path.islink(path):
                yield ind + name
                subtree = _ls_tree_lines(path, skip_pattern,
                                         indent, branch_indent,
                                         last_indent, last_branch_indent)
                for x in subtree:
                    yield branch_ind + x
    for name, is_dir in entries[:-1]:
        for line in ls_entry(name, is_dir, indent, branch_indent):
            yield line
    if entries:
        name, is_dir = entries[-1]
        for line in ls_entry(name, is_dir, last_indent, last_branch_indent):
            yield line


def absdir(path):
    """Return absolute, normalized path to directory, if it exists; None
    otherwise.
    """
    if not os.path.isabs(path):
        path = os.path.normpath(os.path.abspath(os.path.join(os.getcwd(),
                                                             path)))
    if path is None or not os.path.isdir(path):
        return None
    return path


def absfile(path, where=None):
    """Return absolute, normalized path to file (optionally in directory
    where), or None if the file can't be found either in where or the current
    working directory.
    """
    orig = path
    if where is None:
        where = os.getcwd()
    if isinstance(where, list) or isinstance(where, tuple):
        for maybe_path in where:
            maybe_abs = absfile(path, maybe_path)
            if maybe_abs is not None:
                return maybe_abs
        return None
    if not os.path.isabs(path):
        path = os.path.normpath(os.path.abspath(os.path.join(where, path)))
    if path is None or not os.path.exists(path):
        if where != os.getcwd():
            # try the cwd instead
            path = os.path.normpath(os.path.abspath(os.path.join(os.getcwd(),
                                                                 orig)))
    if path is None or not os.path.exists(path):
        return None
    if os.path.isdir(path):
        # might want an __init__.py from pacakge
        init = os.path.join(path,'__init__.py')
        if os.path.isfile(init):
            return init
    elif os.path.isfile(path):
        return path
    return None


def anyp(predicate, iterable):
    for item in iterable:
        if predicate(item):
            return True
    return False


def file_like(name):
    """A name is file-like if it is a path that exists, or it has a
    directory part, or it ends in .py, or it isn't a legal python
    identifier.
    """
    return (os.path.exists(name)
            or os.path.dirname(name)
            or name.endswith('.py')
            or not ident_re.match(os.path.splitext(name)[0]))


def cmp_lineno(a, b):
    """Compare functions by their line numbers.
    
    >>> cmp_lineno(isgenerator, ispackage)
    -1
    >>> cmp_lineno(ispackage, isgenerator)
    1
    >>> cmp_lineno(isgenerator, isgenerator)
    0
    """
    return cmp(func_lineno(a), func_lineno(b))


def func_lineno(func):
    """Get the line number of a function. First looks for
    compat_co_firstlineno, then func_code.co_first_lineno.
    """
    try:
        return func.compat_co_firstlineno
    except AttributeError:
        try:
            return func.func_code.co_firstlineno
        except AttributeError:
            return -1


def isclass(obj):
    """Is obj a class? inspect's isclass is too liberal and returns True
    for objects that can't be subclasses of anything.
    """
    obj_type = type(obj)
    return obj_type in class_types or issubclass(obj_type, type)


def isgenerator(func):
    try:
        return func.func_code.co_flags & CO_GENERATOR != 0
    except AttributeError:
        return False
# backwards compat (issue #64)
is_generator = isgenerator


def ispackage(path):
    """
    Is this path a package directory?

    >>> ispackage('nose')
    True
    >>> ispackage('unit_tests')
    False
    >>> ispackage('nose/plugins')
    True
    >>> ispackage('nose/loader.py')
    False
    """
    if os.path.isdir(path):
        # at least the end of the path must be a legal python identifier
        # and __init__.py[co] must exist
        end = os.path.basename(path)
        if ident_re.match(end):
            for init in ('__init__.py', '__init__.pyc', '__init__.pyo'):
                if os.path.isfile(os.path.join(path, init)):
                    return True
            if sys.platform.startswith('java') and \
                    os.path.isfile(os.path.join(path, '__init__$py.class')):
                return True
    return False


def getfilename(package, relativeTo=None):
    """Find the python source file for a package, relative to a
    particular directory (defaults to current working directory if not
    given).
    """
    if relativeTo is None:
        relativeTo = os.getcwd()
    path = os.path.join(relativeTo, os.sep.join(package.split('.')))
    suffixes = ('/__init__.py', '.py')
    for suffix in suffixes:
        filename = path + suffix
        if os.path.exists(filename):
            return filename
    return None
    

def getpackage(filename):
    """
    Find the full dotted package name for a given python source file
    name. Returns None if the file is not a python source file.
    
    >>> getpackage('foo.py')
    'foo'
    >>> getpackage('biff/baf.py')
    'baf'
    >>> getpackage('nose/util.py')
    'nose.util'

    Works for directories too.

    >>> getpackage('nose')
    'nose'
    >>> getpackage('nose/plugins')
    'nose.plugins'

    And __init__ files stuck onto directories

    >>> getpackage('nose/plugins/__init__.py')
    'nose.plugins'

    Absolute paths also work.

    >>> path = os.path.abspath(os.path.join('nose', 'plugins'))
    >>> getpackage(path)
    'nose.plugins'
    """
    src_file = src(filename)
    if not src_file.endswith('.py') and not ispackage(src_file):
        return None
    base, ext = os.path.splitext(os.path.basename(src_file))
    if base == '__init__':
        mod_parts = []
    else:
        mod_parts = [base]
    path, part = os.path.split(os.path.split(src_file)[0])
    while part:
        if ispackage(os.path.join(path, part)):
            mod_parts.append(part)
        else:
            break
        path, part = os.path.split(path)
    mod_parts.reverse()
    return '.'.join(mod_parts)


def ln(label):
    """Draw a 70-char-wide divider, with label in the middle.

    >>> ln('hello there')
    '---------------------------- hello there -----------------------------'
    """
    label_len = len(label) + 2
    chunk = (70 - label_len) / 2
    out = '%s %s %s' % ('-' * chunk, label, '-' * chunk)
    pad = 70 - len(out)
    if pad > 0:
        out = out + ('-' * pad)
    return out


def resolve_name(name, module=None):
    """Resolve a dotted name to a module and its parts. This is stolen
    wholesale from unittest.TestLoader.loadTestByName.

    >>> resolve_name('nose.util') #doctest: +ELLIPSIS
    <module 'nose.util' from...>
    >>> resolve_name('nose.util.resolve_name') #doctest: +ELLIPSIS
    <function resolve_name at...>
    """
    parts = name.split('.')
    parts_copy = parts[:]
    if module is None:
        while parts_copy:
            try:
                log.debug("__import__ %s", name)
                module = __import__('.'.join(parts_copy))
                break
            except ImportError:
                del parts_copy[-1]
                if not parts_copy:
                    raise
        parts = parts[1:]
    obj = module
    log.debug("resolve: %s, %s, %s, %s", parts, name, obj, module)
    for part in parts:
        obj = getattr(obj, part)
    return obj


def split_test_name(test):
    """Split a test name into a 3-tuple containing file, module, and callable
    names, any of which (but not all) may be blank.

    Test names are in the form:

    file_or_module:callable

    Either side of the : may be dotted. To change the splitting behavior, you
    can alter nose.util.split_test_re.
    """
    norm = os.path.normpath
    file_or_mod = test
    fn = None
    if not ':' in test:
        # only a file or mod part
        if file_like(test):
            return (norm(test), None, None)
        else:
            return (None, test, None)

    # could be path|mod:callable, or a : in the file path someplace
    head, tail = os.path.split(test)
    if not head:
        # this is a case like 'foo:bar' -- generally a module
        # name followed by a callable, but also may be a windows
        # drive letter followed by a path
        try:
            file_or_mod, fn = test.split(':')
            if file_like(fn):
                # must be a funny path
                file_or_mod, fn = test, None
        except ValueError:
            # more than one : in the test
            # this is a case like c:\some\path.py:a_test
            parts = test.split(':')
            if len(parts[0]) == 1:
                file_or_mod, fn = ':'.join(parts[:-1]), parts[-1]
            else:
                # nonsense like foo:bar:baz
                raise ValueError("Test name '%s' could not be parsed. Please "
                                 "format test names as path:callable or "
                                 "module:callable.")
    elif not tail:
        # this is a case like 'foo:bar/'
        # : must be part of the file path, so ignore it
        file_or_mod = test
    else:
        if ':' in tail:
            file_part, fn = tail.split(':')
        else:
            file_part = tail
        file_or_mod = os.sep.join([head, file_part])
    if file_or_mod:
        if file_like(file_or_mod):
            return (norm(file_or_mod), None, fn)
        else:
            return (None, file_or_mod, fn)
    else:
        return (None, None, fn)
split_test_name.__test__ = False # do not collect

    
def test_address(test):
    """Find the test address for a test, which may be a module, filename,
    class, method or function.
    """
    if hasattr(test, "address"):
        return test.address()
    # type-based polymorphism sucks in general, but I believe is
    # appropriate here
    t = type(test)
    file = module = call = None
    if t == types.ModuleType:
        file = getattr(test, '__file__', None)
        module = getattr(test, '__name__', None)
        return (file, module, call)
    if t == types.FunctionType or issubclass(t, type) or t == types.ClassType:
        module = getattr(test, '__module__', None)
        if module is not None:
            m = sys.modules[module]
            file = getattr(m, '__file__', None)
            if file is not None:
                file = os.path.abspath(file)
        call = getattr(test, '__name__', None)
        return (file, module, call)
    if t == types.InstanceType:
        return test_address(test.__class__)
    if t == types.MethodType:
        cls_adr = test_address(test.im_class)
        return (cls_adr[0], cls_adr[1],
                "%s.%s" % (cls_adr[2], test.__name__))
    # handle unittest.TestCase instances
    if isinstance(test, unittest.TestCase):
        if hasattr(test, '_FunctionTestCase__testFunc'):
            # unittest FunctionTestCase
            return test_address(test._FunctionTestCase__testFunc)
        # regular unittest.TestCase
        cls_adr = test_address(test.__class__)
        # 2.5 compat: __testMethodName changed to _testMethodName
        try:
            method_name = test._TestCase__testMethodName
        except AttributeError:
            method_name = test._testMethodName
        return (cls_adr[0], cls_adr[1],
                "%s.%s" % (cls_adr[2], method_name))
    raise TypeError("I don't know what %s is (%s)" % (test, t))
test_address.__test__ = False # do not collect


def try_run(obj, names):
    """Given a list of possible method names, try to run them with the
    provided object. Keep going until something works. Used to run
    setup/teardown methods for module, package, and function tests.
    """
    for name in names:
        func = getattr(obj, name, None)
        if func is not None:
            if type(obj) == types.ModuleType:
                # py.test compatibility
                try:
                    args, varargs, varkw, defaults = inspect.getargspec(func)
                except TypeError:
                    # Not a function. If it's callable, call it anyway
                    if hasattr(func, '__call__'):
                        func = func.__call__
                    try:
                        args, varargs, varkw, defaults = \
                            inspect.getargspec(func)
                        args.pop(0) # pop the self off
                    except TypeError:
                        raise TypeError("Attribute %s of %r is not a python "
                                        "function. Only functions or callables"
                                        " may be used as fixtures." %
                                        (name, obj))                    
                if len(args):
                    log.debug("call fixture %s.%s(%s)", obj, name, obj)    
                    return func(obj)
            log.debug("call fixture %s.%s", obj, name)
            return func()


def src(filename):
    """Find the python source file for a .pyc, .pyo or $py.class file on
    jython. Returns the filename provided if it is not a python source
    file.
    """
    if filename is None:
        return filename
    if sys.platform.startswith('java') and filename.endswith('$py.class'):
        return '.'.join((filename[:-9], 'py'))
    base, ext = os.path.splitext(filename)
    if ext in ('.pyc', '.pyo', '.py'):
        return '.'.join((base, 'py'))
    return filename


def match_last(a, b, regex):
    """Sort compare function that puts items that match a
    regular expression last.

    >>> from nose.config import Config
    >>> c = Config()
    >>> regex = c.testMatch
    >>> entries = ['.', '..', 'a_test', 'src', 'lib', 'test', 'foo.py']
    >>> entries.sort(lambda a, b: match_last(a, b, regex))
    >>> entries
    ['.', '..', 'foo.py', 'lib', 'src', 'a_test', 'test']
    """
    if regex.search(a) and not regex.search(b):
        return 1
    elif regex.search(b) and not regex.search(a):
        return -1
    return cmp(a, b)

        
def tolist(val):
    """Convert a value that may be a list or a (possibly comma-separated)
    string into a list. The exception: None is returned as None, not [None].

    >>> tolist(["one", "two"])
    ['one', 'two']
    >>> tolist("hello")
    ['hello']
    >>> tolist("separate,values, with, commas,  spaces , are    ,ok")
    ['separate', 'values', 'with', 'commas', 'spaces', 'are', 'ok']
    """
    if val is None:
        return None
    try:
        # might already be a list
        val.extend([])
        return val
    except AttributeError:
        pass
    # might be a string
    try:
        return re.split(r'\s*,\s*', val)
    except TypeError:
        # who knows... 
        return list(val)


class odict(dict):
    """Simple ordered dict implementation, based on:

    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747
    """
    def __init__(self, *arg, **kw):
        self._keys = []
        super(odict, self).__init__(*arg, **kw)

    def __delitem__(self, key):
        super(odict, self).__delitem__(key)
        self._keys.remove(key)

    def __setitem__(self, key, item):
        super(odict, self).__setitem__(key, item)
        if key not in self._keys:
            self._keys.append(key)

    def __str__(self):
        return "{%s}" % ', '.join(["%r: %r" % (k, v) for k, v in self.items()])

    def clear(self):
        super(odict, self).clear()
        self._keys = []

    def copy(self):
        d = super(odict, self).copy()
        d._keys = self._keys[:]
        return d

    def items(self):
        return zip(self._keys, self.values())

    def keys(self):
        return self._keys[:]

    def setdefault(self, key, failobj=None):
        item = super(odict, self).setdefault(key, failobj)
        if key not in self._keys:
            self._keys.append(key)
        return item

    def update(self, dict):
        super(odict, self).update(dict)
        for key in dict.keys():
            if key not in self._keys:
                self._keys.append(key)

    def values(self):
        return map(self.get, self._keys)


def transplant_func(func, module):
    """
    Make a function imported from module A appear as if it is located
    in module B.

    >>> from pprint import pprint
    >>> pprint.__module__
    'pprint'
    >>> pp = transplant_func(pprint, __name__)
    >>> pp.__module__
    'nose.util'

    The original function is not modified

    >>> pprint.__module__
    'pprint'

    Calling the transplanted function calls the original.

    >>> pp([1, 2])
    [1, 2]
    >>> pprint([1,2])
    [1, 2]

    """
    from nose.tools import make_decorator
    def newfunc(*arg, **kw):
        return func(*arg, **kw)
    
    newfunc = make_decorator(func)(newfunc)
    newfunc.__module__ = module
    return newfunc


def transplant_class(cls, module):
    """
    Make a class appear to reside in `module`, rather than the module in which
    it is actually defined.

    >>> from nose.failure import Failure
    >>> Failure.__module__
    'nose.failure'
    >>> Nf = transplant_class(Failure, __name__)
    >>> Nf.__module__
    'nose.util'
    >>> Nf.__name__
    'Failure'
    
    """
    class C(cls):
        pass
    C.__module__ = module
    C.__name__ = cls.__name__
    return C


if __name__ == '__main__':
    import doctest
    doctest.testmod()