67
# {prefix: [transport_classes]}
68
# Transports are inserted onto the list LIFO and tried in order; as a result
69
# transports provided by plugins are tried first, which is usually what we
71
_protocol_handlers = {
74
def register_transport(prefix, klass, override=DEPRECATED_PARAMETER):
75
"""Register a transport that can be used to open URLs
77
Normally you should use register_lazy_transport, which defers loading the
78
implementation until it's actually used, and so avoids pulling in possibly
79
large implementation libraries.
81
# Note that this code runs very early in library setup -- trace may not be
83
global _protocol_handlers
84
if deprecated_passed(override):
85
warnings.warn("register_transport(override) is deprecated")
86
_protocol_handlers.setdefault(prefix, []).insert(0, klass)
89
def register_lazy_transport(scheme, module, classname):
90
"""Register lazy-loaded transport class.
92
When opening a URL with the given scheme, load the module and then
93
instantiate the particular class.
95
If the module raises DependencyNotPresent when it's imported, it is
96
skipped and another implementation of the protocol is tried. This is
97
intended to be used when the implementation depends on an external
98
implementation that may not be present. If any other error is raised, it
99
propagates up and the attempt to open the url fails.
101
:param scheme: The url scheme part, eg "ftp://"
103
# TODO: If no implementation of a protocol is available because of missing
104
# dependencies, we should perhaps show the message about what dependency
107
mod = __import__(module, globals(), locals(), [classname])
108
klass = getattr(mod, classname)
110
_loader.module = module
111
register_transport(scheme, _loader)
114
def unregister_transport(scheme, factory):
115
"""Unregister a transport."""
116
_protocol_handlers[scheme].remove(factory)
117
if _protocol_handlers[scheme] == []:
118
del _protocol_handlers[scheme]
66
from bzrlib import registry
121
69
def _get_protocol_handlers():
122
70
"""Return a dictionary of {urlprefix: [factory]}"""
123
return _protocol_handlers
71
return transport_list_registry
126
74
def _set_protocol_handlers(new_handlers):
129
77
WARNING this will remove all build in protocols. Use with care.
131
global _protocol_handlers
132
_protocol_handlers = new_handlers
79
global transport_list_registry
80
transport_list_registry = new_handlers
135
83
def _clear_protocol_handlers():
136
global _protocol_handlers
137
_protocol_handlers = {}
84
global transport_list_registry
85
transport_list_registry = TransportListRegistry()
140
88
def _get_transport_modules():
141
89
"""Return a list of the modules providing transports."""
143
for prefix, factory_list in _protocol_handlers.items():
91
for prefix, factory_list in transport_list_registry.iteritems():
144
92
for factory in factory_list:
145
if factory.__module__ == "bzrlib.transport":
146
# this is a lazy load transport, because no real ones
147
# are directly in bzrlib.transport
148
modules.add(factory.module)
93
if hasattr(factory, "_module_name"):
94
modules.add(factory._module_name)
150
modules.add(factory.__module__)
96
modules.add(factory._obj.__module__)
151
97
# Add chroot directly, because there is not handler registered for it.
152
98
modules.add('bzrlib.transport.chroot')
153
99
result = list(modules)
104
class TransportListRegistry(registry.Registry):
105
"""A registry which simplifies tracking available Transports.
107
A registration of a new protocol requires two step:
108
1) register the prefix with the function register_transport( )
109
2) register the protocol provider with the function
110
register_transport_provider( ) ( and the "lazy" variant )
112
This in needed because:
113
a) a single provider can support multple protcol ( like the ftp
114
privider which supports both the ftp:// and the aftp:// protocols )
115
b) a single protocol can have multiple providers ( like the http://
116
protocol which is supported by both the urllib and pycurl privider )
119
def register_transport_provider(self, key, obj):
120
self.get(key).insert(0, registry._ObjectGetter(obj))
122
def register_lazy_transport_provider(self, key, module_name, member_name):
123
self.get(key).insert(0,
124
registry._LazyObjectGetter(module_name, member_name))
126
def register_transport(self, key, help=None, info=None):
127
self.register(key, [], help, info)
129
def set_default_transport(self, key=None):
130
"""Return either 'key' or the default key if key is None"""
131
self._default_key = key
134
transport_list_registry = TransportListRegistry( )
137
def register_transport_proto(prefix, help=None, info=None):
138
transport_list_registry.register_transport(prefix, help, info)
141
def register_lazy_transport(prefix, module, classname):
142
if not prefix in transport_list_registry:
143
register_transport_proto(prefix)
144
transport_list_registry.register_lazy_transport_provider(prefix, module, classname)
147
def register_transport(prefix, klass, override=DEPRECATED_PARAMETER):
148
if not prefix in transport_list_registry:
149
register_transport_proto(prefix)
150
transport_list_registry.register_transport_provider(prefix, klass)
158
153
def register_urlparse_netloc_protocol(protocol):
159
154
"""Ensure that protocol is setup to be used with urlparse netloc parsing."""
160
155
if protocol not in urlparse.uses_netloc:
161
156
urlparse.uses_netloc.append(protocol)
159
def unregister_transport(scheme, factory):
160
"""Unregister a transport."""
161
l = transport_list_registry.get(scheme)
165
transport_list_registry.get(scheme).remove(i)
168
transport_list_registry.remove(scheme)
164
172
def split_url(url):
165
173
# TODO: jam 20060606 urls should only be ascii, or they should raise InvalidURL
166
174
if isinstance(url, unicode):
1218
1227
def readv(self, name, offsets):
1219
1228
self._calls.append((name, offsets))
1220
1229
return self._adapted.readv(name, offsets)
1223
1232
# None is the default transport, for things with no url scheme
1224
register_lazy_transport(None, 'bzrlib.transport.local', 'LocalTransport')
1233
register_transport_proto('file://',
1234
help="Access using the standard filesystem (default)")
1225
1235
register_lazy_transport('file://', 'bzrlib.transport.local', 'LocalTransport')
1236
transport_list_registry.set_default_transport("file://")
1238
register_transport_proto('sftp://',
1239
help="Access using SFTP (most SSH servers provide SFTP).")
1226
1240
register_lazy_transport('sftp://', 'bzrlib.transport.sftp', 'SFTPTransport')
1227
1241
# Decorated http transport
1242
register_transport_proto('http+urllib://',
1243
# help="Read-only access of branches exported on the web."
1228
1245
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
1229
1246
'HttpTransport_urllib')
1247
register_transport_proto('https+urllib://',
1248
# help="Read-only access of branches exported on the web using SSL."
1230
1250
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
1231
1251
'HttpTransport_urllib')
1252
register_transport_proto('http+pycurl://',
1253
# help="Read-only access of branches exported on the web."
1232
1255
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
1233
1256
'PyCurlTransport')
1257
register_transport_proto('https+pycurl://',
1258
# help="Read-only access of branches exported on the web using SSL."
1234
1260
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
1235
1261
'PyCurlTransport')
1236
1262
# Default http transports (last declared wins (if it can be imported))
1263
register_transport_proto('http://',
1264
help="Read-only access of branches exported on the web.")
1265
register_transport_proto('https://',
1266
help="Read-only access of branches exported on the web using SSL.")
1237
1267
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
1238
1268
'HttpTransport_urllib')
1239
1269
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
1240
1270
'HttpTransport_urllib')
1241
1271
register_lazy_transport('http://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
1242
1272
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
1274
register_transport_proto('ftp://',
1275
help="Access using passive FTP.")
1243
1276
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1277
register_transport_proto('aftp://',
1278
help="Access using active FTP.")
1244
1279
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1281
register_transport_proto('memory://')
1245
1282
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
1283
register_transport_proto('chroot+')
1285
register_transport_proto('readonly+',
1286
# help="This modifier converts any transport to be readonly."
1246
1288
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')
1289
register_transport_proto('fakenfs+')
1247
1290
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
1291
register_transport_proto('vfat+')
1248
1292
register_lazy_transport('vfat+',
1249
1293
'bzrlib.transport.fakevfat',
1250
1294
'FakeVFATTransportDecorator')
1295
register_transport_proto('bzr://',
1296
help="Fast access using the Bazaar smart server.")
1251
1298
register_lazy_transport('bzr://',
1252
1299
'bzrlib.transport.remote',
1253
1300
'RemoteTCPTransport')
1301
register_transport_proto('bzr+http://',
1302
# help="Fast access using the Bazaar smart server over HTTP."
1254
1304
register_lazy_transport('bzr+http://',
1255
1305
'bzrlib.transport.remote',
1256
1306
'RemoteHTTPTransport')
1307
register_transport_proto('bzr+ssh://',
1308
help="Fast access using the Bazaar smart server over SSH.")
1257
1309
register_lazy_transport('bzr+ssh://',
1258
1310
'bzrlib.transport.remote',
1259
1311
'RemoteSSHTransport')