--- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1072,7 +1072,7 @@ if columns <= 0 or lines <= 0: try: size = os.get_terminal_size(sys.__stdout__.fileno()) - except (NameError, OSError): + except (AttributeError, OSError): size = os.terminal_size(fallback) if columns <= 0: columns = size.columns --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1857,6 +1857,31 @@ self.assertEqual(expected, actual) + def test_os_without_get_terminal_size(self): #26801 + """Don't fail if os.get_terminal_size() doesn't exist.""" + get_terminal_size = getattr(os, "get_terminal_size", None) + if get_terminal_size is not None: + del os.get_terminal_size + + # make sure the function gets to (try to) call os.get_terminal)_size + # by removing all environment variables if they exist + columns = os.environ.pop("COLUMNS", None) + lines = os.environ.pop("LINES", None) + + try: + result = shutil.get_terminal_size() + except AttributeError: + self.fail("shutil.get_terminal_size() failed with AttributeError") + + # re-insert environment variables (if applicable) + if columns is not None: + os.environ["COLUMNS"] = columns + if lines is not None: + os.environ["LINES"] = lines + + # add back get_terminal_size to the os module + if get_terminal_size is not None: + os.get_terminal_size = get_terminal_size class PublicAPITests(unittest.TestCase): """Ensures that the correct values are exposed in the public API."""