mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	
		
			
	
	
		
			156 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			156 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								import unittest
							 | 
						||
| 
								 | 
							
								from _apple_support import SystemLog
							 | 
						||
| 
								 | 
							
								from test.support import is_apple
							 | 
						||
| 
								 | 
							
								from unittest.mock import Mock, call
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if not is_apple:
							 | 
						||
| 
								 | 
							
								    raise unittest.SkipTest("Apple-specific")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Test redirection of stdout and stderr to the Apple system log.
							 | 
						||
| 
								 | 
							
								class TestAppleSystemLogOutput(unittest.TestCase):
							 | 
						||
| 
								 | 
							
								    maxDiff = None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def assert_writes(self, output):
							 | 
						||
| 
								 | 
							
								        self.assertEqual(
							 | 
						||
| 
								 | 
							
								            self.log_write.mock_calls,
							 | 
						||
| 
								 | 
							
								            [
							 | 
						||
| 
								 | 
							
								                call(self.log_level, line)
							 | 
						||
| 
								 | 
							
								                for line in output
							 | 
						||
| 
								 | 
							
								            ]
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.log_write.reset_mock()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def setUp(self):
							 | 
						||
| 
								 | 
							
								        self.log_write = Mock()
							 | 
						||
| 
								 | 
							
								        self.log_level = 42
							 | 
						||
| 
								 | 
							
								        self.log = SystemLog(self.log_write, self.log_level, errors="replace")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_repr(self):
							 | 
						||
| 
								 | 
							
								        self.assertEqual(repr(self.log), "<SystemLog (level 42)>")
							 | 
						||
| 
								 | 
							
								        self.assertEqual(repr(self.log.buffer), "<LogStream (level 42)>")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_log_config(self):
							 | 
						||
| 
								 | 
							
								        self.assertIs(self.log.writable(), True)
							 | 
						||
| 
								 | 
							
								        self.assertIs(self.log.readable(), False)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.assertEqual("UTF-8", self.log.encoding)
							 | 
						||
| 
								 | 
							
								        self.assertEqual("replace", self.log.errors)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.assertIs(self.log.line_buffering, True)
							 | 
						||
| 
								 | 
							
								        self.assertIs(self.log.write_through, False)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_empty_str(self):
							 | 
						||
| 
								 | 
							
								        self.log.write("")
							 | 
						||
| 
								 | 
							
								        self.log.flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.assert_writes([])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_simple_str(self):
							 | 
						||
| 
								 | 
							
								        self.log.write("hello world\n")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"hello world\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_buffered_str(self):
							 | 
						||
| 
								 | 
							
								        self.log.write("h")
							 | 
						||
| 
								 | 
							
								        self.log.write("ello")
							 | 
						||
| 
								 | 
							
								        self.log.write(" ")
							 | 
						||
| 
								 | 
							
								        self.log.write("world\n")
							 | 
						||
| 
								 | 
							
								        self.log.write("goodbye.")
							 | 
						||
| 
								 | 
							
								        self.log.flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"hello world\n", b"goodbye."])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_manual_flush(self):
							 | 
						||
| 
								 | 
							
								        self.log.write("Hello")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.assert_writes([])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.log.write(" world\nHere for a while...\nGoodbye")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"Hello world\n", b"Here for a while...\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.log.write(" world\nHello again")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"Goodbye world\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.log.flush()
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"Hello again"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_non_ascii(self):
							 | 
						||
| 
								 | 
							
								        # Spanish
							 | 
						||
| 
								 | 
							
								        self.log.write("ol\u00e9\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"ol\xc3\xa9\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Chinese
							 | 
						||
| 
								 | 
							
								        self.log.write("\u4e2d\u6587\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"\xe4\xb8\xad\xe6\x96\x87\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Printing Non-BMP emoji
							 | 
						||
| 
								 | 
							
								        self.log.write("\U0001f600\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"\xf0\x9f\x98\x80\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # Non-encodable surrogates are replaced
							 | 
						||
| 
								 | 
							
								        self.log.write("\ud800\udc00\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"??\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_modified_null(self):
							 | 
						||
| 
								 | 
							
								        # Null characters are logged using "modified UTF-8".
							 | 
						||
| 
								 | 
							
								        self.log.write("\u0000\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"\xc0\x80\n"])
							 | 
						||
| 
								 | 
							
								        self.log.write("a\u0000\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"a\xc0\x80\n"])
							 | 
						||
| 
								 | 
							
								        self.log.write("\u0000b\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"\xc0\x80b\n"])
							 | 
						||
| 
								 | 
							
								        self.log.write("a\u0000b\n")
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"a\xc0\x80b\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_nonstandard_str(self):
							 | 
						||
| 
								 | 
							
								        # String subclasses are accepted, but they should be converted
							 | 
						||
| 
								 | 
							
								        # to a standard str without calling any of their methods.
							 | 
						||
| 
								 | 
							
								        class CustomStr(str):
							 | 
						||
| 
								 | 
							
								            def splitlines(self, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								                raise AssertionError()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            def __len__(self):
							 | 
						||
| 
								 | 
							
								                raise AssertionError()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            def __str__(self):
							 | 
						||
| 
								 | 
							
								                raise AssertionError()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.log.write(CustomStr("custom\n"))
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"custom\n"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_non_str(self):
							 | 
						||
| 
								 | 
							
								        # Non-string classes are not accepted.
							 | 
						||
| 
								 | 
							
								        for obj in [b"", b"hello", None, 42]:
							 | 
						||
| 
								 | 
							
								            with self.subTest(obj=obj):
							 | 
						||
| 
								 | 
							
								                with self.assertRaisesRegex(
							 | 
						||
| 
								 | 
							
								                    TypeError,
							 | 
						||
| 
								 | 
							
								                    fr"write\(\) argument must be str, not "
							 | 
						||
| 
								 | 
							
								                    fr"{type(obj).__name__}"
							 | 
						||
| 
								 | 
							
								                ):
							 | 
						||
| 
								 | 
							
								                    self.log.write(obj)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_byteslike_in_buffer(self):
							 | 
						||
| 
								 | 
							
								        # The underlying buffer *can* accept bytes-like objects
							 | 
						||
| 
								 | 
							
								        self.log.buffer.write(bytearray(b"hello"))
							 | 
						||
| 
								 | 
							
								        self.log.flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.log.buffer.write(b"")
							 | 
						||
| 
								 | 
							
								        self.log.flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.log.buffer.write(b"goodbye")
							 | 
						||
| 
								 | 
							
								        self.log.flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.assert_writes([b"hello", b"goodbye"])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_non_byteslike_in_buffer(self):
							 | 
						||
| 
								 | 
							
								        for obj in ["hello", None, 42]:
							 | 
						||
| 
								 | 
							
								            with self.subTest(obj=obj):
							 | 
						||
| 
								 | 
							
								                with self.assertRaisesRegex(
							 | 
						||
| 
								 | 
							
								                    TypeError,
							 | 
						||
| 
								 | 
							
								                    fr"write\(\) argument must be bytes-like, not "
							 | 
						||
| 
								 | 
							
								                    fr"{type(obj).__name__}"
							 | 
						||
| 
								 | 
							
								                ):
							 | 
						||
| 
								 | 
							
								                    self.log.buffer.write(obj)
							 |