diff -r 15b20201cfa5 Lib/shutil.py --- a/Lib/shutil.py Tue Apr 19 23:37:17 2016 +0300 +++ b/Lib/shutil.py Wed Apr 20 00:14:52 2016 +0300 @@ -1072,7 +1072,7 @@ def get_terminal_size(fallback=(80, 24)) if columns <= 0 or lines <= 0: try: size = os.get_terminal_size(sys.__stdout__.fileno()) - except (AttributeError, OSError): + except (AttributeError, ValueError, OSError): size = os.terminal_size(fallback) if columns <= 0: columns = size.columns diff -r 15b20201cfa5 Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py Tue Apr 19 23:37:17 2016 +0300 +++ b/Lib/test/test_shutil.py Wed Apr 20 00:14:52 2016 +0300 @@ -1836,6 +1836,14 @@ class TermsizeTests(unittest.TestCase): size = shutil.get_terminal_size() self.assertEqual(size.lines, 888) + def test_bad_environ(self): + with support.EnvironmentVarGuard() as env: + env['COLUMNS'] = 'xxx' + env['LINES'] = 'yyy' + size = shutil.get_terminal_size() + self.assertGreaterEqual(size.columns, 0) + self.assertGreaterEqual(size.lines, 0) + @unittest.skipUnless(os.isatty(sys.__stdout__.fileno()), "not on tty") @unittest.skipUnless(hasattr(os, 'get_terminal_size'), 'need os.get_terminal_size()') @@ -1859,6 +1867,31 @@ class TermsizeTests(unittest.TestCase): self.assertEqual(expected, actual) + def test_fallback(self): + with support.EnvironmentVarGuard() as env: + del env['LINES'] + del env['COLUMNS'] + + # sys.__stdout__ has no fileno() + with support.swap_attr(sys, '__stdout__', None): + actual = shutil.get_terminal_size(fallback=(1, 2)) + self.assertEqual(actual, (1, 2)) + + # sys.__stdout__.fileno() not in (0, 1, 2) + with open(os.devnull, 'w') as f, \ + support.swap_attr(sys, '__stdout__', f): + actual = shutil.get_terminal_size(fallback=(3, 4)) + self.assertEqual(actual, (3, 4)) + + # No sys.__stdout__ + with support.swap_attr(sys, '__stdout__', None): + try: + del sys.__stdout__ + actual = shutil.get_terminal_size(fallback=(5, 6)) + finally: + sys.__stdout__ = None + self.assertEqual(actual, (5, 6)) + class PublicAPITests(unittest.TestCase): """Ensures that the correct values are exposed in the public API."""