https://github.com/python/cpython/commit/0d43164d498224d836bf80ba0098d4ce3cd2e5a7
commit: 0d43164d498224d836bf80ba0098d4ce3cd2e5a7
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: orsenthil <[email protected]>
date: 2026-11-02T08:43:47Z
summary:

[3.15] gh-131178: Add tests for `ftplib` command-line interface (GH-161080) 
(#161154)

* gh-131178: Add tests for ftplib command-line interface

Add unit tests in Lib/test/test_ftplib.py covering the ftplib command-line 
interface: verifying usage message on empty invocation, subprocess invocation, 
host connection with debuglevel, directory and passive mode commands, file 
retrieval, and custom netrc file error handling.

(cherry picked from commit c29f95a98310fb0a8a7d432741d4753872a57d0f)


Co-authored-by: Rudransh Shekhar <[email protected]>
Co-authored-by: Senthil Kumaran <[email protected]>

files:
M Lib/test/test_ftplib.py

diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py
index f1eff9430f7351..a7fc855c383329 100644
--- a/Lib/test/test_ftplib.py
+++ b/Lib/test/test_ftplib.py
@@ -1188,6 +1188,77 @@ def test__all__(self):
         support.check__all__(self, ftplib, not_exported=not_exported)
 
 
+class CommandLineTest(TestCase):
+    """Tests for the ftplib command-line interface."""
+
+    def test_main_no_arguments_prints_usage(self):
+        with mock.patch('sys.argv', ['ftplib']), \
+             support.captured_stdout() as stdout:
+            with self.assertRaises(SystemExit) as cm:
+                ftplib.test()
+            self.assertEqual(cm.exception.code, 0)
+        output = stdout.getvalue()
+        self.assertIn('Usage:', output)
+        self.assertIn('Options:', output)
+        self.assertIn('Commands:', output)
+
+    @requires_subprocess()
+    def test_subprocess_invocation_no_args(self):
+        from test.support.script_helper import assert_python_ok
+        rc, out, err = assert_python_ok('-m', 'ftplib')
+        self.assertEqual(rc, 0)
+        self.assertIn(b'Usage:', out)
+        self.assertIn(b'Options:', out)
+        self.assertIn(b'Commands:', out)
+        self.assertEqual(err, b'')
+
+    @mock.patch('ftplib.FTP')
+    @mock.patch('netrc.netrc', side_effect=OSError)
+    def test_cli_host_and_debugging(self, mock_netrc, mock_ftp_cls):
+        mock_ftp = mock_ftp_cls.return_value
+        with mock.patch('sys.argv', ['ftplib', '-d', '-d', 'example.com']):
+            ftplib.test()
+        mock_ftp_cls.assert_called_once_with('example.com')
+        mock_ftp.set_debuglevel.assert_called_once_with(2)
+        mock_ftp.login.assert_called_once_with('', '', '')
+        mock_ftp.quit.assert_called_once()
+
+    @mock.patch('ftplib.FTP')
+    @mock.patch('netrc.netrc', side_effect=OSError)
+    def test_cli_commands(self, mock_netrc, mock_ftp_cls):
+        mock_ftp = mock_ftp_cls.return_value
+        with mock.patch('sys.argv', ['ftplib', 'example.com', '-l/pub', 
'-d/incoming', '-p']):
+            ftplib.test()
+        mock_ftp_cls.assert_called_once_with('example.com')
+        mock_ftp.dir.assert_called_once_with('/pub')
+        mock_ftp.sendcmd.assert_called_once_with('CWD /incoming')
+        mock_ftp.set_pasv.assert_called_once()
+        mock_ftp.quit.assert_called_once()
+
+    @mock.patch('ftplib.FTP')
+    @mock.patch('netrc.netrc', side_effect=OSError)
+    def test_cli_retrieve_file(self, mock_netrc, mock_ftp_cls):
+        mock_ftp = mock_ftp_cls.return_value
+        with mock.patch('sys.argv', ['ftplib', 'example.com', 
'testfile.txt']), \
+             mock.patch('sys.stdout') as mock_stdout:
+            ftplib.test()
+        mock_ftp.retrbinary.assert_called_once_with(
+            'RETR testfile.txt', mock_stdout.buffer.write, 1024
+        )
+        mock_stdout.buffer.flush.assert_called_once()
+        mock_stdout.flush.assert_called_once()
+        mock_ftp.quit.assert_called_once()
+
+    @mock.patch('ftplib.FTP')
+    @mock.patch('netrc.netrc', side_effect=OSError)
+    def test_cli_custom_rcfile_error(self, mock_netrc, mock_ftp_cls):
+        with mock.patch('sys.argv', ['ftplib', '-rnonexistent.netrc', 
'example.com']), \
+             support.captured_stderr() as stderr:
+            ftplib.test()
+        self.assertIn("Could not open account file -- using anonymous login.",
+                      stderr.getvalue())
+
+
 def setUpModule():
     thread_info = threading_helper.threading_setup()
     unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info)

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to