| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -102,6 +102,7 @@ | |||
| 102 | 102 | ||
| 103 | 103 | """ | |
| 104 | 104 | ||
| 105 | + import sys | ||
| 105 | 106 | import unittest | |
| 106 | 107 | import weakref | |
| 107 | 108 | from test.support import run_doctest, run_unittest, cpython_only | |
@@ -134,6 +135,43 @@ def test_newempty(self): | |||
| 134 | 135 | self.assertEqual(co.co_name, "funcname") | |
| 135 | 136 | self.assertEqual(co.co_firstlineno, 15) | |
| 136 | 137 | ||
| 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 | + | ||
| 137 | 175 | ||
| 138 | 176 | class CodeWeakRefTest(unittest.TestCase): | |
| 139 | 177 | ||
@@ -163,7 +201,7 @@ def callback(code): | |||
| 163 | 201 | def test_main(verbose=None): | |
| 164 | 202 | from test import test_code | |
| 165 | 203 | run_doctest(test_code, verbose) | |
| 166 | - run_unittest(CodeTest, CodeWeakRefTest) | ||
| 204 | + run_unittest(CodeTest, CodeConstsTest, CodeWeakRefTest) | ||
| 167 | 205 | ||
| 168 | 206 | ||
| 169 | 207 | if __name__ == "__main__": | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,8 @@ What's New in Python 3.6.0 beta 2 | |||
| 10 | 10 | Core and Builtins | |
| 11 | 11 | ----------------- | |
| 12 | 12 | ||
| 13 | + - Issue #27942: String constants now interned recursively in tuples and frozensets. | ||
| 14 | + | ||
| 13 | 15 | - Issue #21578: Fixed misleading error message when ImportError called with | |
| 14 | 16 | invalid keyword args. | |
| 15 | 17 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -54,6 +54,50 @@ intern_strings(PyObject *tuple) | |||
| 54 | 54 | } | |
| 55 | 55 | } | |
| 56 | 56 | ||
| 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 | + | ||
| 57 | 101 | ||
| 58 | 102 | PyCodeObject * | |
| 59 | 103 | PyCode_New(int argcount, int kwonlyargcount, | |
@@ -92,13 +136,7 @@ PyCode_New(int argcount, int kwonlyargcount, | |||
| 92 | 136 | intern_strings(varnames); | |
| 93 | 137 | intern_strings(freevars); | |
| 94 | 138 | 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); | ||
| 102 | 140 | /* Create mapping between cells and arguments if needed. */ | |
| 103 | 141 | if (n_cellvars) { | |
| 104 | 142 | Py_ssize_t total_args = argcount + kwonlyargcount + | |
| Back | FazBrowse Home | New Git URL |
0 commit comments