Skip to content

[C API] Add PyUnicode_Equal() function #124502

Description

@vstinner

Python 3.13 moved the private _PyUnicode_EQ() function to internal C API. mypy and Pyodide are using it.

I propose to add a public PyUnicode_Equal(a, b) function to the limited C API 3.14 to replace the private _PyUnicode_EQ() function:

  • Return 1 if a is equal to b.
  • Return 0 if a is not equal to b.
  • Set a TypeError exception and return -1 if a or b is not a Python str object.
  • The function always succeed if a and b are strings.

Linked PRs

Activity

  1. added a commit that references this issue on Sep 25, 2024
  2. vstinner commented on Sep 25, 2024

    @vstinner
    MemberAuthor
  3. rruuaanng commented on Sep 25, 2024

    @rruuaanng
    Contributor

    I think PyUnicode_Equal should like strcmp in glibc.
    Return 0 if a is equal to b.
    Return 1 if a isn't equal to b.

  4. vstinner commented on Sep 25, 2024

    @vstinner
    MemberAuthor

    I think PyUnicode_Equal should like strcmp in glibc.
    Return 0 if a is equal to b.
    Return 1 if a isn't equal to b.

    The C API Guidelines suggest to return 1 if "found" and 0 if "not found": https://devguide.python.org/developer-workflow/c-api/#guidelines-for-expanding-changing-the-public-api

    IMO it's more natural to return 1 if equal and 0 if not equal. So you can write if (PyUnicode_Equal(a, b)) { /* a == b */ }.

    Moreover, PyUnicode_Equal() API the same as existing private functions _PyUnicode_EQ() and _PyUnicode_Equal() (except that these functions don't check if arguments are strings).

  5. rruuaanng commented on Sep 25, 2024

    @rruuaanng
    Contributor

    I think PyUnicode_Equal should like strcmp in glibc.

    Return 0 if a is equal to b.

    Return 1 if a isn't equal to b.

    The C API Guidelines suggest to return 1 if "found" and 0 if "not found": https://devguide.python.org/developer-workflow/c-api/#guidelines-for-expanding-changing-the-public-api

    IMO it's more natural to return 1 if equal and 0 if not equal. So you can write if (PyUnicode_Equal(a, b)) { /* a == b */ }.

    Moreover, PyUnicode_Equal() API the same as existing private functions _PyUnicode_EQ() and _PyUnicode_Equal() (except that these functions don't check if arguments are strings).

    I think that's good idea, So when will it be implemented?
    Maybe you could give me a shot. Haha

  6. vstinner commented on Sep 25, 2024

    @vstinner
    MemberAuthor

    I already implemented the function. See attached PR.

  7. ZeroIntensity commented on Sep 25, 2024

    @ZeroIntensity
    Member

    Hmm, will this result in a cascade of PySomething_Equal functions? This case should be special, I don't think we need PyLong_Equal, PyDict_Equal, PyList_Equal, etc.

    Out of curiosity, what's the benefit here over PyUnicode_Compare(...) == 0?

  8. picnixz commented on Sep 25, 2024

    @picnixz
    Member

    PyUnicode_Compare is slower since it needs to handle Unicode kinds separately (you need to take care of mixed kinds since comparing two Unicode strings of different kinds is a well-defined operation). PyUnicode_Equal is faster because 1) it directly uses memcmp and 2) only needs to do something when the Unicode kinds match.

  9. vstinner commented on Sep 25, 2024

    @vstinner
    MemberAuthor

    Hmm, will this result in a cascade of PySomething_Equal functions? This case should be special, I don't think we need PyLong_Equal, PyDict_Equal, PyList_Equal, etc.

    C extensions such as mypy and Pyodide are already using the private _PyUnicode_EQ() function which has been removed in Python 3.13. I'm proposing a public replacement for them.

    I'm not aware of other PyTYPE_Equal() function. Only PyUnicode has a specialized equal function.

    Out of curiosity, what's the benefit here over PyUnicode_Compare(...) == 0?

    PyUnicode_Compare() returns -1 for "less than" but also for the error case. The caller must call PyErr_Occurred() which is inefficient. It causes an ambiguous return value: capi-workgroup/problems#1

    PyUnicode_Equal() has no such ambiguous return value (-1 only means error). Moreover, it may be a little bit faster, but I'm not sure about that.

  10. ZeroIntensity commented on Sep 25, 2024

    @ZeroIntensity
    Member

    I'm not aware of other PyTYPE_Equal() function. Only PyUnicode has a specialize equal function.

    Yeah, that's what I mean. I think it would be a bad idea to use this as precedent for future "faster" PyXXX_Equal functions. I'm fine with PyUnicode_Equal.

  11. vstinner commented on Sep 25, 2024

    @vstinner
    MemberAuthor

    I created capi-workgroup/decisions#43 issue in the C API Working Group.

  12. added 7 commits that reference this issue on Oct 7, 2024
  13. vstinner commented on Oct 9, 2024

    @vstinner
    MemberAuthor

    Function added by change a7f0727.

  14. vstinner commented on Oct 9, 2024

    @vstinner
    MemberAuthor

    Function added to pythoncapi-compat with change: python/pythoncapi-compat@abc0f29.

  15. added 3 commits that reference this issue on Oct 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions