77#include <Python.h>
88#include "CPy.h"
99
10- // On 3.13+, _PyUnicode_CheckConsistency and _PyUnicode_ToLowerFull/ToUpperFull
11- // were moved from the public API to internal/pycore_unicodeobject.h.
10+ // The _PyUnicode_CheckConsistency definition has been moved to the internal API
1211// https://github.com/python/cpython/pull/106398
13- #if CPY_3_13_FEATURES
12+ #if defined( Py_DEBUG ) && CPY_3_13_FEATURES
1413#include "internal/pycore_unicodeobject.h"
1514#endif
1615
@@ -684,7 +683,12 @@ static int CPy_ASCII_Upper(unsigned char c) { return Py_TOUPPER(c); }
684683
685684static PyObject * CPyStr_ChangeCase (PyObject * self ,
686685 int (* ascii_func )(unsigned char ),
687- int (* unicode_func )(Py_UCS4 , Py_UCS4 * )) {
686+ #if CPY_3_13_FEATURES
687+ PyObject * method_name
688+ #else
689+ int (* unicode_func )(Py_UCS4 , Py_UCS4 * )
690+ #endif
691+ ) {
688692 Py_ssize_t len = PyUnicode_GET_LENGTH (self );
689693 if (len == 0 ) {
690694 Py_INCREF (self );
@@ -703,6 +707,11 @@ static PyObject *CPyStr_ChangeCase(PyObject *self,
703707 return res ;
704708 }
705709
710+ #if CPY_3_13_FEATURES
711+ // On 3.13+, _PyUnicode_ToLowerFull/ToUpperFull are no longer exported,
712+ // so fall back to CPython's method implementation for non-ASCII strings.
713+ return PyObject_CallMethodNoArgs (self , method_name );
714+ #else
706715 // General Unicode: unicode_func handles 1-to-N expansion.
707716 // Worst case: each codepoint expands to 3 (per Unicode standard).
708717 // The tmp buffer is short-lived, and PyUnicode_FromKindAndData
@@ -724,14 +733,23 @@ static PyObject *CPyStr_ChangeCase(PyObject *self,
724733 PyObject * res = PyUnicode_FromKindAndData (PyUnicode_4BYTE_KIND , tmp , out_len );
725734 PyMem_Free (tmp );
726735 return res ;
736+ #endif
727737}
728738
729739PyObject * CPyStr_Lower (PyObject * self ) {
740+ #if CPY_3_13_FEATURES
741+ return CPyStr_ChangeCase (self , CPy_ASCII_Lower , mypyc_interned_str .lower );
742+ #else
730743 return CPyStr_ChangeCase (self , CPy_ASCII_Lower , _PyUnicode_ToLowerFull );
744+ #endif
731745}
732746
733747PyObject * CPyStr_Upper (PyObject * self ) {
748+ #if CPY_3_13_FEATURES
749+ return CPyStr_ChangeCase (self , CPy_ASCII_Upper , mypyc_interned_str .upper );
750+ #else
734751 return CPyStr_ChangeCase (self , CPy_ASCII_Upper , _PyUnicode_ToUpperFull );
752+ #endif
735753}
736754
737755bool CPyStr_IsDigit (PyObject * str ) {
0 commit comments