215
214
(other.start, other.length, other.ranges))
217
class LateReadError(object):
218
"""A helper for transports which pretends to be a readable file.
220
When read() is called, errors.ReadError is raised.
223
def __init__(self, path):
227
"""a no-op - do nothing."""
230
"""Raise ReadError."""
231
raise errors.ReadError(self._path)
236
def read(self, count=-1):
218
243
class Transport(object):
219
244
"""This class encapsulates methods for retrieving or putting a file
220
245
from/to a storage location.
473
498
def get(self, relpath):
474
499
"""Get the file at the given relative path.
501
This may fail in a number of ways:
502
- HTTP servers may return content for a directory. (unexpected
504
- FTP servers may indicate NoSuchFile for a directory.
505
- SFTP servers may give a file handle for a directory that will
508
For correct use of the interface, be sure to catch errors.PathError
509
when calling it and catch errors.ReadError when reading from the
476
512
:param relpath: The relative path to the file
477
513
:rtype: File-like object.
575
611
:param fudge_factor: All transports have some level of 'it is
576
612
better to read some more data and throw it away rather
577
613
than seek', so collapse if we are 'close enough'
578
:return: yield _CoalescedOffset objects, which have members for wher
614
:return: yield _CoalescedOffset objects, which have members for where
579
615
to start, how much to read, and how to split those
1177
1213
raise NotImplementedError
1180
class TransportTestProviderAdapter(object):
1181
"""A tool to generate a suite testing all transports for a single test.
1183
This is done by copying the test once for each transport and injecting
1184
the transport_class and transport_server classes into each copy. Each copy
1185
is also given a new id() to make it easy to identify.
1188
def adapt(self, test):
1189
result = unittest.TestSuite()
1190
for klass, server_factory in self._test_permutations():
1191
new_test = deepcopy(test)
1192
new_test.transport_class = klass
1193
new_test.transport_server = server_factory
1194
def make_new_test_id():
1195
new_id = "%s(%s)" % (new_test.id(), server_factory.__name__)
1196
return lambda: new_id
1197
new_test.id = make_new_test_id()
1198
result.addTest(new_test)
1201
def get_transport_test_permutations(self, module):
1202
"""Get the permutations module wants to have tested."""
1203
if getattr(module, 'get_test_permutations', None) is None:
1204
raise AssertionError("transport module %s doesn't provide get_test_permutations()"
1206
##warning("transport module %s doesn't provide get_test_permutations()"
1207
## % module.__name__)
1209
return module.get_test_permutations()
1211
def _test_permutations(self):
1212
"""Return a list of the klass, server_factory pairs to test."""
1214
for module in _get_transport_modules():
1216
result.extend(self.get_transport_test_permutations(reduce(getattr,
1217
(module).split('.')[1:],
1218
__import__(module))))
1219
except errors.DependencyNotPresent, e:
1220
# Continue even if a dependency prevents us
1221
# from running this test
1226
1216
class TransportLogger(object):
1227
1217
"""Adapt a transport to get clear logging data on api calls.
1304
1294
# help="This modifier converts any transport to be readonly."
1306
1296
register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')
1307
1298
register_transport_proto('fakenfs+')
1308
1299
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
1301
register_transport_proto('brokenrename+')
1302
register_lazy_transport('brokenrename+', 'bzrlib.transport.brokenrename',
1303
'BrokenRenameTransportDecorator')
1309
1305
register_transport_proto('vfat+')
1310
1306
register_lazy_transport('vfat+',
1311
1307
'bzrlib.transport.fakevfat',