[Python-checkins] cpython (merge 3.5 -> 3.6): Merge from 3.5.

serhiy.storchaka python-checkins at python.org
Sat Oct 8 15:48:28 EDT 2016


https://hg.python.org/cpython/rev/6803a6478056
changeset: 104395:6803a6478056
branch: 3.6
parent: 104392:4d4aefa52f49
parent: 104394:13addd71b751
user: Serhiy Storchaka <storchaka at gmail.com>
date: Sat Oct 08 22:46:01 2016 +0300
summary:
 Merge from 3.5.
files:
 Doc/c-api/unicode.rst | 9 +++-
 Lib/test/test_unicode.py | 45 ++++++++++++++++++++++++++-
 Misc/NEWS | 3 +
 Modules/_testcapimodule.c | 34 ++++++++++++++++++++
 Objects/unicodeobject.c | 10 ++++-
 5 files changed, 94 insertions(+), 7 deletions(-)
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -572,13 +572,16 @@
 .. versionadded:: 3.3
 
 
-.. c:function:: int PyUnicode_CopyCharacters(PyObject *to, Py_ssize_t to_start, \
- PyObject *from, Py_ssize_t from_start, Py_ssize_t how_many)
+.. c:function:: Py_ssize_t PyUnicode_CopyCharacters(PyObject *to, \
+ Py_ssize_t to_start, \
+ PyObject *from, \
+ Py_ssize_t from_start, \
+ Py_ssize_t how_many)
 
 Copy characters from one Unicode object into another. This function performs
 character conversion when necessary and falls back to :c:func:`memcpy` if
 possible. Returns ``-1`` and sets an exception on error, otherwise returns
- ``0``.
+ the number of copied characters.
 
 .. versionadded:: 3.3
 
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -4,7 +4,7 @@
 
 (c) Copyright CNRI, All Rights Reserved. NO WARRANTY.
 
-"""#"
+"""
 import _string
 import codecs
 import itertools
@@ -2735,6 +2735,49 @@
 self.assertEqual(unicode_asucs4(s, len(s), 1), s+'0円')
 self.assertEqual(unicode_asucs4(s, len(s), 0), s+'\uffff')
 
+ # Test PyUnicode_CopyCharacters()
+ @support.cpython_only
+ def test_copycharacters(self):
+ from _testcapi import unicode_copycharacters
+
+ strings = [
+ 'abcde', '\xa1\xa2\xa3\xa4\xa5',
+ '\u4f60\u597d\u4e16\u754c\uff01',
+ '\U0001f600\U0001f601\U0001f602\U0001f603\U0001f604'
+ ]
+
+ for idx, from_ in enumerate(strings):
+ # wide -> narrow: exceed maxchar limitation
+ for to in strings[:idx]:
+ self.assertRaises(
+ SystemError,
+ unicode_copycharacters, to, 0, from_, 0, 5
+ )
+ # same kind
+ for from_start in range(5):
+ self.assertEqual(
+ unicode_copycharacters(from_, 0, from_, from_start, 5),
+ (from_[from_start:from_start+5].ljust(5, '0円'),
+ 5-from_start)
+ )
+ for to_start in range(5):
+ self.assertEqual(
+ unicode_copycharacters(from_, to_start, from_, to_start, 5),
+ (from_[to_start:to_start+5].rjust(5, '0円'),
+ 5-to_start)
+ )
+ # narrow -> wide
+ # Tests omitted since this creates invalid strings.
+
+ s = strings[0]
+ self.assertRaises(IndexError, unicode_copycharacters, s, 6, s, 0, 5)
+ self.assertRaises(IndexError, unicode_copycharacters, s, -1, s, 0, 5)
+ self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, 6, 5)
+ self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, -1, 5)
+ self.assertRaises(SystemError, unicode_copycharacters, s, 1, s, 0, 5)
+ self.assertRaises(SystemError, unicode_copycharacters, s, 0, s, 0, -1)
+ self.assertRaises(SystemError, unicode_copycharacters, s, 0, b'', 0, 0)
+
 @support.cpython_only
 def test_encode_decimal(self):
 from _testcapi import unicode_encodedecimal
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #28379: Added sanity checks and tests for PyUnicode_CopyCharacters().
+ Patch by Xiang Zhang.
+
 - Issue #28376: The type of long range iterator is now registered as Iterator.
 Patch by Oren Milman.
 
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1859,6 +1859,39 @@
 }
 
 static PyObject *
+unicode_copycharacters(PyObject *self, PyObject *args)
+{
+ PyObject *from, *to, *to_copy;
+ Py_ssize_t from_start, to_start, how_many, copied;
+
+ if (!PyArg_ParseTuple(args, "UnOnn:unicode_copycharacters", &to, &to_start,
+ &from, &from_start, &how_many)) {
+ return NULL;
+ }
+
+ if (PyUnicode_READY(to) < 0) {
+ return NULL;
+ }
+
+ if (!(to_copy = PyUnicode_New(PyUnicode_GET_LENGTH(to),
+ PyUnicode_MAX_CHAR_VALUE(to)))) {
+ return NULL;
+ }
+ if (PyUnicode_Fill(to_copy, 0, PyUnicode_GET_LENGTH(to_copy), 0U) < 0) {
+ Py_DECREF(to_copy);
+ return NULL;
+ }
+
+ if ((copied = PyUnicode_CopyCharacters(to_copy, to_start, from,
+ from_start, how_many)) < 0) {
+ Py_DECREF(to_copy);
+ return NULL;
+ }
+
+ return Py_BuildValue("(Nn)", to_copy, copied);
+}
+
+static PyObject *
 unicode_encodedecimal(PyObject *self, PyObject *args)
 {
 Py_UNICODE *unicode;
@@ -4061,6 +4094,7 @@
 {"unicode_aswidechar", unicode_aswidechar, METH_VARARGS},
 {"unicode_aswidecharstring",unicode_aswidecharstring, METH_VARARGS},
 {"unicode_asucs4", unicode_asucs4, METH_VARARGS},
+ {"unicode_copycharacters", unicode_copycharacters, METH_VARARGS},
 {"unicode_encodedecimal", unicode_encodedecimal, METH_VARARGS},
 {"unicode_transformdecimaltoascii", unicode_transformdecimaltoascii, METH_VARARGS},
 {"unicode_legacy_string", unicode_legacy_string, METH_VARARGS},
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -1549,15 +1549,19 @@
 if (PyUnicode_READY(to) == -1)
 return -1;
 
- if (from_start < 0) {
+ if ((size_t)from_start > (size_t)PyUnicode_GET_LENGTH(from)) {
 PyErr_SetString(PyExc_IndexError, "string index out of range");
 return -1;
 }
- if (to_start < 0) {
+ if ((size_t)to_start > (size_t)PyUnicode_GET_LENGTH(to)) {
 PyErr_SetString(PyExc_IndexError, "string index out of range");
 return -1;
 }
- how_many = Py_MIN(PyUnicode_GET_LENGTH(from), how_many);
+ if (how_many < 0) {
+ PyErr_SetString(PyExc_SystemError, "how_many cannot be negative");
+ return -1;
+ }
+ how_many = Py_MIN(PyUnicode_GET_LENGTH(from)-from_start, how_many);
 if (to_start + how_many > PyUnicode_GET_LENGTH(to)) {
 PyErr_Format(PyExc_SystemError,
 "Cannot write %zi characters at %zi "
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /