/breezy/unstable

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy/unstable

« back to all changes in this revision

Viewing changes to breezy/transport/ftp/__init__.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-24 01:39:33 UTC
  • mfrom: (3815.3776.6)
  • Revision ID: jelmer@jelmer.uk-20170524013933-ir4y4tqtrsiz2ka2
New upstream snapshot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
from __future__ import absolute_import
29
29
 
30
 
from cStringIO import StringIO
31
30
import ftplib
32
31
import getpass
33
32
import os
36
35
import stat
37
36
import time
38
37
 
39
 
from bzrlib import (
 
38
from ... import (
40
39
    config,
41
40
    errors,
42
41
    osutils,
43
42
    urlutils,
44
43
    )
45
 
from bzrlib.symbol_versioning import (
 
44
from ...sixish import (
 
45
    BytesIO,
 
46
    )
 
47
from ...symbol_versioning import (
46
48
    DEPRECATED_PARAMETER,
47
49
    deprecated_in,
48
50
    deprecated_passed,
49
51
    warn,
50
52
    )
51
 
from bzrlib.trace import mutter, warning
52
 
from bzrlib.transport import (
 
53
from ...trace import mutter, warning
 
54
from ...transport import (
53
55
    AppendBasedFileStream,
54
56
    ConnectedTransport,
55
57
    _file_streams,
150
152
            connection.set_pasv(not self.is_active)
151
153
            # binary mode is the default
152
154
            connection.voidcmd('TYPE I')
153
 
        except socket.error, e:
 
155
        except socket.error as e:
154
156
            raise errors.SocketConnectionError(self._host, self._port,
155
157
                                               msg='Unable to connect to',
156
158
                                               orig_error= e)
157
 
        except ftplib.error_perm, e:
 
159
        except ftplib.error_perm as e:
158
160
            raise errors.TransportError(msg="Error setting up connection:"
159
161
                                        " %s" % str(e), orig_error=e)
160
162
        return connection, (user, password)
179
181
 
180
182
    def _translate_ftp_error(self, err, path, extra=None,
181
183
                              unknown_exc=FtpPathError):
182
 
        """Try to translate an ftplib exception to a bzrlib exception.
 
184
        """Try to translate an ftplib exception to a breezy exception.
183
185
 
184
186
        :param err: The error to translate into a bzr error
185
187
        :param path: The path which had problems
241
243
            s = f.size(abspath)
242
244
            mutter("FTP has: %s", abspath)
243
245
            return True
244
 
        except ftplib.error_perm, e:
 
246
        except ftplib.error_perm as e:
245
247
            if ('is a directory' in str(e).lower()):
246
248
                mutter("FTP has dir: %s: %s", abspath, e)
247
249
                return True
256
258
                        for this operation.
257
259
 
258
260
        We're meant to return a file-like object which bzr will
259
 
        then read from. For now we do this via the magic of StringIO
 
261
        then read from. For now we do this via the magic of BytesIO
260
262
        """
261
263
        try:
262
264
            mutter("FTP get: %s", self._remote_path(relpath))
263
265
            f = self._get_FTP()
264
 
            ret = StringIO()
 
266
            ret = BytesIO()
265
267
            f.retrbinary('RETR '+self._remote_path(relpath), ret.write, 8192)
266
268
            ret.seek(0)
267
269
            return ret
268
 
        except ftplib.error_perm, e:
 
270
        except ftplib.error_perm as e:
269
271
            raise errors.NoSuchFile(self.abspath(relpath), extra=str(e))
270
 
        except ftplib.error_temp, e:
 
272
        except ftplib.error_temp as e:
271
273
            if retries > _number_of_retries:
272
274
                raise errors.TransportError(msg="FTP temporary error during GET %s. Aborting."
273
275
                                     % self.abspath(relpath),
276
278
                warning("FTP temporary error: %s. Retrying.", str(e))
277
279
                self._reconnect()
278
280
                return self.get(relpath, retries+1)
279
 
        except EOFError, e:
 
281
        except EOFError as e:
280
282
            if retries > _number_of_retries:
281
283
                raise errors.TransportError("FTP control connection closed during GET %s."
282
284
                                     % self.abspath(relpath),
305
307
        if getattr(fp, 'read', None) is None:
306
308
            # hand in a string IO
307
309
            bytes = fp
308
 
            fp = StringIO(bytes)
 
310
            fp = BytesIO(bytes)
309
311
        else:
310
312
            # capture the byte count; .read() may be read only so
311
313
            # decorate it.
329
331
                    return len(bytes)
330
332
                else:
331
333
                    return fp.counted_bytes
332
 
            except (ftplib.error_temp, EOFError), e:
 
334
            except (ftplib.error_temp, EOFError) as e:
333
335
                warning("Failure during ftp PUT of %s: %s. Deleting temporary file."
334
336
                    % (tmp_abspath, e, ))
335
337
                try:
339
341
                            " server.\nFile: %s", tmp_abspath)
340
342
                    raise e
341
343
                raise
342
 
        except ftplib.error_perm, e:
 
344
        except ftplib.error_perm as e:
343
345
            self._translate_ftp_error(e, abspath, extra='could not store',
344
346
                                       unknown_exc=errors.NoSuchFile)
345
 
        except ftplib.error_temp, e:
 
347
        except ftplib.error_temp as e:
346
348
            if retries > _number_of_retries:
347
349
                raise errors.TransportError(
348
350
                    "FTP temporary error during PUT %s: %s. Aborting."
369
371
            f = self._get_FTP()
370
372
            try:
371
373
                f.mkd(abspath)
372
 
            except ftplib.error_reply, e:
 
374
            except ftplib.error_reply as e:
373
375
                # <https://bugs.launchpad.net/bzr/+bug/224373> Microsoft FTP
374
376
                # server returns "250 Directory created." which is kind of
375
377
                # reasonable, 250 meaning "requested file action OK", but not what
379
381
                else:
380
382
                    raise
381
383
            self._setmode(relpath, mode)
382
 
        except ftplib.error_perm, e:
 
384
        except ftplib.error_perm as e:
383
385
            self._translate_ftp_error(e, abspath,
384
386
                unknown_exc=errors.FileExists)
385
387
 
405
407
            mutter("FTP rmd: %s", abspath)
406
408
            f = self._get_FTP()
407
409
            f.rmd(abspath)
408
 
        except ftplib.error_perm, e:
 
410
        except ftplib.error_perm as e:
409
411
            self._translate_ftp_error(e, abspath, unknown_exc=errors.PathError)
410
412
 
411
413
    def append_file(self, relpath, f, mode=None):
444
446
            conn.close()
445
447
            self._setmode(relpath, mode)
446
448
            ftp.getresp()
447
 
        except ftplib.error_perm, e:
 
449
        except ftplib.error_perm as e:
448
450
            # Check whether the command is not supported (reply code 502)
449
451
            if str(e).startswith('502 '):
450
452
                warning("FTP server does not support file appending natively. "
454
456
            else:
455
457
                self._translate_ftp_error(e, abspath, extra='error appending',
456
458
                    unknown_exc=errors.NoSuchFile)
457
 
        except ftplib.error_temp, e:
 
459
        except ftplib.error_temp as e:
458
460
            if retries > _number_of_retries:
459
461
                raise errors.TransportError(
460
462
                    "FTP temporary error during APPEND %s. Aborting."
485
487
                cmd = "SITE CHMOD %s %s" % (oct(mode),
486
488
                                            self._remote_path(relpath))
487
489
                ftp.sendcmd(cmd)
488
 
            except ftplib.error_perm, e:
 
490
            except ftplib.error_perm as e:
489
491
                # Command probably not available on this server
490
492
                warning("FTP Could not set permissions to %s on %s. %s",
491
493
                        oct(mode), self._remote_path(relpath), str(e))
505
507
    def _rename(self, abs_from, abs_to, f):
506
508
        try:
507
509
            f.rename(abs_from, abs_to)
508
 
        except (ftplib.error_temp, ftplib.error_perm), e:
 
510
        except (ftplib.error_temp, ftplib.error_perm) as e:
509
511
            self._translate_ftp_error(e, abs_from,
510
512
                ': unable to rename to %r' % (abs_to))
511
513
 
517
519
            mutter("FTP mv: %s => %s", abs_from, abs_to)
518
520
            f = self._get_FTP()
519
521
            self._rename_and_overwrite(abs_from, abs_to, f)
520
 
        except ftplib.error_perm, e:
 
522
        except ftplib.error_perm as e:
521
523
            self._translate_ftp_error(e, abs_from,
522
524
                extra='unable to rename to %r' % (rel_to,),
523
525
                unknown_exc=errors.PathError)
541
543
        try:
542
544
            mutter("FTP rm: %s", abspath)
543
545
            f.delete(abspath)
544
 
        except ftplib.error_perm, e:
 
546
        except ftplib.error_perm as e:
545
547
            self._translate_ftp_error(e, abspath, 'error deleting',
546
548
                unknown_exc=errors.NoSuchFile)
547
549
 
548
550
    def external_url(self):
549
 
        """See bzrlib.transport.Transport.external_url."""
 
551
        """See breezy.transport.Transport.external_url."""
550
552
        # FTP URL's are externally usable.
551
553
        return self.base
552
554
 
562
564
        try:
563
565
            try:
564
566
                paths = f.nlst(basepath)
565
 
            except ftplib.error_perm, e:
 
567
            except ftplib.error_perm as e:
566
568
                self._translate_ftp_error(e, relpath,
567
569
                                           extra='error with list_dir')
568
 
            except ftplib.error_temp, e:
 
570
            except ftplib.error_temp as e:
569
571
                # xs4all's ftp server raises a 450 temp error when listing an
570
572
                # empty directory. Check for that and just return an empty list
571
573
                # in that case. See bug #215522
611
613
            mutter("FTP stat: %s", abspath)
612
614
            f = self._get_FTP()
613
615
            return FtpStatResult(f, abspath)
614
 
        except ftplib.error_perm, e:
 
616
        except ftplib.error_perm as e:
615
617
            self._translate_ftp_error(e, abspath, extra='error w/ stat')
616
618
 
617
619
    def lock_read(self, relpath):
638
640
 
639
641
def get_test_permutations():
640
642
    """Return the permutations to be used in testing."""
641
 
    from bzrlib.tests import ftp_server
 
643
    from ...tests import ftp_server
642
644
    return [(FtpTransport, ftp_server.FTPTestServer)]