1
# Copyright (C) 2004, 2005 by Canonical Ltd
1
# Copyright (C) 2004, 2005 Canonical Ltd
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.
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.
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.
45
from bzrlib.lazy_import import lazy_import
46
lazy_import(globals(), """
48
from bzrlib.config import config_dir
49
from bzrlib.trace import log_error, mutter, log_exception, warning, \
51
from bzrlib.errors import BzrError
52
from bzrlib import plugins
53
from bzrlib.osutils import pathjoin
55
DEFAULT_PLUGIN_PATH = pathjoin(config_dir(), 'plugins')
57
from bzrlib.trace import mutter, warning, log_exception_quietly
60
DEFAULT_PLUGIN_PATH = None
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
93
107
# People can make sure plugins are loaded, they just won't be twice
95
#raise BzrError("plugins already initialized")
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__))
101
115
load_from_dirs(dirs)
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.
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]
127
140
if not os.path.isdir(d):
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
135
if os.path.isfile(pathjoin(path, entry)):
148
if os.path.isfile(osutils.pathjoin(path, entry)):
137
150
else: # This directory is not a package
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'):
148
if getattr(bzrlib.plugins, f, None):
161
if getattr(plugins, f, None):
149
162
mutter('Plugin name %s already loaded', f)
151
mutter('add plugin name %s', f)
164
# mutter('add plugin name %s', f)
152
165
plugin_names.add(f)
154
167
plugin_names = list(plugin_names)
156
169
for name in plugin_names:
158
171
plugin_info = imp.find_module(name, [d])
159
mutter('load plugin %r', plugin_info)
172
# mutter('load plugin %r', plugin_info)
161
174
plugin = imp.load_module('bzrlib.plugins.' + name,
163
setattr(bzrlib.plugins, name, plugin)
176
setattr(plugins, name, plugin)
165
178
if plugin_info[0] is not None:
166
179
plugin_info[0].close()
168
mutter('loaded succesfully')
180
# mutter('loaded succesfully')
169
181
except KeyboardInterrupt:
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()
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.
196
valid_suffixes = ('.py', '.pyc', '.pyo') # only python modules/packages
198
for zip_name in zips:
199
if '.zip' not in zip_name:
202
ziobj = zipimport.zipimporter(zip_name)
203
except zipimport.ZipImportError:
206
mutter('Looking for plugins in %r', zip_name)
208
# use zipfile to get list of files/dirs inside zip
209
z = zipfile.ZipFile(ziobj.archive)
210
namelist = z.namelist()
214
prefix = ziobj.prefix.replace('\\','/')
216
namelist = [name[ix:]
218
if name.startswith(prefix)]
220
mutter('Names in archive: %r', namelist)
222
for name in namelist:
223
if not name or name.endswith('/'):
226
# '/' is used to separate pathname components inside zip archives
229
head, tail = '', name
231
head, tail = name.rsplit('/',1)
233
# we don't need looking in subdirectories
236
base, suffix = osutils.splitext(tail)
237
if suffix not in valid_suffixes:
240
if base == '__init__':
251
if getattr(plugins, plugin_name, None):
252
mutter('Plugin name %s already loaded', plugin_name)
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))
263
except KeyboardInterrupt:
266
## import pdb; pdb.set_trace()
267
warning('Unable to load plugin %r from %r'
269
log_exception_quietly()