Skip to content

Commit 29a5447

Browse files
Issue #28701: Replace _PyUnicode_CompareWithId with _PyUnicode_EqualToASCIIId.
The latter function is more readable, faster and doesn't raise exceptions. Based on patch by Xiang Zhang.
2 parents 1a73bf3 + fab6acd commit 29a5447

File tree

5 files changed

+65
-8
lines changed

5 files changed

+65
-8
lines changed

Include/unicodeobject.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,12 +2037,31 @@ PyAPI_FUNC(int) PyUnicode_Compare(
20372037
);
20382038

20392039
#ifndef Py_LIMITED_API
2040+
/* Compare a string with an identifier and return -1, 0, 1 for less than,
2041+
equal, and greater than, respectively.
2042+
Raise an exception and return -1 on error. */
2043+
20402044
PyAPI_FUNC(int) _PyUnicode_CompareWithId(
20412045
PyObject *left, /* Left string */
20422046
_Py_Identifier *right /* Right identifier */
20432047
);
2048+
2049+
/* Test whether a unicode is equal to ASCII identifier. Return 1 if true,
2050+
0 otherwise. Return 0 if any argument contains non-ASCII characters.
2051+
Any error occurs inside will be cleared before return. */
2052+
2053+
PyAPI_FUNC(int) _PyUnicode_EqualToASCIIId(
2054+
PyObject *left, /* Left string */
2055+
_Py_Identifier *right /* Right identifier */
2056+
);
20442057
#endif
20452058

2059+
/* Compare a Unicode object with C string and return -1, 0, 1 for less than,
2060+
equal, and greater than, respectively. It is best to pass only
2061+
ASCII-encoded strings, but the function interprets the input string as
2062+
ISO-8859-1 if it contains non-ASCII characters.
2063+
Raise an exception and return -1 on error. */
2064+
20462065
PyAPI_FUNC(int) PyUnicode_CompareWithASCIIString(
20472066
PyObject *left,
20482067
const char *right /* ASCII-encoded string */

Objects/typeobject.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ type_repr(PyTypeObject *type)
863863
return NULL;
864864
}
865865

