/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/plugin.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-01-04 21:50:41 UTC
  • mfrom: (2221.2.2 internalerror)
  • Revision ID: pqm@pqm.ubuntu.com-20070104215041-e2f73db439c71aa6
Make most LockErrors internal

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2004, 2005 Canonical Ltd
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
39
39
# That could be either a separate Python interpreter or perhaps a new
40
40
# namespace inside this interpreter.
41
41
 
42
 
import imp
43
42
import os
44
43
import sys
 
44
 
 
45
from bzrlib.lazy_import import lazy_import
 
46
lazy_import(globals(), """
 
47
import imp
45
48
import types
46
49
 
47
 
import bzrlib
48
 
from bzrlib.config import config_dir
49
 
from bzrlib.trace import log_error, mutter, log_exception, warning, \
50
 
        log_exception_quietly
51
 
from bzrlib.errors import BzrError
52
 
from bzrlib import plugins
53
 
from bzrlib.osutils import pathjoin
54
 
 
55
 
DEFAULT_PLUGIN_PATH = pathjoin(config_dir(), 'plugins')
 
50
from bzrlib import (
 
51
    config,
 
52
    osutils,
 
53
    plugins,
 
54
    )
 
55
""")
 
56
 
 
57
from bzrlib.trace import mutter, warning, log_exception_quietly
 
58
 
 
59
 
 
60
DEFAULT_PLUGIN_PATH = None
 
61
 
 
62
 
 
63
def get_default_plugin_path():
 
64
    """Get the DEFAULT_PLUGIN_PATH"""
 
65
    global DEFAULT_PLUGIN_PATH
 
66
    if DEFAULT_PLUGIN_PATH is None:
 
67
        DEFAULT_PLUGIN_PATH = osutils.pathjoin(config.config_dir(), 'plugins')
 
68
    return DEFAULT_PLUGIN_PATH
 
69
 
56
70
 
57
71
_loaded = False
58
72
 
60
74
def all_plugins():
61
75
    """Return a dictionary of the plugins."""
62
76
    result = {}
63
 
    for name, plugin in bzrlib.plugins.__dict__.items():
 
77
    for name, plugin in plugins.__dict__.items():
64
78
        if isinstance(plugin, types.ModuleType):
65
79
            result[name] = plugin
66
80
    return result
92
106
    if _loaded:
93
107
        # People can make sure plugins are loaded, they just won't be twice
94
108
        return
95
 
        #raise BzrError("plugins already initialized")
96
109
    _loaded = True
97
110
 
98
 
    dirs = os.environ.get('BZR_PLUGIN_PATH', DEFAULT_PLUGIN_PATH).split(os.pathsep)
 
111
    dirs = os.environ.get('BZR_PLUGIN_PATH',
 
112
                          get_default_plugin_path()).split(os.pathsep)
99
113
    dirs.insert(0, os.path.dirname(plugins.__file__))
100
114
 
101
115
    load_from_dirs(dirs)
 
116
    load_from_zips(dirs)
102
117
 
103
118
 
104
119
def load_from_dirs(dirs):
111
126
    Plugins are loaded into bzrlib.plugins.NAME, and can be found there
112
127
    for future reference.
