summaryrefslogtreecommitdiff
path: root/repoze/bfg/path.py
blob: b4ff404941620572072ecbfa09211aa7c6f0a770 (plain)
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
48
49
50
51
52
53
54
55
56
57
58
59
60
import os
import pkg_resources
import sys

def caller_path(path, level=2):
    """ Return an absolute path """
    if not os.path.isabs(path):
        module = caller_module(level+1)
        prefix = package_path(module)
        path = os.path.join(prefix, path)
    return path

def caller_module(level=2):
    module_globals = sys._getframe(level).f_globals
    module_name = module_globals['__name__']
    module = sys.modules[module_name]
    return module

def package_name(pkg_or_module):
    """ If this function is passed a module, return the dotted Python
    package name of the package in which the module lives.  If this
    function is passed a package, return the dotted Python package
    name of the package itself."""
    if pkg_or_module is None:
        return '__main___'
    pkg_filename = pkg_or_module.__file__
    pkg_name = pkg_or_module.__name__
    splitted = os.path.split(pkg_filename)
    if splitted[-1] in ('__init__.py', '__init__.pyc', '__init__.pyo'):
        # it's a package
        return pkg_name
    return pkg_name.rsplit('.', 1)[0]

def caller_package(level=2, caller_module=caller_module):
    # caller_module in arglist for tests
    module = caller_module(level+1)
    if '__init__.py' in getattr(module, '__file__', ''): # empty at >>>
        # Module is a package
        return module
    # Go up one level to get package
    package_name = module.__name__.rsplit('.', 1)[0]
    return sys.modules[package_name]

def package_path(package):
    # computing the abspath is actually kinda expensive so we memoize
    # the result
    prefix = getattr(package, '__bfg_abspath__', None)
    if prefix is None:
        prefix = pkg_resources.resource_filename(package.__name__, '')
        # pkg_resources doesn't care whether we feed it a package
        # name or a module name within the package, the result
        # will be the same: a directory name to the package itself
        try:
            package.__bfg_abspath__ = prefix
        except:
            # this is only an optimization, ignore any error
            pass
    return prefix