Skip to content

Commit

Permalink
Fixed #23930 -- Added copies of captured_std* managers from CPython's…
Browse files Browse the repository at this point in the history
… test.support.

StringIO import was adapted for compatibility with Python 2.
  • Loading branch information
wrwrwr authored and timgraham committed Nov 29, 2014
1 parent c8dcded commit 6dbe979
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 60 deletions.
48 changes: 48 additions & 0 deletions django/test/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,3 +493,51 @@ def extend_sys_path(*paths):
yield
finally:
sys.path = _orig_sys_path


@contextmanager
def captured_output(stream_name):
"""Return a context manager used by captured_stdout/stdin/stderr
that temporarily replaces the sys stream *stream_name* with a StringIO.
Note: This function and the following ``captured_std*`` are copied
from CPython's ``test.support`` module."""
orig_stdout = getattr(sys, stream_name)
setattr(sys, stream_name, six.StringIO())
try:
yield getattr(sys, stream_name)
finally:
setattr(sys, stream_name, orig_stdout)


def captured_stdout():
"""Capture the output of sys.stdout:
with captured_stdout() as stdout:
print("hello")
self.assertEqual(stdout.getvalue(), "hello\n")
"""
return captured_output("stdout")


def captured_stderr():
"""Capture the output of sys.stderr:
with captured_stderr() as stderr:
print("hello", file=sys.stderr)
self.assertEqual(stderr.getvalue(), "hello\n")
"""
return captured_output("stderr")


def captured_stdin():
"""Capture the input to sys.stdin:
with captured_stdin() as stdin:
stdin.write('hello\n')
stdin.seek(0)
# call test code that consumes from sys.stdin
captured = input()
self.assertEqual(captured, "hello")
"""
return captured_output("stdin")
17 changes: 7 additions & 10 deletions tests/bash_completion/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from django.apps import apps
from django.core.management import ManagementUtility
from django.utils.six import StringIO
from django.test.utils import captured_stdout


class BashCompletionTests(unittest.TestCase):
Expand All @@ -20,12 +20,8 @@ class BashCompletionTests(unittest.TestCase):
def setUp(self):
self.old_DJANGO_AUTO_COMPLETE = os.environ.get('DJANGO_AUTO_COMPLETE')
os.environ['DJANGO_AUTO_COMPLETE'] = '1'
self.output = StringIO()
self.old_stdout = sys.stdout
sys.stdout = self.output

def tearDown(self):
sys.stdout = self.old_stdout
if self.old_DJANGO_AUTO_COMPLETE:
os.environ['DJANGO_AUTO_COMPLETE'] = self.old_DJANGO_AUTO_COMPLETE
else:
Expand Down Expand Up @@ -53,11 +49,12 @@ def _user_input(self, input_str):

def _run_autocomplete(self):
util = ManagementUtility(argv=sys.argv)
try:
util.autocomplete()
except SystemExit:
pass
return self.output.getvalue().strip().split('\n')
with captured_stdout() as stdout:
try:
util.autocomplete()
except SystemExit:
pass
return stdout.getvalue().strip().split('\n')

def test_django_admin_py(self):
"django_admin.py will autocomplete option flags"
Expand Down
20 changes: 7 additions & 13 deletions tests/contenttypes_tests/tests.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import sys