113
128
    """
114
 
    # The problem with imp.get_suffixes() is that it doesn't include
115
 
    # .pyo which is technically valid
116
 
    # It also means that "testmodule.so" will show up as both test and testmodule
117
 
    # though it is only valid as 'test'
118
 
    # but you should be careful, because "testmodule.py" loads as testmodule.
119
 
    suffixes = imp.get_suffixes()
120
 
    suffixes.append(('.pyo', 'rb', imp.PY_COMPILED))
121
 
    package_entries = ['__init__.py', '__init__.pyc', '__init__.pyo']
 
129
    # Get the list of valid python suffixes for __init__.py?
 
130
    # this includes .py, .pyc, and .pyo (depending on if we are running -O)
 
131
    # but it doesn't include compiled modules (.so, .dll, etc)
 
132
    valid_suffixes = [suffix for suffix, mod_type, flags in imp.get_suffixes()
 
133
                              if flags in (imp.PY_SOURCE, imp.PY_COMPILED)]
 
134
    package_entries = ['__init__'+suffix for suffix in valid_suffixes]
122
135
    for d in dirs:
123
136
        if not d:
124
137
            continue
127
140
        if not os.path.isdir(d):
128
141
            continue
129
142
        for f in os.listdir(d):
130
 
            path = pathjoin(d, f)
 
143
            path = osutils.pathjoin(d, f)
131
144
            if os.path.isdir(path):
132
145
                for entry in package_entries:
133
146
                    # This directory should be a package, and thus added to
134
147
                    # the list
135
 
                    if os.path.isfile(pathjoin(path, entry)):
 
148
                    if os.path.isfile(osutils.pathjoin(path, entry)):
136
149
                        break
137
150
                else: # This directory is not a package
138
151
                    continue
139
152
            else:
140
 
                for suffix_info in suffixes:
 
153
                for suffix_info in imp.get_suffixes():
141
154
                    if f.endswith(suffix_info[0]):
142
155
                        f = f[:-len(suffix_info[0])]
143
156
                        if suffix_info[2] == imp.C_EXTENSION and f.endswith('module'):
145
158
                        break
146
159
                else:
147
160
                    continue
148
 
            if getattr(bzrlib.plugins, f, None):
 
161
            if getattr(plugins, f, None):
149
162
                mutter('Plugin name %s already loaded', f)
150
163
            else:
151
 
                mutter('add plugin name %s', f)
 
164
                # mutter('add plugin name %s', f)
152
165
                plugin_names.add(f)
153
166
 
154
167
        plugin_names = list(plugin_names)
156
169
        for name in plugin_names:
157
170
            try:
158
171
                plugin_info = imp.find_module(name, [d])
159
 
                mutter('load plugin %r', plugin_info)
 
172
                # mutter('load plugin %r', plugin_info)
160
173
                try:
161
174
                    plugin = imp.load_module('bzrlib.plugins.' + name,
162
175
                                             *plugin_info)
163
 
                    setattr(bzrlib.plugins, name, plugin)
 
176
                    setattr(plugins, name, plugin)
164
177
                finally:
165
178
                    if plugin_info[0] is not None:
166
179
                        plugin_info[0].close()
167
 
 
168
 
                mutter('loaded succesfully')
 
180
                # mutter('loaded succesfully')
169
181
            except KeyboardInterrupt:
170
182
                raise
171
183
            except Exception, e:
172
184
                ## import pdb; pdb.set_trace()
173
185
                warning('Unable to load plugin %r from %r' % (name, d))
174
186
                log_exception_quietly()
 
187
 
 
188
 
 
189
def load_from_zips(zips):
 
190
    """Load bzr plugins from zip archives with zipimport.
 
191
    It's similar to load_from_dirs but plugins searched inside archives.
 
192
    """
 
193
    import zipfile
 
194
    import zipimport
 
195
 
 
196
    valid_suffixes = ('.py', '.pyc', '.pyo')    # only python modules/packages
 
197
                                                # is allowed
 
198
    for zip_name in zips:
 
199
        if '.zip' not in zip_name:
 
200
            continue
 
201
        try:
 
202
            ziobj = zipimport.zipimporter(zip_name)
 
203
        except zipimport.ZipImportError:
 
204
            # not a valid zip
 
205
            continue
 
206
        mutter('Looking for plugins in %r', zip_name)
 
207
 
 
208
        # use zipfile to get list of files/dirs inside zip
 
209
        z = zipfile.ZipFile(ziobj.archive)
 
210
        namelist = z.namelist()
 
211
        z.close()
 
212
 
 
213
        if ziobj.prefix:
 
214
            prefix = ziobj.prefix.replace('\\','/')
 
215
            ix = len(prefix)
 
216
            namelist = [name[ix:]
 
217
                        for name in namelist
 
218
                        if name.startswith(prefix)]
 
219
 
 
220
        mutter('Names in archive: %r', namelist)
 
221
 
 
222
        for name in namelist:
 
223
            if not name or name.endswith('/'):
 
224
                continue
 
225
 
 
226
            # '/' is used to separate pathname components inside zip archives
 
227
            ix = name.rfind('/')
 
228
            if ix == -1:
 
229
                head, tail = '', name
 
230
            else:
 
231
                head, tail = name.rsplit('/',1)
 
232
            if '/' in head:
 
233
                # we don't need looking in subdirectories
 
234
                continue
 
235
 
 
236
            base, suffix = osutils.splitext(tail)
 
237
            if suffix not in valid_suffixes:
 
238
                continue
 
239
 
 
240
            if base == '__init__':
 
241
                # package
 
242
                plugin_name = head
 
243
            elif head == '':
 
244
                # module
 
245
                plugin_name = base
 
246
            else:
 
247
                continue
 
248
 
 
249
            if not plugin_name:
 
250
                continue
 
251
            if getattr(plugins, plugin_name, None):
 
252
                mutter('Plugin name %s already loaded', plugin_name)
 
253
                continue
 
254
 
 
255
            try:
 
256
                plugin = ziobj.load_module(plugin_name)
 
257
                setattr(plugins, plugin_name, plugin)
 
258
                mutter('Load plugin %s from zip %r', plugin_name, zip_name)
 
259
            except zipimport.ZipImportError, e:
 
260
                mutter('Unable to load plugin %r from %r: %s',
 
261
                       plugin_name, zip_name, str(e))
 
262
                continue
 
263
            except KeyboardInterrupt:
 
264
                raise
 
265
            except Exception, e:
 
266
                ## import pdb; pdb.set_trace()
 
267
                warning('Unable to load plugin %r from %r'
 
268
                        % (name, zip_name))
 
269
                log_exception_quietly()