Index: Python/bltinmodule.c =================================================================== --- Python/bltinmodule.c (Revision 52823) +++ Python/bltinmodule.c (Arbeitskopie) @@ -1119,31 +1106,6 @@ static PyObject * -builtin_intern(PyObject *self, PyObject *args) -{ - PyObject *s; - if (!PyArg_ParseTuple(args, "S:intern", &s)) - return NULL; - if (!PyString_CheckExact(s)) { - PyErr_SetString(PyExc_TypeError, - "can't intern subclass of string"); - return NULL; - } - Py_INCREF(s); - PyString_InternInPlace(&s); - return s; -} - -PyDoc_STRVAR(intern_doc, -"intern(string) -> string\n\ -\n\ -``Intern'' the given string. This enters the string in the (global)\n\ -table of interned strings whose purpose is to speed up dictionary lookups.\n\ -Return the string itself or the previously interned string object with the\n\ -same value."); - - -static PyObject * builtin_iter(PyObject *self, PyObject *args) { PyObject *v, *w = NULL; @@ -2000,8 +1962,7 @@ {"hasattr", builtin_hasattr, METH_VARARGS, hasattr_doc}, {"hash", builtin_hash, METH_O, hash_doc}, {"hex", builtin_hex, METH_O, hex_doc}, {"id", builtin_id, METH_O, id_doc}, - {"intern", builtin_intern, METH_VARARGS, intern_doc}, {"isinstance", builtin_isinstance, METH_VARARGS, isinstance_doc}, {"issubclass", builtin_issubclass, METH_VARARGS, issubclass_doc}, {"iter", builtin_iter, METH_VARARGS, iter_doc}, Index: Python/sysmodule.c =================================================================== --- Python/sysmodule.c (Revision 52823) +++ Python/sysmodule.c (Arbeitskopie) @@ -264,6 +264,32 @@ #endif + +static PyObject * +sys_intern(PyObject *self, PyObject *args) +{ + PyObject *s; + if (!PyArg_ParseTuple(args, "S:intern", &s)) + return NULL; + if (!PyString_CheckExact(s)) { + PyErr_SetString(PyExc_TypeError, + "can't intern subclass of string"); + return NULL; + } + Py_INCREF(s); + PyString_InternInPlace(&s); + return s; +} + +PyDoc_STRVAR(intern_doc, +"intern(string) -> string\n\ +\n\ +``Intern'' the given string. This enters the string in the (global)\n\ +table of interned strings whose purpose is to speed up dictionary lookups.\n\ +Return the string itself or the previously interned string object with the\n\ +same value."); + + /* * Cached interned string objects used for calling the profile and * trace functions. Initialized by trace_init(). @@ -772,6 +811,7 @@ {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, getwindowsversion_doc}, #endif /* MS_WINDOWS */ + {"intern", sys_intern, METH_VARARGS, intern_doc}, #ifdef USE_MALLOPT {"mdebug", sys_mdebug, METH_VARARGS}, #endif Index: Include/stringobject.h =================================================================== --- Include/stringobject.h (Revision 52823) +++ Include/stringobject.h (Arbeitskopie) @@ -28,7 +28,7 @@ Interning strings (ob_sstate) tries to ensure that only one string object with a given value exists, so equality tests can be one pointer comparison. This is generally restricted to strings that "look like" - Python identifiers, although the intern() builtin can be used to force + Python identifiers, although the sys.intern() function can be used to force interning of any string. Together, these sped the interpreter by up to 20%. */ Index: Misc/python-mode.el =================================================================== --- Misc/python-mode.el (Revision 52823) +++ Misc/python-mode.el (Arbeitskopie) @@ -382,7 +382,7 @@ "delattr" "dict" "dir" "divmod" "enumerate" "eval" "execfile" "exit" "file" "filter" "float" "getattr" "globals" "hasattr" - "hash" "hex" "id" "int" "intern" + "hash" "hex" "id" "int" "isinstance" "issubclass" "iter" "len" "license" "list" "locals" "long" "map" "max" "min" "object" "oct" "open" "ord" "pow" "property" "range" Index: Tools/scripts/fixdiv.py =================================================================== --- Tools/scripts/fixdiv.py (Revision 52823) +++ Tools/scripts/fixdiv.py (Arbeitskopie) @@ -198,7 +198,7 @@ list = warnings.get(filename) if list is None: warnings[filename] = list = [] - list.append((int(lineno), intern(what))) + list.append((int(lineno), sys.intern(what))) f.close() return warnings Index: Tools/pybench/Strings.py =================================================================== --- Tools/pybench/Strings.py (Revision 52823) +++ Tools/pybench/Strings.py (Arbeitskopie) @@ -1,5 +1,6 @@ from pybench import Test from string import join +import sys class ConcatStrings(Test): @@ -174,7 +175,7 @@ def test(self): # Make sure the strings *are* interned - s = intern(join(map(str,range(10)))) + s = sys.intern(join(map(str,range(10)))) t = s for i in xrange(self.rounds): @@ -240,7 +241,7 @@ def calibrate(self): - s = intern(join(map(str,range(10)))) + s = sys.intern(join(map(str,range(10)))) t = s for i in xrange(self.rounds): Index: Doc/lib/libsys.tex =================================================================== --- Doc/lib/libsys.tex (Revision 52823) +++ Doc/lib/libsys.tex (Arbeitskopie) @@ -340,6 +340,21 @@ \versionadded{1.5.2} \end{datadesc} +\begin{funcdesc}{intern}{string} + Enter \var{string} in the table of ``interned'' strings and return + the interned string -- which is \var{string} itself or a copy. + Interning strings is useful to gain a little performance on + dictionary lookup -- if the keys in a dictionary are interned, and + the lookup key is interned, the key comparisons (after hashing) can + be done by a pointer compare instead of a string compare. Normally, + the names used in Python programs are automatically interned, and + the dictionaries used to hold module, class or instance attributes + have interned keys. \versionchanged[Interned strings are not + immortal (like they used to be in Python 2.2 and before); + you must keep a reference to the return value of \function{intern()} + around to benefit from it]{2.3} +\end{funcdesc} + \begin{datadesc}{last_type} \dataline{last_value} \dataline{last_traceback} Index: Doc/lib/libfuncs.tex =================================================================== --- Doc/lib/libfuncs.tex (Revision 52823) +++ Doc/lib/libfuncs.tex (Arbeitskopie) @@ -1262,17 +1254,3 @@ argument). \end{funcdesc} -\begin{funcdesc}{intern}{string} - Enter \var{string} in the table of ``interned'' strings and return - the interned string -- which is \var{string} itself or a copy. - Interning strings is useful to gain a little performance on - dictionary lookup -- if the keys in a dictionary are interned, and - the lookup key is interned, the key comparisons (after hashing) can - be done by a pointer compare instead of a string compare. Normally, - the names used in Python programs are automatically interned, and - the dictionaries used to hold module, class or instance attributes - have interned keys. \versionchanged[Interned strings are not - immortal (like they used to be in Python 2.2 and before); - you must keep a reference to the return value of \function{intern()} - around to benefit from it]{2.3} -\end{funcdesc} Index: Doc/tut/tut.tex =================================================================== --- Doc/tut/tut.tex (Revision 52823) +++ Doc/tut/tut.tex (Arbeitskopie) @@ -2700,7 +2700,7 @@ 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'execfile', 'exit', 'file', 'filter', 'float', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', - 'id', 'int', 'intern', 'isinstance', 'issubclass', 'iter', + 'id', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit', 'range', 'reload', 'repr', 'reversed', 'round', 'set', Index: Lib/test/test_builtin.py =================================================================== --- Lib/test/test_builtin.py (Revision 52823) +++ Lib/test/test_builtin.py (Arbeitskopie) @@ -829,30 +819,6 @@ self.assertEqual(int(Foo4()), 42L) self.assertRaises(TypeError, int, Foo5()) - def test_intern(self): - self.assertRaises(TypeError, intern) - s = "never interned before" - self.assert_(intern(s) is s) - s2 = s.swapcase().swapcase() - self.assert_(intern(s2) is s) - - # Subclasses of string can't be interned, because they - # provide too much opportunity for insane things to happen. - # We don't want them in the interned dict and if they aren't - # actually interned, we don't want to create the appearance - # that they are by allowing intern() to succeeed. - class S(str): - def __hash__(self): - return 123 - - self.assertRaises(TypeError, intern, S("abc")) - - # It's still safe to pass these strings to routines that - # call intern internally, e.g. PyObject_SetAttr(). - s = S("abc") - setattr(s, s, s) - self.assertEqual(getattr(s, s), s) - def test_iter(self): self.assertRaises(TypeError, iter) self.assertRaises(TypeError, iter, 42, 42) Index: Lib/test/test_sys.py =================================================================== --- Lib/test/test_sys.py (Revision 52823) +++ Lib/test/test_sys.py (Arbeitskopie) @@ -350,6 +350,31 @@ # the test runs under regrtest. self.assert_(sys.__stdout__.encoding == sys.__stderr__.encoding) + def test_intern(self): + self.assertRaises(TypeError, sys.intern) + s = "never interned before" + self.assert_(sys.intern(s) is s) + s2 = s.swapcase().swapcase() + self.assert_(sys.intern(s2) is s) + + # Subclasses of string can't be interned, because they + # provide too much opportunity for insane things to happen. + # We don't want them in the interned dict and if they aren't + # actually interned, we don't want to create the appearance + # that they are by allowing intern() to succeeed. + class S(str): + def __hash__(self): + return 123 + + self.assertRaises(TypeError, sys.intern, S("abc")) + + # It's still safe to pass these strings to routines that + # call intern internally, e.g. PyObject_SetAttr(). + s = S("abc") + setattr(s, s, s) + self.assertEqual(getattr(s, s), s) + + def test_main(): test.test_support.run_unittest(SysModuleTest)