~bzr-pqm/bzr/bzr.dev

5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
1
# Copyright (C) 2010 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
17
"""General Python convenience functions."""
18
6379.6.3 by Jelmer Vernooij
Use absolute_import.
19
from __future__ import absolute_import
20
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
21
import sys
22
23
24
def get_named_object(module_name, member_name=None):
25
    """Get the Python object named by a given module and member name.
26
27
    This is usually much more convenient than dealing with ``__import__``
5436.2.6 by Andrew Bennetts
Add doctest-able example to get_named_object docstring. Make doctest skip calc_parent_name docstring.
28
    directly::
29
30
        >>> doc = get_named_object('bzrlib.pyutils', 'get_named_object.__doc__')
31
        >>> doc.splitlines()[0]
32
        'Get the Python object named by a given module and member name.'
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
33
5436.2.7 by Andrew Bennetts
Docstring tweaks prompted by review.
34
    :param module_name: a module name, as would be found in sys.modules if
35
        the module is already imported.  It may contain dots.  e.g. 'sys' or
36
        'os.path'.
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
37
    :param member_name: (optional) a name of an attribute in that module to
38
        return.  It may contain dots.  e.g. 'MyClass.some_method'.  If not
39
        given, the named module will be returned instead.
40
    :raises: ImportError or AttributeError.
41
    """
42
    # We may have just a module name, or a module name and a member name,
43
    # and either may contain dots.  __import__'s return value is a bit
44
    # unintuitive, so we need to take care to always return the object
45
    # specified by the full combination of module name + member name.
46
    if member_name:
47
        # Give __import__ a from_list.  It will return the last module in
48
        # the dotted module name.
49
        attr_chain = member_name.split('.')
50
        from_list = attr_chain[:1]
51
        obj = __import__(module_name, {}, {}, from_list)
52
        for attr in attr_chain:
53
            obj = getattr(obj, attr)
54
    else:
55
        # We're just importing a module, no attributes, so we have no
56
        # from_list.  __import__ will return the first module in the dotted
57
        # module name, so we look up the module from sys.modules.
58
        __import__(module_name, globals(), locals(), [])
59
        obj = sys.modules[module_name]
60
    return obj
61
62
63
def calc_parent_name(module_name, member_name=None):
64
    """Determine the 'parent' of a given dotted module name and (optional)
65
    member name.
66
67
    The idea is that ``getattr(parent_obj, final_attr)`` will equal
68
    get_named_object(module_name, member_name).
69
70
    :return: (module_name, member_name, final_attr) tuple.
71
    """
5501.1.1 by Vincent Ladeuil
Unbreak pqm by commenting out the bogus use of doctest +SKIP not supported by python2.4
72
# +SKIP is not recognized by python2.4
73
# Typical use is::
74
# 
75
#     >>> parent_mod, parent_member, final_attr = calc_parent_name(
76
#     ...     module_name, member_name) # doctest: +SKIP
77
#     >>> parent_obj = get_named_object(parent_mod, parent_member)
78
#     ... # doctest: +SKIP
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
79
    if member_name is not None:
80
        split_name = member_name.rsplit('.', 1)
81
        if len(split_name) == 1:
82
            return (module_name, None, member_name)
83
        else:
84
            return (module_name, split_name[0], split_name[1])
85
    else:
86
        split_name = module_name.rsplit('.', 1)
87
        if len(split_name) == 1:
88
            raise AssertionError(
89
                'No parent object for top-level module %r' % (module_name,))
90
        else:
91
            return (split_name[0], None, split_name[1])