from django.apps.registry import Apps, apps
from django.contrib.contenttypes.fields import (
GenericForeignKey, GenericRelation
Expand All @@ -12,9 +10,8 @@
from django.core import checks
from django.db import connections, models, router
from django.test import TestCase
from django.test.utils import override_settings
from django.test.utils import captured_stdout, override_settings
from django.utils.encoding import force_str
from django.utils.six import StringIO

from .models import Author, Article, SchemeIncludedURL

Expand Down Expand Up @@ -369,29 +366,26 @@ def setUp(self):
self.before_count = ContentType.objects.count()
ContentType.objects.create(name='fake', app_label='contenttypes_tests', model='Fake')
self.app_config = apps.get_app_config('contenttypes_tests')
self.old_stdout = sys.stdout
sys.stdout = StringIO()

def tearDown(self):
sys.stdout = self.old_stdout

def test_interactive_true(self):
"""
interactive mode of update_contenttypes() (the default) should delete
stale contenttypes.
"""
management.input = lambda x: force_str("yes")
management.update_contenttypes(self.app_config)
self.assertIn("Deleting stale content type", sys.stdout.getvalue())
with captured_stdout() as stdout:
management.update_contenttypes(self.app_config)
self.assertIn("Deleting stale content type", stdout.getvalue())
self.assertEqual(ContentType.objects.count(), self.before_count)

def test_interactive_false(self):
"""
non-interactive mode of update_contenttypes() shouldn't delete stale
content types.
"""
management.update_contenttypes(self.app_config, interactive=False)
self.assertIn("Stale content types remain.", sys.stdout.getvalue())
with captured_stdout() as stdout:
management.update_contenttypes(self.app_config, interactive=False)
self.assertIn("Stale content types remain.", stdout.getvalue())
self.assertEqual(ContentType.objects.count(), self.before_count + 1)


Expand Down
8 changes: 2 additions & 6 deletions tests/i18n/test_compilation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import os
import shutil
import stat
import sys
import unittest
import gettext as gettext_module

from django.core.management import call_command, CommandError, execute_from_command_line
from django.core.management.utils import find_command
from django.test import SimpleTestCase
from django.test import override_settings
from django.test.utils import captured_stderr, captured_stdout
from django.utils import translation
from django.utils.translation import ugettext
from django.utils.encoding import force_text
Expand Down Expand Up @@ -145,15 +145,11 @@ def setUp(self):
self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale'))

def test_command_help(self):
old_stdout, old_stderr = sys.stdout, sys.stderr
sys.stdout, sys.stderr = StringIO(), StringIO()
try:
with captured_stdout(), captured_stderr():
# `call_command` bypasses the parser; by calling
# `execute_from_command_line` with the help subcommand we
# ensure that there are no issues with the parser itself.
execute_from_command_line(['django-admin', 'help', 'compilemessages'])
finally:
sys.stdout, sys.stderr = old_stdout, old_stderr

def test_one_locale_excluded(self):
call_command('compilemessages', exclude=['it'], stdout=StringIO())
Expand Down
8 changes: 2 additions & 6 deletions tests/i18n/test_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import os
import re
import shutil
import sys
import time
from unittest import SkipTest, skipUnless
import warnings
Expand All @@ -16,6 +15,7 @@
from django.core.management.utils import find_command
from django.test import SimpleTestCase
from django.test import override_settings
from django.test.utils import captured_stderr, captured_stdout
from django.utils.encoding import force_text
from django.utils._os import upath
from django.utils import six
Expand Down Expand Up @@ -632,15 +632,11 @@ def setUp(self):
self.addCleanup(self._rmrf, os.path.join(self.test_dir, 'locale'))

def test_command_help(self):
old_stdout, old_stderr = sys.stdout, sys.stderr
sys.stdout, sys.stderr = StringIO(), StringIO()
try:
with captured_stdout(), captured_stderr():
# `call_command` bypasses the parser; by calling
# `execute_from_command_line` with the help subcommand we
# ensure that there are no issues with the parser itself.
execute_from_command_line(['django-admin', 'help', 'makemessages'])
finally:
sys.stdout, sys.stderr = old_stdout, old_stderr

def test_one_locale_excluded(self):
management.call_command('makemessages', exclude=['it'], stdout=StringIO())
Expand Down
13 changes: 4 additions & 9 deletions tests/servers/test_basehttp.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import sys

from django.core.handlers.wsgi import WSGIRequest
from django.core.servers.basehttp import WSGIRequestHandler
from django.test import TestCase
from django.test.client import RequestFactory
from django.utils.six import BytesIO, StringIO
from django.test.utils import captured_stderr
from django.utils.six import BytesIO


class WSGIRequestHandlerTestCase(TestCase):
Expand All @@ -14,14 +13,10 @@ def test_https(self):

handler = WSGIRequestHandler(request, '192.168.0.2', None)

_stderr = sys.stderr
sys.stderr = StringIO()
try:
with captured_stderr() as stderr:
handler.log_message("GET %s %s", str('\x16\x03'), "4")
self.assertIn(
"You're accessing the developement server over HTTPS, "
"but it only supports HTTP.",
sys.stderr.getvalue()
stderr.getvalue()
)
finally:
sys.stderr = _stderr
22 changes: 6 additions & 16 deletions tests/user_commands/tests.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import os
import sys
import warnings

from django.db import connection
from django.core import management
from django.core.management import BaseCommand, CommandError
from django.core.management.utils import find_command, popen_wrapper
from django.test import SimpleTestCase
from django.test.utils import captured_stderr, captured_stdout
from django.utils import translation
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.six import StringIO
Expand Down Expand Up @@ -42,14 +42,9 @@ def test_system_exit(self):
"""
with self.assertRaises(CommandError):
management.call_command('dance', example="raise")
old_stderr = sys.stderr
sys.stderr = err = StringIO()
try:
with self.assertRaises(SystemExit):
management.ManagementUtility(['manage.py', 'dance', '--example=raise']).execute()
finally:
sys.stderr = old_stderr
self.assertIn("CommandError", err.getvalue())
with captured_stderr() as stderr, self.assertRaises(SystemExit):
management.ManagementUtility(['manage.py', 'dance', '--example=raise']).execute()
self.assertIn("CommandError", stderr.getvalue())

def test_default_en_us_locale_set(self):
# Forces en_us when set to true
Expand Down Expand Up @@ -100,14 +95,9 @@ def test_optparse_compatibility(self):
self.assertEqual(out.getvalue(), "All right, let's dance Rock'n'Roll.\n")

# Simulate command line execution
old_stdout, old_stderr = sys.stdout, sys.stderr
sys.stdout, sys.stderr = StringIO(), StringIO()
try:
with captured_stdout() as stdout, captured_stderr():
management.execute_from_command_line(['django-admin', 'optparse_cmd'])
finally:
output = sys.stdout.getvalue()
sys.stdout, sys.stderr = old_stdout, old_stderr
self.assertEqual(output, "All right, let's dance Rock'n'Roll.\n")
self.assertEqual(stdout.getvalue(), "All right, let's dance Rock'n'Roll.\n")

def test_calling_a_command_with_only_empty_parameter_should_ends_gracefully(self):
out = StringIO()
Expand Down

0 comments on commit 6dbe979

Please sign in to comment.