@@ -1744,6 +1744,203 @@ def test_readline(self):
17441744 self .assertEqual (sout , b"\x80 " )
17451745
17461746
1747+ class CodePageTest (unittest .TestCase ):
1748+ CP_UTF8 = 65001
1749+ vista_or_later = (sys .getwindowsversion ().major >= 6 )
1750+
1751+ def test_invalid_code_page (self ):
1752+ self .assertRaises (ValueError , codecs .code_page_encode , - 1 , 'a' )
1753+ self .assertRaises (ValueError , codecs .code_page_decode , - 1 , b'a' )
1754+ self .assertRaises (WindowsError , codecs .code_page_encode , 123 , 'a' )
1755+ self .assertRaises (WindowsError , codecs .code_page_decode , 123 , b'a' )
1756+
1757+ def test_code_page_name (self ):
1758+ self .assertRaisesRegex (UnicodeEncodeError , 'cp932' ,
1759+ codecs .code_page_encode , 932 , '\xff ' )
1760+ self .assertRaisesRegex (UnicodeDecodeError , 'cp932' ,
1761+ codecs .code_page_decode , 932 , b'\x81 \x00 ' )
1762+ self .assertRaisesRegex (UnicodeDecodeError , 'CP_UTF8' ,
1763+ codecs .code_page_decode , self .CP_UTF8 , b'\xff ' )
1764+
1765+ def check_decode (self , cp , tests ):
1766+ for raw , errors , expected in tests :
1767+ if expected is not None :
1768+ try :
1769+ decoded = codecs .code_page_decode (cp , raw , errors )
1770+ except UnicodeDecodeError as err :
1771+ self .fail ('Unable to decode %a from "cp%s" with '
1772+ 'errors=%r: %s' % (raw , cp , errors , err ))
1773+ self .assertEqual (decoded [0 ], expected ,
1774+ '%a.decode("cp%s", %r)=%a != %a'
1775+ % (raw , cp , errors , decoded [0 ], expected ))
1776+ # assert 0 <= decoded[1] <= len(raw)
1777+ self .assertGreaterEqual (decoded [1 ], 0 )
1778+ self .assertLessEqual (decoded [1 ], len (raw ))
1779+ else :
1780+ self .assertRaises (UnicodeDecodeError ,
1781+ codecs .code_page_decode , cp , raw , errors )
1782+
1783+ def check_encode (self , cp , tests ):
1784+ for text , errors , expected in tests :
1785+ if expected is not None :
1786+ try :
1787+ encoded = codecs .code_page_encode (cp , text , errors )
1788+ except UnicodeEncodeError as err :
1789+ self .fail ('Unable to encode %a to "cp%s" with '
1790+ 'errors=%r: %s' % (text , cp , errors , err ))
1791+ self .assertEqual (encoded [0 ], expected ,
1792+ '%a.encode("cp%s", %r)=%a != %a'
1793+ % (text , cp , errors , encoded [0 ], expected ))
1794+ self .assertEqual (encoded [1 ], len (text ))
1795+ else :
1796+ self .assertRaises (UnicodeEncodeError ,
1797+ codecs .code_page_encode , cp , text , errors )
1798+
1799+ def test_cp932 (self ):
1800+ self .check_encode (932 , (
1801+ ('abc' , 'strict' , b'abc' ),
1802+ ('\uff44 \u9a3e ' , 'strict' , b'\x82 \x84 \xe9 \x80 ' ),
1803+ # not encodable
1804+ ('\xff ' , 'strict' , None ),
1805+ ('[\xff ]' , 'ignore' , b'[]' ),
1806+ ('[\xff ]' , 'replace' , b'[y]' ),
1807+ ('[\u20ac ]' , 'replace' , b'[?]' ),
1808+ ))
1809+ tests = [
1810+ (b'abc' , 'strict' , 'abc' ),
1811+ (b'\x82 \x84 \xe9 \x80 ' , 'strict' , '\uff44 \u9a3e ' ),
1812+ # invalid bytes
1813+ (b'\xff ' , 'strict' , None ),
1814+ (b'\xff ' , 'ignore' , '' ),
1815+ (b'\xff ' , 'replace' , '\ufffd ' ),
1816+ (b'\x81 \x00 abc' , 'strict' , None ),
1817+ (b'\x81 \x00 abc' , 'ignore' , '\x00 abc' ),
1818+ ]
1819+ if self .vista_or_later :
1820+ tests .append ((b'\x81 \x00 abc' , 'replace' , '\ufffd \x00 abc' ))
1821+ else :
1822+ tests .append ((b'\x81 \x00 abc' , 'replace' , '\x00 \x00 abc' ))
1823+ self .check_decode (932 , tests )
1824+
1825+ def test_cp1252 (self ):
1826+ self .check_encode (1252 , (
1827+ ('abc' , 'strict' , b'abc' ),
1828+ ('\xe9 \u20ac ' , 'strict' , b'\xe9 \x80 ' ),
1829+ ('\xff ' , 'strict' , b'\xff ' ),
1830+ ('\u0141 ' , 'strict' , None ),
1831+ ('\u0141 ' , 'ignore' , b'' ),
1832+ ('\u0141 ' , 'replace' , b'L' ),
1833+ ))
1834+ self .check_decode (1252 , (
1835+ (b'abc' , 'strict' , 'abc' ),
1836+ (b'\xe9 \x80 ' , 'strict' , '\xe9 \u20ac ' ),
1837+ (b'\xff ' , 'strict' , '\xff ' ),
1838+ ))
1839+
1840+ def test_cp_utf7 (self ):
1841+ cp = 65000
1842+ self .check_encode (cp , (
1843+ ('abc' , 'strict' , b'abc' ),
1844+ ('\xe9 \u20ac ' , 'strict' , b'+AOkgrA-' ),
1845+ ('\U0010ffff ' , 'strict' , b'+2//f/w-' ),
1846+ ('\udc80 ' , 'strict' , b'+3IA-' ),
1847+ ('\ufffd ' , 'strict' , b'+//0-' ),
1848+ ))
1849+ self .check_decode (cp , (
1850+ (b'abc' , 'strict' , 'abc' ),
1851+ (b'+AOkgrA-' , 'strict' , '\xe9 \u20ac ' ),
1852+ (b'+2//f/w-' , 'strict' , '\U0010ffff ' ),
1853+ (b'+3IA-' , 'strict' , '\udc80 ' ),
1854+ (b'+//0-' , 'strict' , '\ufffd ' ),
1855+ # invalid bytes
1856+ (b'[+/]' , 'strict' , '[]' ),
1857+ (b'[\xff ]' , 'strict' , '[\xff ]' ),
1858+ ))
1859+
1860+ def test_cp_utf8 (self ):
1861+ cp = self .CP_UTF8
1862+
1863+ tests = [
1864+ ('abc' , 'strict' , b'abc' ),
1865+ ('\xe9 \u20ac ' , 'strict' , b'\xc3 \xa9 \xe2 \x82 \xac ' ),
1866+ ('\U0010ffff ' , 'strict' , b'\xf4 \x8f \xbf \xbf ' ),
1867+ ]
1868+ if self .vista_or_later :
1869+ tests .append (('\udc80 ' , 'strict' , None ))
1870+ tests .append (('\udc80 ' , 'ignore' , b'' ))
1871+ tests .append (('\udc80 ' , 'replace' , b'?' ))
1872+ else :
1873+ tests .append (('\udc80 ' , 'strict' , b'\xed \xb2 \x80 ' ))
1874+ self .check_encode (cp , tests )
1875+
1876+ tests = [
1877+ (b'abc' , 'strict' , 'abc' ),
1878+ (b'\xc3 \xa9 \xe2 \x82 \xac ' , 'strict' , '\xe9 \u20ac ' ),
1879+ (b'\xf4 \x8f \xbf \xbf ' , 'strict' , '\U0010ffff ' ),
1880+ (b'\xef \xbf \xbd ' , 'strict' , '\ufffd ' ),
1881+ (b'[\xc3 \xa9 ]' , 'strict' , '[\xe9 ]' ),
1882+ # invalid bytes
1883+ (b'[\xff ]' , 'strict' , None ),
1884+ (b'[\xff ]' , 'ignore' , '[]' ),
1885+ (b'[\xff ]' , 'replace' , '[\ufffd ]' ),
1886+ ]
1887+ if self .vista_or_later :
1888+ tests .extend ((
1889+ (b'[\xed \xb2 \x80 ]' , 'strict' , None ),
1890+ (b'[\xed \xb2 \x80 ]' , 'ignore' , '[]' ),
1891+ (b'[\xed \xb2 \x80 ]' , 'replace' , '[\ufffd \ufffd \ufffd ]' ),
1892+ ))
1893+ else :
1894+ tests .extend ((
1895+ (b'[\xed \xb2 \x80 ]' , 'strict' , '[\udc80 ]' ),
1896+ ))
1897+ self .check_decode (cp , tests )
1898+
1899+ def test_error_handlers (self ):
1900+ self .check_encode (932 , (
1901+ ('\xff ' , 'backslashreplace' , b'\\ xff' ),
1902+ ('\xff ' , 'xmlcharrefreplace' , b'ÿ' ),
1903+ ))
1904+ self .check_decode (932 , (
1905+ (b'\xff ' , 'surrogateescape' , '\udcff ' ),
1906+ ))
1907+ if self .vista_or_later :
1908+ self .check_encode (self .CP_UTF8 , (
1909+ ('\udc80 ' , 'surrogatepass' , b'\xed \xb2 \x80 ' ),
1910+ ))
1911+
1912+ def test_multibyte_encoding (self ):
1913+ self .check_decode (932 , (
1914+ (b'\x84 \xe9 \x80 ' , 'ignore' , '\u9a3e ' ),
1915+ (b'\x84 \xe9 \x80 ' , 'replace' , '\ufffd \u9a3e ' ),
1916+ ))
1917+ self .check_decode (self .CP_UTF8 , (
1918+ (b'\xff \xf4 \x8f \xbf \xbf ' , 'ignore' , '\U0010ffff ' ),
1919+ (b'\xff \xf4 \x8f \xbf \xbf ' , 'replace' , '\ufffd \U0010ffff ' ),
1920+ ))
1921+ if self .vista_or_later :
1922+ self .check_encode (self .CP_UTF8 , (
1923+ ('[\U0010ffff \uDC80 ]' , 'ignore' , b'[\xf4 \x8f \xbf \xbf ]' ),
1924+ ('[\U0010ffff \uDC80 ]' , 'replace' , b'[\xf4 \x8f \xbf \xbf ?]' ),
1925+ ))
1926+
1927+ def test_incremental (self ):
1928+ decoded = codecs .code_page_decode (932 ,
1929+ b'\xe9 \x80 \xe9 ' , 'strict' ,
1930+ False )
1931+ self .assertEqual (decoded , ('\u9a3e ' , 2 ))
1932+
1933+ decoded = codecs .code_page_decode (932 ,
1934+ b'\xe9 \x80 \xe9 \x80 ' , 'strict' ,
1935+ False )
1936+ self .assertEqual (decoded , ('\u9a3e \u9a3e ' , 4 ))
1937+
1938+ decoded = codecs .code_page_decode (932 ,
1939+ b'abc' , 'strict' ,
1940+ False )
1941+ self .assertEqual (decoded , ('abc' , 3 ))
1942+
1943+
17471944def test_main ():
17481945 support .run_unittest (
17491946 UTF32Test ,
@@ -1772,6 +1969,7 @@ def test_main():
17721969 SurrogateEscapeTest ,
17731970 BomTest ,
17741971 TransformCodecTest ,
1972+ CodePageTest ,
17751973 )
17761974
17771975
0 commit comments