FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Issue #27942: String constants now interned recursively in tuples and… · python/cpython@3738c2d · GitHub

Repository navigation

Commit 3738c2d

Browse files
Issue #27942: String constants now interned recursively in tuples and frozensets.
2 parents c6b5f08 + 00a0fc1 commit 3738c2d

5 files changed

Lines changed: 3706 additions & 3633 deletions

File tree

‎Lib/test/test_code.py‎

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
103103
"""
104104

105+
import sys
105106
import unittest
106107
import weakref
107108
from test.support import run_doctest, run_unittest, cpython_only
@@ -134,6 +135,43 @@ def test_newempty(self):
134135
self.assertEqual(co.co_name, "funcname")
135136
self.assertEqual(co.co_firstlineno, 15)
136137

138+
class CodeConstsTest(unittest.TestCase):
139+
140+
def find_const(self, consts, value):
141+
for v in consts:
142+
if v == value:
143+
return v
144+
self.assertIn(value, consts) # rises an exception
145+
self.fail('Should be never reached')
146+
147+
def assertIsInterned(self, s):
148+
if s is not sys.intern(s):
149+
self.fail('String %r is not interned' % (s,))
150+
151+
@cpython_only
152+
def test_interned_string(self):
153+
co = compile('res = "str_value"', '?', 'exec')
154+
v = self.find_const(co.co_consts, 'str_value')
155+
self.assertIsInterned(v)
156+
157+
@cpython_only
158+
def test_interned_string_in_tuple(self):
159+
co = compile('res = ("str_value",)', '?', 'exec')
160+
v = self.find_const(co.co_consts, ('str_value',))
161+
self.assertIsInterned(v[0])
162+
163+
@cpython_only
164+
def test_interned_string_in_frozenset(self):
165+
co = compile('res = a in {"str_value"}', '?', 'exec')
166+
v = self.find_const(co.co_consts, frozenset(('str_value',)))
167+
self.assertIsInterned(tuple(v)[0])
168+
169+
@cpython_only
170+
def test_interned_string_default(self):
171+
def f(a='str_value'):
172+
return a
173+
self.assertIsInterned(f())
174+
137175

138176
class CodeWeakRefTest(unittest.TestCase):
139177

@@ -163,7 +201,7 @@ def callback(code):
163201
def test_main(verbose=None):
164202
from test import test_code
165203
run_doctest(test_code, verbose)
166-
run_unittest(CodeTest, CodeWeakRefTest)
204+
run_unittest(CodeTest, CodeConstsTest, CodeWeakRefTest)
167205

168206

169207
if __name__ == "__main__":

‎Misc/NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ What's New in Python 3.6.0 beta 2
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #27942: String constants now interned recursively in tuples and frozensets.
14+
1315
- Issue #21578: Fixed misleading error message when ImportError called with
1416
invalid keyword args.
1517

‎Objects/codeobject.c‎

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,50 @@ intern_strings(PyObject *tuple)
5454
}
5555
}
5656

57+
/* Intern selected string constants */
58+
static int
59+
intern_string_constants(PyObject *tuple)
60+
{
61+
int modified = 0;
62+
Py_ssize_t i;
63+
64+
for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
65+
PyObject *v = PyTuple_GET_ITEM(tuple, i);
66+
if (PyUnicode_CheckExact(v)) {
67+
if (all_name_chars(v)) {
68+
PyObject *w = v;
69+
PyUnicode_InternInPlace(&v);
70+
if (w != v) {
71+
PyTuple_SET_ITEM(tuple, i, v);
72+
modified = 1;
73+
}
74+
}
75+
}
76+
else if (PyTuple_CheckExact(v)) {
77+
intern_string_constants(v);
78+
}
79+
else if (PyFrozenSet_CheckExact(v)) {
80+
PyObject *tmp = PySequence_Tuple(v);
81+
if (tmp == NULL) {
82+
PyErr_Clear();
83+
continue;
84+
}
85+
if (intern_string_constants(tmp)) {
86+
v = PyFrozenSet_New(tmp);
87+
if (v == NULL) {
88+
PyErr_Clear();
89+
}
90+
else {
91+
PyTuple_SET_ITEM(tuple, i, v);
92+
modified = 1;
93+
}
94+
}
95+
Py_DECREF(tmp);
96+
}
97+
}
98+
return modified;
99+
}
100+
57101

58102
PyCodeObject *
59103
PyCode_New(int argcount, int kwonlyargcount,
@@ -92,13 +136,7 @@ PyCode_New(int argcount, int kwonlyargcount,
92136
intern_strings(varnames);
93137
intern_strings(freevars);
94138
intern_strings(cellvars);
95-
/* Intern selected string constants */
96-
for (i = PyTuple_GET_SIZE(consts); --i >= 0; ) {
97-
PyObject *v = PyTuple_GetItem(consts, i);
98-
if (!all_name_chars(v))
99-
continue;
100-
PyUnicode_InternInPlace(&PyTuple_GET_ITEM(consts, i));
101-
}
139+
intern_string_constants(consts);
102140
/* Create mapping between cells and arguments if needed. */
103141
if (n_cellvars) {
104142
Py_ssize_t total_args = argcount + kwonlyargcount +

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL