Changeset 1:e93155993afc for ftputil.py
- Timestamp:
- 2002-01-13 01:08:26 (9 years ago)
- Branch:
- default
- convert_revision:
- svn:778c30c8-61e0-0310-89d4-fe2f97a467b2/trunk@2
- Files:
-
- 1 modified
-
ftputil.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ftputil.py
r0 r1 31 31 32 32 import ftplib 33 import cStringIO 33 34 34 35 35 class FTPIOError(IOError): 36 pass 36 def __init__(self, msg, ftp_exception=None): 37 self.ftp_exception = ftp_exception 38 IOError(self, msg) 39 37 40 38 41 class _FTPFile: 39 42 '''Represents a file-like object connected to an 40 FTP host.''' 43 FTP host. File and socket are closed appropriately if 44 the close operation is requested.''' 41 45 42 def __init__(self, host, path):46 def __init__(self, conn, mode): 43 47 '''Construct the file(-like) object.''' 44 self._host = host 45 self._path = path 46 self.closed = 0 48 self._conn = conn 49 # this should be returned if someone asks 50 self.mode = mode 51 self._binary = 'b' in mode 52 if mode == 'r': 53 # the FTP server ensures the correct mode via 54 # the previous TYPE command 55 mode = 'rb' 56 self._fp = conn.makefile(mode) 47 57 48 def read(self, bytes=None): 49 '''Return 'bytes' bytes from the file object, or up 50 to EOF if the argument is not provided.''' 51 pass 58 def _normalize_linefeeds(text): 59 r'''Return data with occurences of \r removed.''' 60 return data.replace('\r', '') 52 61 53 def readline(self): 54 '''Return a single line from the file object.''' 55 pass 62 def read(self, *args, **kwargs): 63 '''Return read bytes, normalized if in ASCII 64 transfer mode.''' 65 text = apply(self._fp.read, args, kwargs) 66 if self._binary: 67 return text 68 else: 69 return self._normalize_linefeeds(text) 56 70 57 def readlines(self): 58 '''Return a list of lines until EOF.''' 59 pass 71 def readlines(self, *args, **kwargs): 72 '''Return read lines, normalized if in ASCII 73 transfer mode.''' 74 lines = apply(self._fp.readlines, args, kwargs) 75 return [self._normalize_linefeeds(line) 76 for line in lines] 77 78 def __getattr__(self, attr_name): 79 '''Delegate unknown attribute requests to the file.''' 80 if attr_name in ( 'flush isatty fileno read readline ' 81 'readlines xreadlines seek tell truncate write ' 82 'writelines closed name softspace'.split() ): 83 return eval('self._fp.%s' % attr_name) 84 else: 85 raise AttributeError("'FTPFile' object has no " 86 "attribute '%s'" % attr_name) 87 88 def close(self): 89 '''Close the FTPFile. We need no 'if'; the file and the 90 socket object can be closed multiply without harm.''' 91 self._fp.close() 92 self._conn.close() 60 93 61 def write(self, data): 62 '''Write a data string to the file.''' 63 pass 94 def __del__(self): 95 # not strictly necessary; file and socket are 96 # closed on garbage collection, anyway 97 self.close() 64 98 65 def writelines(self, data):66 '''Write a list of strings to the file object.'''67 pass68 99 69 def close(self):70 if not self.closed:71 # what will we do?72 pass73 74 75 100 class FTPHost: 76 101 '''FTP host class''' … … 80 105 stage I don't know if I need a new FTP connection for 81 106 each file transfer.''' 82 self._hostname = host 107 self._hostname = hostname 83 108 self._user = user 84 109 self._password = password 85 self._host = ftplib.FTP(hostnam me, user, password)110 self._host = ftplib.FTP(hostname, user, password) 86 111 87 112 def file(self, path, mode='r'): 88 '''Return a file -like object that is connected to113 '''Return a file(-like) object that is connected to an 89 114 FTP host.''' 90 # we don't support append modes 91 assert '+' not in mode 92 if 'r' in mode: 93 # read modes 94 if 'b' in mode: 95 # open for binary reading 96 else: 97 # open for ASCII reading 98 elif 'w' in mode: 99 # write modes 100 if 'b' in mode: 101 # open for binary writing 102 else: 103 # open for ASCII writing 115 if '+' in mode: 116 raise FTPIOError("append modes not supported") 117 if mode not in ( 'r rb br w wb bw'.split() ): 118 raise FTPIOError("invalid mode") 119 # select ASCII or binary mode 120 transfer_type = ('A', 'I')['b' in mode] 121 command = 'TYPE %s' % transfer_type 122 # logic taken from ftplib; 123 # why this strange distinction? 124 if mode == 'r': 125 self._host.sendcmd(command) 126 else: 127 self._host.voidcmd(command) 128 # make transfer command 129 command_type = ('STOR', 'RETR')['r' in mode] 130 command = '%s %s' % (command_type, path) 131 # get connection and file object 132 conn = self._host.transfercmd(command) 133 self._host.voidresp() 134 ftp_file = _FTPFile(conn, mode) 135 return ftp_file 104 136
