diff options
| author | Barry Warsaw | 2016-04-08 22:45:36 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2016-04-08 22:45:36 -0400 |
| commit | b0b36f18f86be2c8a8a443bf425ad4114c53c06e (patch) | |
| tree | ff34562b3f050c8dc4ccd3c82153d667248e2829 /src/mailman/utilities | |
| parent | 29da358eb0c92ba94d417736927060411c4264f8 (diff) | |
| download | mailman-b0b36f18f86be2c8a8a443bf425ad4114c53c06e.tar.gz mailman-b0b36f18f86be2c8a8a443bf425ad4114c53c06e.tar.zst mailman-b0b36f18f86be2c8a8a443bf425ad4114c53c06e.zip | |
Diffstat (limited to 'src/mailman/utilities')
| -rw-r--r-- | src/mailman/utilities/interact.py | 10 | ||||
| -rw-r--r-- | src/mailman/utilities/tests/test_interact.py | 99 |
2 files changed, 103 insertions, 6 deletions
diff --git a/src/mailman/utilities/interact.py b/src/mailman/utilities/interact.py index d74cd8af7..3c38b02aa 100644 --- a/src/mailman/utilities/interact.py +++ b/src/mailman/utilities/interact.py @@ -24,7 +24,7 @@ import code from mailman import public -DEFAULT_BANNER = '' +DEFAULT_BANNER = object() @public @@ -33,7 +33,7 @@ def interact(upframe=True, banner=DEFAULT_BANNER, overrides=None): :param upframe: Whether or not to populate the interpreter's globals with the locals from the frame that called this function. - :type upfframe: bool + :type upframe: bool :param banner: The banner to print before the interpreter starts. :type banner: string :param overrides: Additional interpreter globals to add. @@ -61,13 +61,11 @@ def interact(upframe=True, banner=DEFAULT_BANNER, overrides=None): startup = os.environ.get('PYTHONSTARTUP') if startup: with open(startup, 'r', encoding='utf-8') as fp: - interp.runsource(fp.read(), startup) + interp.runcode(compile(fp.read(), startup, 'exec')) # We don't want the funky console object in parentheses in the banner. - if banner == DEFAULT_BANNER: + if banner is DEFAULT_BANNER: banner = '''\ Python %s on %s Type "help", "copyright", "credits" or "license" for more information.''' % ( sys.version, sys.platform) - elif not banner: - banner = None interp.interact(banner) diff --git a/src/mailman/utilities/tests/test_interact.py b/src/mailman/utilities/tests/test_interact.py new file mode 100644 index 000000000..65a1155fb --- /dev/null +++ b/src/mailman/utilities/tests/test_interact.py @@ -0,0 +1,99 @@ +# Copyright (C) 2016 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. + +"""Test the interact utility.""" + + +import sys +import unittest + +from contextlib import ExitStack +from io import StringIO +from mailman.app.lifecycle import create_list +from mailman.testing.helpers import hackenv +from mailman.testing.layers import ConfigLayer +from mailman.utilities.interact import interact +from tempfile import NamedTemporaryFile +from unittest.mock import patch + + +class TestInteract(unittest.TestCase): + layer = ConfigLayer + + def setUp(self): + resources = ExitStack() + self.addCleanup(resources.close) + self._enter = resources.enter_context + self._enter(patch('code.input', side_effect=EOFError)) + self._stderr = StringIO() + self._enter(patch('sys.stderr', self._stderr)) + + def test_interact(self): + mlist = create_list('ant@example.com') + results = [] + fp = self._enter(NamedTemporaryFile('w', encoding='utf-8')) + self._enter(hackenv('PYTHONSTARTUP', fp.name)) + print('results.append(mlist.list_id)', file=fp) + fp.flush() + interact() + self.assertEqual(results, [mlist.list_id]) + + def test_interact_overrides(self): + create_list('ant@example.com') + bee = create_list('bee@example.com') + results = [] + fp = self._enter(NamedTemporaryFile('w', encoding='utf-8')) + self._enter(hackenv('PYTHONSTARTUP', fp.name)) + print('results.append(mlist.list_id)', file=fp) + fp.flush() + interact(overrides=dict(mlist=bee)) + self.assertEqual(results, [bee.list_id]) + + def test_interact_default_banner(self): + self._enter(hackenv('PYTHONSTARTUP', None)) + interact() + stderr = self._stderr.getvalue().splitlines() + banner = 'Python {} on {} '.format(sys.version, sys.platform) + self.assertEqual(stderr[0], banner.splitlines()[0]) + + def test_interact_custom_banner(self): + self._enter(hackenv('PYTHONSTARTUP', None)) + interact(banner='Welcome') + stderr = self._stderr.getvalue().splitlines() + self.assertEqual(stderr[0], 'Welcome') + + def test_interact_no_upframe(self): + upframed = False # noqa + fp = self._enter(NamedTemporaryFile('w', encoding='utf-8')) + self._enter(hackenv('PYTHONSTARTUP', fp.name)) + print('print(upframed)', file=fp) + fp.flush() + interact(upframe=False, banner='') + lines = self._stderr.getvalue().splitlines() + self.assertIn("NameError: name 'upframed' is not defined", lines) + + def test_interact_multiline(self): + # GL issue #224. + fp = self._enter(NamedTemporaryFile('w', encoding='utf-8')) + self._enter(hackenv('PYTHONSTARTUP', fp.name)) + print('import sys', file=fp) + print("print('hello', file=sys.stderr)", file=fp) + print("print('world', file=sys.stderr)", file=fp) + fp.flush() + interact(banner='') + lines = self._stderr.getvalue() + self.assertEqual(lines, 'hello\nworld\n\n', lines) |
