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]
