~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Demo/imputil/importers.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# importers.py
 
3
#
 
4
# Demonstration subclasses of imputil.Importer
 
5
#
 
6
 
 
7
# There should be consideration for the imports below if it is desirable
 
8
# to have "all" modules be imported through the imputil system.
 
9
 
 
10
# these are C extensions
 
11
import sys
 
12
import imp
 
13
import struct
 
14
import marshal
 
15
 
 
16
# these are .py modules
 
17
import imputil
 
18
import os
 
19
 
 
20
######################################################################
 
21
 
 
22
_TupleType = type(())
 
23
_StringType = type('')
 
24
 
 
25
######################################################################
 
26
 
 
27
# byte-compiled file suffic character
 
28
_suffix_char = __debug__ and 'c' or 'o'
 
29
 
 
30
# byte-compiled file suffix
 
31
_suffix = '.py' + _suffix_char
 
32
 
 
33
# the C_EXTENSION suffixes
 
34
_c_suffixes = filter(lambda x: x[2] == imp.C_EXTENSION, imp.get_suffixes())
 
35
 
 
36
def _timestamp(pathname):
 
37
    "Return the file modification time as a Long."
 
38
    try:
 
39
        s = os.stat(pathname)
 
40
    except OSError:
 
41
        return None
 
42
    return long(s[8])
 
43
 
 
44
def _fs_import(dir, modname, fqname):
 
45
    "Fetch a module from the filesystem."
 
46
 
 
47
    pathname = os.path.join(dir, modname)
 
48
    if os.path.isdir(pathname):
 
49
        values = { '__pkgdir__' : pathname, '__path__' : [ pathname ] }
 
50
        ispkg = 1
 
51
        pathname = os.path.join(pathname, '__init__')
 
52
    else:
 
53
        values = { }
 
54
        ispkg = 0
 
55
 
 
56
        # look for dynload modules
 
57
        for desc in _c_suffixes:
 
58
            file = pathname + desc[0]
 
59
            try:
 
60
                fp = open(file, desc[1])
 
61
            except IOError:
 
62
                pass
 
63
            else:
 
64
                module = imp.load_module(fqname, fp, file, desc)
 
65
                values['__file__'] = file
 
66
                return 0, module, values
 
67
 
 
68
    t_py = _timestamp(pathname + '.py')
 
69
    t_pyc = _timestamp(pathname + _suffix)
 
70
    if t_py is None and t_pyc is None:
 
71
        return None
 
72
    code = None
 
73
    if t_py is None or (t_pyc is not None and t_pyc >= t_py):
 
74
        file = pathname + _suffix
 
75
        f = open(file, 'rb')
 
76
        if f.read(4) == imp.get_magic():
 
77
            t = struct.unpack('<I', f.read(4))[0]
 
78
            if t == t_py:
 
79
                code = marshal.load(f)
 
80
        f.close()
 
81
    if code is None:
 
82
        file = pathname + '.py'
 
83
        code = _compile(file, t_py)
 
84
 
 
85
    values['__file__'] = file
 
86
    return ispkg, code, values
 
87
 
 
88
######################################################################
 
89
#
 
90
# Simple function-based importer
 
91
#
 
92
class FuncImporter(imputil.Importer):
 
93
    "Importer subclass to delegate to a function rather than method overrides."
 
94
    def __init__(self, func):
 
95
        self.func = func
 
96
    def get_code(self, parent, modname, fqname):
 
97
        return self.func(parent, modname, fqname)
 
98
 
 
99
def install_with(func):
 
100
    FuncImporter(func).install()
 
101
 
 
102
 
 
103
######################################################################
 
104
#
 
105
# Base class for archive-based importing
 
106
#
 
107
class PackageArchiveImporter(imputil.Importer):
 
108
    """Importer subclass to import from (file) archives.
 
109
 
 
110
    This Importer handles imports of the style <archive>.<subfile>, where
 
111
    <archive> can be located using a subclass-specific mechanism and the
 
112
    <subfile> is found in the archive using a subclass-specific mechanism.
 
113
 
 
114
    This class defines two hooks for subclasses: one to locate an archive
 
115
    (and possibly return some context for future subfile lookups), and one
 
116
    to locate subfiles.
 
117
    """
 
118
 
 
119
    def get_code(self, parent, modname, fqname):
 
120
        if parent:
 
121
            # the Importer._finish_import logic ensures that we handle imports
 
122
            # under the top level module (package / archive).
 
123
            assert parent.__importer__ == self
 
124
 
 
125
            # if a parent "package" is provided, then we are importing a
 
