From dea574c49a0fa1fe932a8006bb9cdc564deaf8c9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 13 Aug 2018 13:25:26 +0300 Subject: [PATCH 1/5] bpo-34392: Add sys.isinterned(). --- Doc/library/sys.rst | 8 +++++ Lib/test/test_sys.py | 8 +++++ .../2018-08-13-13-25-15.bpo-34392.9kIlMF.rst | 1 + Python/clinic/sysmodule.c.h | 34 ++++++++++++++++++- Python/sysmodule.c | 18 ++++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 4ad060fc639e5e..bdf22386178e8c 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -865,6 +865,14 @@ always available. value of :func:`intern` around to benefit from it. +.. function:: isinterned(string) + + Return :const:`True` if the given string is "interned", :const:`False` + otherwise. + + .. versionadded:: 3.8 + + .. function:: is_finalizing() Return :const:`True` if the Python interpreter is diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 336ae447a8de5e..818e7bfd567d45 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -505,10 +505,17 @@ def test_intern(self): global numruns numruns += 1 self.assertRaises(TypeError, sys.intern) + self.assertRaises(TypeError, sys.intern, b'abc') + self.assertRaises(TypeError, sys.isinterned) + self.assertRaises(TypeError, sys.isinterned, b'abc') s = "never interned before" + str(numruns) + self.assertIs(sys.isinterned(s), False) self.assertTrue(sys.intern(s) is s) + self.assertIs(sys.isinterned(s), True) s2 = s.swapcase().swapcase() + self.assertIs(sys.isinterned(s2), False) self.assertTrue(sys.intern(s2) is s) + self.assertIs(sys.isinterned(s2), False) # Subclasses of string can't be interned, because they # provide too much opportunity for insane things to happen. @@ -520,6 +527,7 @@ def __hash__(self): return 123 self.assertRaises(TypeError, sys.intern, S("abc")) + self.assertIs(sys.isinterned(S("abc")), False) def test_sys_flags(self): self.assertTrue(sys.flags) diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst b/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst new file mode 100644 index 00000000000000..d399493e041d06 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst @@ -0,0 +1 @@ +Added :func:`sys.isinterned`. diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 3e1480513f6c2a..f56fb255170d1d 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -2,6 +2,38 @@ preserve [clinic start generated code]*/ +PyDoc_STRVAR(sys_isinterned__doc__, +"isinterned($module, string, /)\n" +"--\n" +"\n" +"Return True if the given string is \"interned\"."); + +#define SYS_ISINTERNED_METHODDEF \ + {"isinterned", (PyCFunction)sys_isinterned, METH_O, sys_isinterned__doc__}, + +static int +sys_isinterned_impl(PyObject *module, PyObject *string); + +static PyObject * +sys_isinterned(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *string; + int _return_value; + + if (!PyArg_Parse(arg, "U:isinterned", &string)) { + goto exit; + } + _return_value = sys_isinterned_impl(module, string); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + PyDoc_STRVAR(sys_set_coroutine_origin_tracking_depth__doc__, "set_coroutine_origin_tracking_depth($module, /, depth)\n" "--\n" @@ -63,4 +95,4 @@ sys_get_coroutine_origin_tracking_depth(PyObject *module, PyObject *Py_UNUSED(ig exit: return return_value; } -/*[clinic end generated code: output=4a3ac42b97d710ff input=a9049054013a1b77]*/ +/*[clinic end generated code: output=68a9c05a9862af2d input=a9049054013a1b77]*/ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 177b8307626d64..0fd1f35ad6817e 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -447,6 +447,23 @@ Return the string itself or the previously interned string object with the\n\ same value."); +/*[clinic input] +sys.isinterned -> bool + + string: unicode + / + +Return True if the given string is "interned". +[clinic start generated code]*/ + +static int +sys_isinterned_impl(PyObject *module, PyObject *string) +/*[clinic end generated code: output=0364c3f36499f868 input=2fe09bef8edf732e]*/ +{ + return PyUnicode_CHECK_INTERNED(string); +} + + /* * Cached interned string objects used for calling the profile and * trace functions. Initialized by trace_init(). @@ -1557,6 +1574,7 @@ static PyMethodDef sys_methods[] = { METH_NOARGS, enablelegacywindowsfsencoding_doc }, #endif /* MS_WINDOWS */ {"intern", sys_intern, METH_VARARGS, intern_doc}, + SYS_ISINTERNED_METHODDEF {"is_finalizing", sys_is_finalizing, METH_NOARGS, is_finalizing_doc}, #ifdef USE_MALLOPT {"mdebug", sys_mdebug, METH_VARARGS}, From 7b916980cc0e5463882ee74409acbe1e15832569 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 19 Aug 2018 09:52:48 +0300 Subject: [PATCH 2/5] Rename to sys._is_interned(). --- Doc/library/sys.rst | 6 +++++- Lib/test/test_sys.py | 22 +++++++++++++++------- Python/clinic/sysmodule.c.h | 18 +++++++++--------- Python/sysmodule.c | 8 ++++---- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index bdf22386178e8c..b252b668952de6 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -865,13 +865,17 @@ always available. value of :func:`intern` around to benefit from it. -.. function:: isinterned(string) +.. function:: _is_interned(string) Return :const:`True` if the given string is "interned", :const:`False` otherwise. .. versionadded:: 3.8 + .. impl-detail:: + + It is not guaranteed to exist in all implementations of Python. + .. function:: is_finalizing() diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 818e7bfd567d45..9d59ff387237dd 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -504,18 +504,25 @@ def test_43581(self): def test_intern(self): global numruns numruns += 1 + has_is_interned = (test.support.check_impl_detail(cpython=True) + or hasattr(sys, '_is_interned')) self.assertRaises(TypeError, sys.intern) self.assertRaises(TypeError, sys.intern, b'abc') - self.assertRaises(TypeError, sys.isinterned) - self.assertRaises(TypeError, sys.isinterned, b'abc') + if has_is_interned: + self.assertRaises(TypeError, sys._is_interned) + self.assertRaises(TypeError, sys._is_interned, b'abc') s = "never interned before" + str(numruns) - self.assertIs(sys.isinterned(s), False) + if has_is_interned: + self.assertIs(sys._is_interned(s), False) self.assertTrue(sys.intern(s) is s) - self.assertIs(sys.isinterned(s), True) + if has_is_interned: + self.assertIs(sys._is_interned(s), True) s2 = s.swapcase().swapcase() - self.assertIs(sys.isinterned(s2), False) + if has_is_interned: + self.assertIs(sys._is_interned(s2), False) self.assertTrue(sys.intern(s2) is s) - self.assertIs(sys.isinterned(s2), False) + if has_is_interned: + self.assertIs(sys._is_interned(s2), False) # Subclasses of string can't be interned, because they # provide too much opportunity for insane things to happen. @@ -527,7 +534,8 @@ def __hash__(self): return 123 self.assertRaises(TypeError, sys.intern, S("abc")) - self.assertIs(sys.isinterned(S("abc")), False) + if has_is_interned: + self.assertIs(sys._is_interned(S("abc")), False) def test_sys_flags(self): self.assertTrue(sys.flags) diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index f56fb255170d1d..6128a577b75b3e 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -2,29 +2,29 @@ preserve [clinic start generated code]*/ -PyDoc_STRVAR(sys_isinterned__doc__, -"isinterned($module, string, /)\n" +PyDoc_STRVAR(sys__is_interned__doc__, +"_is_interned($module, string, /)\n" "--\n" "\n" "Return True if the given string is \"interned\"."); -#define SYS_ISINTERNED_METHODDEF \ - {"isinterned", (PyCFunction)sys_isinterned, METH_O, sys_isinterned__doc__}, +#define SYS__IS_INTERNED_METHODDEF \ + {"_is_interned", (PyCFunction)sys__is_interned, METH_O, sys__is_interned__doc__}, static int -sys_isinterned_impl(PyObject *module, PyObject *string); +sys__is_interned_impl(PyObject *module, PyObject *string); static PyObject * -sys_isinterned(PyObject *module, PyObject *arg) +sys__is_interned(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *string; int _return_value; - if (!PyArg_Parse(arg, "U:isinterned", &string)) { + if (!PyArg_Parse(arg, "U:_is_interned", &string)) { goto exit; } - _return_value = sys_isinterned_impl(module, string); + _return_value = sys__is_interned_impl(module, string); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; } @@ -95,4 +95,4 @@ sys_get_coroutine_origin_tracking_depth(PyObject *module, PyObject *Py_UNUSED(ig exit: return return_value; } -/*[clinic end generated code: output=68a9c05a9862af2d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=95761ded68d29915 input=a9049054013a1b77]*/ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 0fd1f35ad6817e..9cd78b489c515f 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -448,7 +448,7 @@ same value."); /*[clinic input] -sys.isinterned -> bool +sys._is_interned -> bool string: unicode / @@ -457,8 +457,8 @@ Return True if the given string is "interned". [clinic start generated code]*/ static int -sys_isinterned_impl(PyObject *module, PyObject *string) -/*[clinic end generated code: output=0364c3f36499f868 input=2fe09bef8edf732e]*/ +sys__is_interned_impl(PyObject *module, PyObject *string) +/*[clinic end generated code: output=c3678267b4e9d7ed input=039843e17883b606]*/ { return PyUnicode_CHECK_INTERNED(string); } @@ -1574,7 +1574,7 @@ static PyMethodDef sys_methods[] = { METH_NOARGS, enablelegacywindowsfsencoding_doc }, #endif /* MS_WINDOWS */ {"intern", sys_intern, METH_VARARGS, intern_doc}, - SYS_ISINTERNED_METHODDEF + SYS__IS_INTERNED_METHODDEF {"is_finalizing", sys_is_finalizing, METH_NOARGS, is_finalizing_doc}, #ifdef USE_MALLOPT {"mdebug", sys_mdebug, METH_VARARGS}, From 4ae8dd9fe1ce39ac25016ce1a20f22c6e53fa10c Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 8 May 2022 17:19:41 +0300 Subject: [PATCH 3/5] Update version. --- Doc/library/sys.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 25ad22c2db54f2..eac39ca036616d 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1054,7 +1054,7 @@ always available. Return :const:`True` if the given string is "interned", :const:`False` otherwise. - .. versionadded:: 3.11 + .. versionadded:: 3.12 .. impl-detail:: From 5f86a68975ac9c2d6392bff6b2d87004d1888a42 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 9 May 2022 07:53:57 +0300 Subject: [PATCH 4/5] Update Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst Co-authored-by: Inada Naoki --- .../Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst b/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst index d399493e041d06..bc4fd1ad1f5c7c 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2018-08-13-13-25-15.bpo-34392.9kIlMF.rst @@ -1 +1 @@ -Added :func:`sys.isinterned`. +Added :func:`sys._is_interned`. From f8319208b8fe3de7a5500ef3ac555ec9c1f1b246 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 4 Dec 2023 10:28:24 +0200 Subject: [PATCH 5/5] Add a What's New entry. --- Doc/library/sys.rst | 2 +- Doc/whatsnew/3.13.rst | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 1f9b0aca2af990..7f359819e6847e 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1210,7 +1210,7 @@ always available. Return :const:`True` if the given string is "interned", :const:`False` otherwise. - .. versionadded:: 3.12 + .. versionadded:: 3.13 .. impl-detail:: diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 372e4a45468e68..676305c6e1d06a 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -297,6 +297,13 @@ sqlite3 object is not :meth:`closed ` explicitly. (Contributed by Erlend E. Aasland in :gh:`105539`.) +sys +--- + +* Add the :func:`sys._is_interned` function to test if the string was interned. + This function is not guaranteed to exist in all implementations of Python. + (Contributed by Serhiy Storchaka in :gh:`78573`.) + tkinter -------