866-
if (mod != NULL && _PyUnicode_CompareWithId(mod, &PyId_builtins))
866+
if (mod != NULL && !_PyUnicode_EqualToASCIIId(mod, &PyId_builtins))
867867
rtn = PyUnicode_FromFormat("<class '%U.%U'>", mod, name);
868868
else
869869
rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
@@ -2403,7 +2403,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
24032403
if (!valid_identifier(tmp))
24042404
goto error;
24052405
assert(PyUnicode_Check(tmp));
2406-
if (_PyUnicode_CompareWithId(tmp, &PyId___dict__) == 0) {
2406+
if (_PyUnicode_EqualToASCIIId(tmp, &PyId___dict__)) {
24072407
if (!may_add_dict || add_dict) {
24082408
PyErr_SetString(PyExc_TypeError,
24092409
"__dict__ slot disallowed: "
@@ -2434,7 +2434,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
24342434
for (i = j = 0; i < nslots; i++) {
24352435
tmp = PyTuple_GET_ITEM(slots, i);
24362436
if ((add_dict &&
2437-
_PyUnicode_CompareWithId(tmp, &PyId___dict__) == 0) ||
2437+
_PyUnicode_EqualToASCIIId(tmp, &PyId___dict__)) ||
24382438
(add_weak &&
24392439
_PyUnicode_EqualToASCIIString(tmp, "__weakref__")))
24402440
continue;
@@ -3538,7 +3538,7 @@ object_repr(PyObject *self)
35383538
Py_XDECREF(mod);
35393539
return NULL;
35403540
}
3541-
if (mod != NULL && _PyUnicode_CompareWithId(mod, &PyId_builtins))
3541+
if (mod != NULL && !_PyUnicode_EqualToASCIIId(mod, &PyId_builtins))
35423542
rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self);
35433543
else
35443544
rtn = PyUnicode_FromFormat("<%s object at %p>",
@@ -7238,7 +7238,7 @@ super_getattro(PyObject *self, PyObject *name)
72387238
(i.e. super, or a subclass), not the class of su->obj. */
72397239
if (PyUnicode_Check(name) &&
72407240
PyUnicode_GET_LENGTH(name) == 9 &&
7241-
_PyUnicode_CompareWithId(name, &PyId___class__) == 0)
7241+
_PyUnicode_EqualToASCIIId(name, &PyId___class__))
72427242
goto skip;
72437243

72447244
mro = starttype->tp_mro;
@@ -7450,7 +7450,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
74507450
for (i = 0; i < n; i++) {
74517451
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
74527452
assert(PyUnicode_Check(name));
7453-
if (!_PyUnicode_CompareWithId(name, &PyId___class__)) {
7453+
if (_PyUnicode_EqualToASCIIId(name, &PyId___class__)) {
74547454
Py_ssize_t index = co->co_nlocals +
74557455
PyTuple_GET_SIZE(co->co_cellvars) + i;
74567456
PyObject *cell = f->f_localsplus[index];

Objects/unicodeobject.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11083,6 +11083,44 @@ _PyUnicode_EqualToASCIIString(PyObject *unicode, const char *str)
1108311083
memcmp(PyUnicode_1BYTE_DATA(unicode), str, len) == 0;
1108411084
}
1108511085

11086+
int
11087+
_PyUnicode_EqualToASCIIId(PyObject *left, _Py_Identifier *right)
11088+
{
11089+
PyObject *right_uni;
11090+
Py_hash_t hash;
11091+
11092+
assert(_PyUnicode_CHECK(left));
11093+
assert(right->string);
11094+
11095+
if (PyUnicode_READY(left) == -1) {
11096+
/* memory error or bad data */
11097+
PyErr_Clear();
11098+
return non_ready_unicode_equal_to_ascii_string(left, right->string);
11099+
}
11100+
11101+
if (!PyUnicode_IS_ASCII(left))
11102+
return 0;
11103+
11104+
right_uni = _PyUnicode_FromId(right); /* borrowed */
11105+
if (right_uni == NULL) {
11106+
/* memory error or bad data */
11107+
PyErr_Clear();
11108+
return _PyUnicode_EqualToASCIIString(left, right->string);
11109+
}
11110+
11111+
if (left == right_uni)
11112+
return 1;
11113+
11114+
if (PyUnicode_CHECK_INTERNED(left))
11115+
return 0;
11116+
11117+
assert(_PyUnicode_HASH(right_uni) != 1);
11118+
hash = _PyUnicode_HASH(left);
11119+
if (hash != -1 && hash != _PyUnicode_HASH(right_uni))
11120+
return 0;
11121+
11122+
return unicode_compare_eq(left, right_uni);
11123+
}
1108611124

1108711125
#define TEST_COND(cond) \
1108811126
((cond) ? Py_True : Py_False)

Python/errors.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ PyErr_WriteUnraisable(PyObject *obj)
984984
goto done;
985985
}
986986
else {
987-
if (_PyUnicode_CompareWithId(moduleName, &PyId_builtins) != 0) {
987+
if (!_PyUnicode_EqualToASCIIId(moduleName, &PyId_builtins)) {
988988
if (PyFile_WriteObject(moduleName, f, Py_PRINT_RAW) < 0)
989989
goto done;
990990
if (PyFile_WriteString(".", f) < 0)

Python/pythonrun.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ print_exception(PyObject *f, PyObject *value)
751751
err = PyFile_WriteString("<unknown>", f);
752752
}
753753
else {
754-
if (_PyUnicode_CompareWithId(moduleName, &PyId_builtins) != 0)
754+
if (!_PyUnicode_EqualToASCIIId(moduleName, &PyId_builtins))
755755
{
756756
err = PyFile_WriteObject(moduleName, f, Py_PRINT_RAW);
757757
err += PyFile_WriteString(".", f);

0 commit comments

Comments
 (0)