diff options
-rw-r--r-- | Lib/_pyio.py | 6 | ||||
-rw-r--r-- | Lib/socketserver.py | 1 | ||||
-rw-r--r-- | Lib/sysconfig.py | 6 | ||||
-rw-r--r-- | Lib/test/cjkencodings/hz-utf8.txt | 2 | ||||
-rw-r--r-- | Lib/test/cjkencodings/hz.txt | 2 | ||||
-rw-r--r-- | Lib/test/test_codecencodings_cn.py | 29 | ||||
-rw-r--r-- | Lib/test/test_io.py | 9 | ||||
-rw-r--r-- | Lib/test/test_multibytecodec.py | 30 | ||||
-rw-r--r-- | Lib/test/test_sysconfig.py | 34 | ||||
-rw-r--r-- | Makefile.pre.in | 4 | ||||
-rw-r--r-- | Misc/NEWS | 14 | ||||
-rw-r--r-- | Modules/_io/fileio.c | 2 | ||||
-rw-r--r-- | Modules/_io/iobase.c | 8 | ||||
-rw-r--r-- | Modules/_testembed.c | 6 | ||||
-rw-r--r-- | Modules/cjkcodecs/multibytecodec.c | 8 | ||||
-rw-r--r-- | Objects/typeobject.c | 6 | ||||
-rw-r--r-- | Tools/msi/msi.py | 2 |
17 files changed, 144 insertions, 25 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 35dea41..b79d5fc 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -558,7 +558,11 @@ class RawIOBase(IOBase): if not data: break res += data - return bytes(res) + if res: + return bytes(res) + else: + # b'' or None + return data def readinto(self, b): """Read up to len(b) bytes into bytearray b. diff --git a/Lib/socketserver.py b/Lib/socketserver.py index 089b3ba..7389608 100644 --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -549,7 +549,6 @@ class ForkingMixIn: self.active_children = [] self.active_children.append(pid) self.close_request(request) - return else: # Child process. # This must never return, hence os._exit()! diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index 41bccf3..2279a51 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -294,7 +294,7 @@ def _parse_makefile(filename, vars=None): variables.remove(name) if name.startswith('PY_') \ - and name[3:] in renamed_variables: + and name[3:] in renamed_variables: name = name[3:] if name not in done: @@ -302,7 +302,9 @@ def _parse_makefile(filename, vars=None): else: - # bogus variable reference; just drop it since we can't deal + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + done[name] = value variables.remove(name) # strip spurious spaces diff --git a/Lib/test/cjkencodings/hz-utf8.txt b/Lib/test/cjkencodings/hz-utf8.txt new file mode 100644 index 0000000..7c11735 --- /dev/null +++ b/Lib/test/cjkencodings/hz-utf8.txt @@ -0,0 +1,2 @@ +This sentence is in ASCII. +The next sentence is in GB.己所不欲,勿施於人。Bye. diff --git a/Lib/test/cjkencodings/hz.txt b/Lib/test/cjkencodings/hz.txt new file mode 100644 index 0000000..f882d46 --- /dev/null +++ b/Lib/test/cjkencodings/hz.txt @@ -0,0 +1,2 @@ +This sentence is in ASCII. +The next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye. diff --git a/Lib/test/test_codecencodings_cn.py b/Lib/test/test_codecencodings_cn.py index a2d9718..dca9f10 100644 --- a/Lib/test/test_codecencodings_cn.py +++ b/Lib/test/test_codecencodings_cn.py @@ -50,6 +50,35 @@ class Test_GB18030(test_multibytecodec_support.TestBase, unittest.TestCase): ) has_iso10646 = True +class Test_HZ(test_multibytecodec_support.TestBase, unittest.TestCase): + encoding = 'hz' + tstring = test_multibytecodec_support.load_teststring('hz') + codectests = ( + # test '~\n' (3 lines) + (b'This sentence is in ASCII.\n' + b'The next sentence is in GB.~{<:Ky2;S{#,~}~\n' + b'~{NpJ)l6HK!#~}Bye.\n', + 'strict', + 'This sentence is in ASCII.\n' + 'The next sentence is in GB.' + '\u5df1\u6240\u4e0d\u6b32\uff0c\u52ff\u65bd\u65bc\u4eba\u3002' + 'Bye.\n'), + # test '~\n' (4 lines) + (b'This sentence is in ASCII.\n' + b'The next sentence is in GB.~\n' + b'~{<:Ky2;S{#,NpJ)l6HK!#~}~\n' + b'Bye.\n', + 'strict', + 'This sentence is in ASCII.\n' + 'The next sentence is in GB.' + '\u5df1\u6240\u4e0d\u6b32\uff0c\u52ff\u65bd\u65bc\u4eba\u3002' + 'Bye.\n'), + # invalid bytes + (b'ab~cd', 'replace', 'ab\uFFFDd'), + (b'ab\xffcd', 'replace', 'ab\uFFFDcd'), + (b'ab~{\x81\x81\x41\x44~}cd', 'replace', 'ab\uFFFD\uFFFD\u804Acd'), + ) + def test_main(): support.run_unittest(__name__) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index dac30cb..707b7cb 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -827,14 +827,17 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests): # Inject some None's in there to simulate EWOULDBLOCK rawio = self.MockRawIO((b"abc", b"d", None, b"efg", None, None, None)) bufio = self.tp(rawio) - self.assertEqual(b"abcd", bufio.read(6)) self.assertEqual(b"e", bufio.read(1)) self.assertEqual(b"fg", bufio.read()) self.assertEqual(b"", bufio.peek(1)) - self.assertTrue(None is bufio.read()) + self.assertIsNone(bufio.read()) self.assertEqual(b"", bufio.read()) + rawio = self.MockRawIO((b"a", None, None)) + self.assertEqual(b"a", rawio.readall()) + self.assertIsNone(rawio.readall()) + def test_read_past_eof(self): rawio = self.MockRawIO((b"abc", b"d", b"efg")) bufio = self.tp(rawio) @@ -2505,6 +2508,8 @@ class MiscIOTest(unittest.TestCase): self.assertRaises(ValueError, f.read) if hasattr(f, "read1"): self.assertRaises(ValueError, f.read1, 1024) + if hasattr(f, "readall"): + self.assertRaises(ValueError, f.readall) if hasattr(f, "readinto"): self.assertRaises(ValueError, f.readinto, bytearray(1024)) self.assertRaises(ValueError, f.readline) diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py index fe772e1..86c68dc 100644 --- a/Lib/test/test_multibytecodec.py +++ b/Lib/test/test_multibytecodec.py @@ -256,6 +256,36 @@ class Test_ISO2022(unittest.TestCase): # Any ISO 2022 codec will cause the segfault myunichr(x).encode('iso_2022_jp', 'ignore') +class TestStateful(unittest.TestCase): + text = '\u4E16\u4E16' + encoding = 'iso-2022-jp' + expected = b'\x1b$B@$@$' + expected_reset = b'\x1b$B@$@$\x1b(B' + + def test_encode(self): + self.assertEqual(self.text.encode(self.encoding), self.expected_reset) + + def test_incrementalencoder(self): + encoder = codecs.getincrementalencoder(self.encoding)() + output = b''.join( + encoder.encode(char) + for char in self.text) + self.assertEqual(output, self.expected) + + def test_incrementalencoder_final(self): + encoder = codecs.getincrementalencoder(self.encoding)() + last_index = len(self.text) - 1 + output = b''.join( + encoder.encode(char, index == last_index) + for index, char in enumerate(self.text)) + self.assertEqual(output, self.expected_reset) + +class TestHZStateful(TestStateful): + text = '\u804a\u804a' + encoding = 'hz' + expected = b'~{ADAD' + expected_reset = b'~{ADAD~}' + def test_main(): support.run_unittest(__name__) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index a97b388..2ea8819 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -26,7 +26,6 @@ class TestSysConfig(unittest.TestCase): """Make a copy of sys.path""" super(TestSysConfig, self).setUp() self.sys_path = sys.path[:] - self.makefile = None # patching os.uname if hasattr(os, 'uname'): self.uname = os.uname @@ -49,8 +48,6 @@ class TestSysConfig(unittest.TestCase): def tearDown(self): """Restore sys.path""" sys.path[:] = self.sys_path - if self.makefile is not None: - os.unlink(self.makefile) self._cleanup_testfn() if self.uname is not None: os.uname = self.uname @@ -236,12 +233,6 @@ class TestSysConfig(unittest.TestCase): config_h = sysconfig.get_config_h_filename() self.assertTrue(os.path.isfile(config_h), config_h) - @unittest.skipIf(sys.platform.startswith('win'), - 'Test is not Windows compatible') - def test_get_makefile_filename(self): - makefile = sysconfig.get_makefile_filename() - self.assertTrue(os.path.isfile(makefile), makefile) - def test_get_scheme_names(self): wanted = ('nt', 'nt_user', 'os2', 'os2_home', 'osx_framework_user', 'posix_home', 'posix_prefix', 'posix_user') @@ -339,10 +330,33 @@ class TestSysConfig(unittest.TestCase): self.assertEqual(my_platform, test_platform) +class MakefileTests(unittest.TestCase): + @unittest.skipIf(sys.platform.startswith('win'), + 'Test is not Windows compatible') + def test_get_makefile_filename(self): + makefile = sysconfig.get_makefile_filename() + self.assertTrue(os.path.isfile(makefile), makefile) + + def test_parse_makefile(self): + self.addCleanup(unlink, TESTFN) + with open(TESTFN, "w") as makefile: + print("var1=a$(VAR2)", file=makefile) + print("VAR2=b$(var3)", file=makefile) + print("var3=42", file=makefile) + print("var4=$/invalid", file=makefile) + print("var5=dollar$$5", file=makefile) + vars = sysconfig._parse_makefile(TESTFN) + self.assertEqual(vars, { + 'var1': 'ab42', + 'VAR2': 'b42', + 'var3': 42, + 'var4': '$/invalid', + 'var5': 'dollar$5', + }) def test_main(): - run_unittest(TestSysConfig) + run_unittest(TestSysConfig, MakefileTests) if __name__ == "__main__": test_main() diff --git a/Makefile.pre.in b/Makefile.pre.in index db870a4..50ba086 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -909,8 +909,8 @@ EXTRAPLATDIR= @EXTRAPLATDIR@ MACHDEPS= $(PLATDIR) $(EXTRAPLATDIR) XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ - tkinter/test/test_ttk site-packages test \ - test/decimaltestdata test/xmltestdata test/subprocessdata \ + tkinter/test/test_ttk site-packages test \ + test/cjkencodings test/decimaltestdata test/xmltestdata test/subprocessdata \ test/tracedmodules test/encoded_modules \ concurrent concurrent/futures encodings \ email email/mime email/test email/test/data \ @@ -13,6 +13,20 @@ Core and Builtins Library ------- +- Issue #12175: RawIOBase.readall() now returns None if read() returns None. + +- Issue #12175: FileIO.readall() now raises a ValueError instead of an IOError + if the file is closed. + +- Issue #12070: Fix the Makefile parser of the sysconfig module to handle + correctly references to "bogus variable" (e.g. "prefix=$/opt/python"). + +- Issue #12100: Don't reset incremental encoders of CJK codecs at each call to + their encode() method anymore, but continue to call the reset() method if the + final argument is True. + +- Issue #5715: In socketserver, close the server socket in the child process. + - Correct lookup of __dir__ on objects. Among other things, this causes errors besides AttributeError found on lookup to be propagated. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 1aa5ee9..141b6de 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -583,6 +583,8 @@ fileio_readall(fileio *self) Py_ssize_t total = 0; int n; + if (self->fd < 0) + return err_closed(); if (!_PyVerify_fd(self->fd)) return PyErr_SetFromErrno(PyExc_IOError); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index ec7a242..f06f562 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -815,6 +815,14 @@ rawiobase_readall(PyObject *self, PyObject *args) Py_DECREF(chunks); return NULL; } + if (data == Py_None) { + if (PyList_GET_SIZE(chunks) == 0) { + Py_DECREF(chunks); + return data; + } + Py_DECREF(data); + break; + } if (!PyBytes_Check(data)) { Py_DECREF(chunks); Py_DECREF(data); diff --git a/Modules/_testembed.c b/Modules/_testembed.c index 0df5ede..51b439f 100644 --- a/Modules/_testembed.c +++ b/Modules/_testembed.c @@ -17,7 +17,9 @@ void print_subinterp(void) int main(int argc, char *argv[]) { PyThreadState *mainstate, *substate; +#ifdef WITH_THREAD PyGILState_STATE gilstate; +#endif int i, j; for (i=0; i<3; i++) { @@ -28,10 +30,12 @@ int main(int argc, char *argv[]) Py_Initialize(); mainstate = PyThreadState_Get(); +#ifdef WITH_THREAD PyEval_InitThreads(); PyEval_ReleaseThread(mainstate); gilstate = PyGILState_Ensure(); +#endif print_subinterp(); PyThreadState_Swap(NULL); @@ -43,7 +47,9 @@ int main(int argc, char *argv[]) PyThreadState_Swap(mainstate); print_subinterp(); +#ifdef WITH_THREAD PyGILState_Release(gilstate); +#endif PyEval_RestoreThread(mainstate); Py_Finalize(); diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index af7ea5b..7b04f020 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -479,7 +479,7 @@ multibytecodec_encode(MultibyteCodec *codec, MultibyteEncodeBuffer buf; Py_ssize_t finalsize, r = 0; - if (datalen == 0) + if (datalen == 0 && !(flags & MBENC_RESET)) return PyBytes_FromStringAndSize(NULL, 0); buf.excobj = NULL; @@ -514,7 +514,7 @@ multibytecodec_encode(MultibyteCodec *codec, break; } - if (codec->encreset != NULL) + if (codec->encreset != NULL && (flags & MBENC_RESET)) for (;;) { Py_ssize_t outleft; @@ -784,8 +784,8 @@ encoder_encode_stateful(MultibyteStatefulEncoderContext *ctx, inbuf_end = inbuf + datalen; r = multibytecodec_encode(ctx->codec, &ctx->state, - (const Py_UNICODE **)&inbuf, - datalen, ctx->errors, final ? MBENC_FLUSH : 0); + (const Py_UNICODE **)&inbuf, datalen, + ctx->errors, final ? MBENC_FLUSH | MBENC_RESET : 0); if (r == NULL) { /* recover the original pending buffer */ if (origpending > 0) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8eaf51f..3c724fd 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2582,9 +2582,9 @@ static PyMethodDef type_methods[] = { PyDoc_STR("__prepare__() -> dict\n" "used to create the namespace for the class statement")}, {"__instancecheck__", type___instancecheck__, METH_O, - PyDoc_STR("__instancecheck__() -> check if an object is an instance")}, + PyDoc_STR("__instancecheck__() -> bool\ncheck if an object is an instance")}, {"__subclasscheck__", type___subclasscheck__, METH_O, - PyDoc_STR("__subclasscheck__() -> check if a class is a subclass")}, + PyDoc_STR("__subclasscheck__() -> bool\ncheck if a class is a subclass")}, {0} }; @@ -3430,7 +3430,7 @@ static PyMethodDef object_methods[] = { {"__format__", object_format, METH_VARARGS, PyDoc_STR("default object formatter")}, {"__sizeof__", object_sizeof, METH_NOARGS, - PyDoc_STR("__sizeof__() -> size of object in memory, in bytes")}, + PyDoc_STR("__sizeof__() -> int\nsize of object in memory, in bytes")}, {0} }; diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py index 53e652d..5db62cd 100644 --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -1031,6 +1031,8 @@ def add_files(db): lib.glob("*.0") if dir=='tests' and parent.physical=='distutils': lib.add_file("Setup.sample") + if dir=='cjkencodings': + lib.glob("*.txt") if dir=='decimaltestdata': lib.glob("*.decTest") if dir=='xmltestdata': |