Index: Lib/ftplib.py =================================================================== --- Lib/ftplib.py (révision 68762) +++ Lib/ftplib.py (copie de travail) @@ -117,6 +117,28 @@ if user: self.login(user, passwd, acct) + def __enter__(self): + """Context management protocol. Returns self.""" + return self + + def __exit__(self, *args): + """Context management protocol. + + Will try to quit() if active, then close(). + If not active, a simple close() call is made. + """ + if self.sock is not None and self.getwelcome() is not None: + try: + self.quit() + except socket.error, e: + self.close() + # [Errno 61] is Connection refused + # if the error is different, we want to raise it. + if e.errno != 61: + raise + else: + self.close() + def connect(self, host='', port=0, timeout=-999): '''Connect to host. Arguments are: - host: hostname to connect to (string, default previous host) Index: Lib/test/test_ftplib.py =================================================================== --- Lib/test/test_ftplib.py (révision 68762) +++ Lib/test/test_ftplib.py (copie de travail) @@ -361,7 +361,34 @@ # IPv4 is in use, just make sure send_epsv has not been used self.assertEqual(self.server.handler.last_received_cmd, 'pasv') + def test_with_statement(self): + # simplest block + with ftplib.FTP(timeout=2) as ftp: + pass + server = DummyFTPServer((HOST, 0)) + server.start() + try: + # now let's do a bit of work + with ftplib.FTP(timeout=2) as ftp: + ftp.connect(server.host, server.port) + ftp.voidcmd('echo 200') + ftp.voidcmd('echo 299') + self.assertRaises(ftplib.error_reply, ftp.voidcmd, 'echo 199') + self.assertRaises(ftplib.error_reply, ftp.voidcmd, 'echo 300') + finally: + server.stop() + + server = DummyFTPServer((HOST, 0)) + server.start() + try: + # let's see what happens if already quit + with ftplib.FTP(timeout=2) as ftp: + ftp.connect(server.host, server.port) + ftp.quit() + finally: + server.stop() + class TestIPv6Environment(TestCase): def setUp(self):