126
            # sub-file from the archive.
 
127
            result = self.get_subfile(parent.__archive__, modname)
 
128
            if result is None:
 
129
                return None
 
130
            if isinstance(result, _TupleType):
 
131
                assert len(result) == 2
 
132
                return (0,) + result
 
133
            return 0, result, {}
 
134
 
 
135
        # no parent was provided, so the archive should exist somewhere on the
 
136
        # default "path".
 
137
        archive = self.get_archive(modname)
 
138
        if archive is None:
 
139
            return None
 
140
        return 1, "", {'__archive__':archive}
 
141
 
 
142
    def get_archive(self, modname):
 
143
        """Get an archive of modules.
 
144
 
 
145
        This method should locate an archive and return a value which can be
 
146
        used by get_subfile to load modules from it. The value may be a simple
 
147
        pathname, an open file, or a complex object that caches information
 
148
        for future imports.
 
149
 
 
150
        Return None if the archive was not found.
 
151
        """
 
152
        raise RuntimeError, "get_archive not implemented"
 
153
 
 
154
    def get_subfile(self, archive, modname):
 
155
        """Get code from a subfile in the specified archive.
 
156
 
 
157
        Given the specified archive (as returned by get_archive()), locate
 
158
        and return a code object for the specified module name.
 
159
 
 
160
        A 2-tuple may be returned, consisting of a code object and a dict
 
161
        of name/values to place into the target module.
 
162
 
 
163
        Return None if the subfile was not found.
 
164
        """
 
165
        raise RuntimeError, "get_subfile not implemented"
 
166
 
 
167
 
 
168
class PackageArchive(PackageArchiveImporter):
 
169
    "PackageArchiveImporter subclass that refers to a specific archive."
 
170
 
 
171
    def __init__(self, modname, archive_pathname):
 
172
        self.__modname = modname
 
173
        self.__path = archive_pathname
 
174
 
 
175
    def get_archive(self, modname):
 
176
        if modname == self.__modname:
 
177
            return self.__path
 
178
        return None
 
179
 
 
180
    # get_subfile is passed the full pathname of the archive
 
181
 
 
182
 
 
183
######################################################################
 
184
#
 
185
# Emulate the standard directory-based import mechanism
 
186
#
 
187
class DirectoryImporter(imputil.Importer):
 
188
    "Importer subclass to emulate the standard importer."
 
189
 
 
190
    def __init__(self, dir):
 
191
        self.dir = dir
 
192
 
 
193
    def get_code(self, parent, modname, fqname):
 
194
        if parent:
 
195
            dir = parent.__pkgdir__
 
196
        else:
 
197
            dir = self.dir
 
198
 
 
199
        # Return the module (and other info) if found in the specified
 
200
        # directory. Otherwise, return None.
 
201
        return _fs_import(dir, modname, fqname)
 
202
 
 
203
    def __repr__(self):
 
204
        return '<%s.%s for "%s" at 0x%x>' % (self.__class__.__module__,
 
205
                                             self.__class__.__name__,
 
206
                                             self.dir,
 
207
                                             id(self))
 
208
 
 
209
 
 
210
######################################################################
 
211
#
 
212
# Emulate the standard path-style import mechanism
 
213
#
 
214
class PathImporter(imputil.Importer):
 
215
    def __init__(self, path=sys.path):
 
216
        self.path = path
 
217
 
 
218
    def get_code(self, parent, modname, fqname):
 
219
        if parent:
 
220
            # we are looking for a module inside of a specific package
 
221
            return _fs_import(parent.__pkgdir__, modname, fqname)
 
222
 
 
223
        # scan sys.path, looking for the requested module
 
224
        for dir in self.path:
 
225
            if isinstance(dir, _StringType):
 
226
                result = _fs_import(dir, modname, fqname)
 
227
                if result:
 
228
                    return result
 
229
 
 
230
        # not found
 
231
        return None
 
232
 
 
233
######################################################################
 
234
 
 
235
def _test_dir():
 
236
    "Debug/test function to create DirectoryImporters from sys.path."
 
237
    imputil.ImportManager().install()
 
238
    path = sys.path[:]
 
239
    path.reverse()
 
240
    for d in path:
 
241
        sys.path.insert(0, DirectoryImporter(d))
 
242
    sys.path.insert(0, imputil.BuiltinImporter())
 
243
 
 
244
def _test_revamp():
 
245
    "Debug/test function for the revamped import system."
 
246
    imputil.ImportManager().install()
 
247
    sys.path.insert(0, PathImporter())
 
248
    sys.path.insert(0, imputil.BuiltinImporter())