import subprocess # noqa: F401 import pytest from pandas.io.formats.console import detect_console_encoding from pandas.io.formats.terminal import _get_terminal_size_tput class MockEncoding(object): # TODO(py27): replace with mock """ Used to add a side effect when accessing the 'encoding' property. If the side effect is a str in nature, the value will be returned. Otherwise, the side effect should be an exception that will be raised. """ def __init__(self, encoding): super(MockEncoding, self).__init__() self.val = encoding @property def encoding(self): return self.raise_or_return(self.val) @staticmethod def raise_or_return(val): if isinstance(val, str): return val else: raise val @pytest.mark.parametrize('empty,filled', [ ['stdin', 'stdout'], ['stdout', 'stdin'] ]) def test_detect_console_encoding_from_stdout_stdin(monkeypatch, empty, filled): # Ensures that when sys.stdout.encoding or sys.stdin.encoding is used when # they have values filled. # GH 21552 with monkeypatch.context() as context: context.setattr('sys.{}'.format(empty), MockEncoding('')) context.setattr('sys.{}'.format(filled), MockEncoding(filled)) assert detect_console_encoding() == filled @pytest.mark.parametrize('encoding', [ AttributeError, IOError, 'ascii' ]) def test_detect_console_encoding_fallback_to_locale(monkeypatch, encoding): # GH 21552 with monkeypatch.context() as context: context.setattr('locale.getpreferredencoding', lambda: 'foo') context.setattr('sys.stdout', MockEncoding(encoding)) assert detect_console_encoding() == 'foo' @pytest.mark.parametrize('std,locale', [ ['ascii', 'ascii'], ['ascii', Exception], [AttributeError, 'ascii'], [AttributeError, Exception], [IOError, 'ascii'], [IOError, Exception] ]) def test_detect_console_encoding_fallback_to_default(monkeypatch, std, locale): # When both the stdout/stdin encoding and locale preferred encoding checks # fail (or return 'ascii', we should default to the sys default encoding. # GH 21552 with monkeypatch.context() as context: context.setattr( 'locale.getpreferredencoding', lambda: MockEncoding.raise_or_return(locale) ) context.setattr('sys.stdout', MockEncoding(std)) context.setattr('sys.getdefaultencoding', lambda: 'sysDefaultEncoding') assert detect_console_encoding() == 'sysDefaultEncoding' @pytest.mark.parametrize("size", ['', ['']]) def test_terminal_unknown_dimensions(monkeypatch, size, mocker): def communicate(*args, **kwargs): return size monkeypatch.setattr('subprocess.Popen', mocker.Mock()) monkeypatch.setattr('subprocess.Popen.return_value.returncode', None) monkeypatch.setattr( 'subprocess.Popen.return_value.communicate', communicate) result = _get_terminal_size_tput() assert result is None