[Python-checkins] cpython (merge 2.7 -> 2.7): merge heads
benjamin.peterson
python-checkins at python.org
Mon Mar 19 02:23:35 CET 2012
http://hg.python.org/cpython/rev/22db03646d9b
changeset: 75832:22db03646d9b
branch: 2.7
parent: 75831:9f0bf9992664
parent: 75825:ad030571e6c0
user: Benjamin Peterson <benjamin at python.org>
date: Sun Mar 18 21:23:22 2012 -0400
summary:
merge heads
files:
.hgtags | 2 +
Doc/faq/design.rst | 10 +-
Doc/library/email.encoders.rst | 4 +
Doc/library/json.rst | 8 +
Doc/library/re.rst | 30 +----
Lib/test/test_queue.py | 8 +-
Mac/README | 10 +-
Misc/NEWS | 3 +
Python/import.c | 126 +++++++++++++++-----
9 files changed, 130 insertions(+), 71 deletions(-)
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -137,6 +137,8 @@
c1dc9e7986a2a8e1070ec7bee748520febef382e v2.6.6rc1
e189dc8fd66154ef46d9cd22584d56669b544ca3 v2.6.6rc2
9f8771e0905277f8b3c2799113a062fda4164995 v2.6.6
+caab08cd2b3eb5a6f78479b2513b65d36c754f41 v2.6.8rc1
+1d1b7b9fad48bd0dc60dc8a06cca4459ef273127 v2.6.8rc2
b4107eb00b4271fb73a9e1b736d4f23460950778 v2.7a1
adc85ebc7271cc22e24e816782bb2b8d7fa3a6b3 v2.7a2
4180557b7a9bb9dd5341a18af199f843f199e46e v2.7a3
diff --git a/Doc/faq/design.rst b/Doc/faq/design.rst
--- a/Doc/faq/design.rst
+++ b/Doc/faq/design.rst
@@ -297,8 +297,9 @@
How fast are exceptions?
------------------------
-A try/except block is extremely efficient. Actually catching an exception is
-expensive. In versions of Python prior to 2.0 it was common to use this idiom::
+A try/except block is extremely efficient if no exceptions are raised. Actually
+catching an exception is expensive. In versions of Python prior to 2.0 it was
+common to use this idiom::
try:
value = mydict[key]
@@ -309,11 +310,10 @@
This only made sense when you expected the dict to have the key almost all the
time. If that wasn't the case, you coded it like this::
- if mydict.has_key(key):
+ if key in mydict:
value = mydict[key]
else:
- mydict[key] = getvalue(key)
- value = mydict[key]
+ value = mydict[key] = getvalue(key)
.. note::
diff --git a/Doc/library/email.encoders.rst b/Doc/library/email.encoders.rst
--- a/Doc/library/email.encoders.rst
+++ b/Doc/library/email.encoders.rst
@@ -18,6 +18,10 @@
payload, encode it, and reset the payload to this newly encoded value. They
should also set the :mailheader:`Content-Transfer-Encoding` header as appropriate.
+Note that these functions are not meaningful for a multipart message. They
+must be applied to individual subparts instead, and will raise a
+:exc:`TypeError` if passed a message whose type is multipart.
+
Here are the encoding functions provided:
diff --git a/Doc/library/json.rst b/Doc/library/json.rst
--- a/Doc/library/json.rst
+++ b/Doc/library/json.rst
@@ -170,6 +170,14 @@
:class:`unicode` instance. The other arguments have the same meaning as in
:func:`dump`.
+ .. note::
+
+ Keys in key/value pairs of JSON are always of the type :class:`str`. When
+ a dictionary is converted into JSON, all the keys of the dictionary are
+ coerced to strings. As a result of this, if a dictionary is convered
+ into JSON and then back into a dictionary, the dictionary may not equal
+ the original one. That is, ``loads(dumps(x)) != x`` if x has non-string
+ keys.
.. function:: load(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])
diff --git a/Doc/library/re.rst b/Doc/library/re.rst
--- a/Doc/library/re.rst
+++ b/Doc/library/re.rst
@@ -766,8 +766,8 @@
.. attribute:: RegexObject.flags
- The flags argument used when the RE object was compiled, or ``0`` if no flags
- were provided.
+ The regex matching flags. This is a combination of the flags given to
+ :func:`.compile` and any ``(?...)`` inline flags in the pattern.
.. attribute:: RegexObject.groups
@@ -1077,28 +1077,6 @@
(\S+) - (\d+) errors, (\d+) warnings
-Avoiding recursion
-^^^^^^^^^^^^^^^^^^
-
-If you create regular expressions that require the engine to perform a lot of
-recursion, you may encounter a :exc:`RuntimeError` exception with the message
-``maximum recursion limit`` exceeded. For example, ::
-
- >>> s = 'Begin ' + 1000*'a very long string ' + 'end'
- >>> re.match('Begin (\w| )*? end', s).end()
- Traceback (most recent call last):
- File "<stdin>", line 1, in ?
- File "/usr/local/lib/python2.5/re.py", line 132, in match
- return _compile(pattern, flags).match(string)
- RuntimeError: maximum recursion limit exceeded
-
-You can often restructure your regular expression to avoid recursion.
-
-Starting with Python 2.3, simple uses of the ``*?`` pattern are special-cased to
-avoid recursion. Thus, the above regular expression can avoid recursion by
-being recast as ``Begin [a-zA-Z0-9_ ]*?end``. As a further benefit, such
-regular expressions will run faster than their recursive equivalents.
-
.. _search-vs-match:
search() vs. match()
@@ -1145,7 +1123,7 @@
First, here is the input. Normally it may come from a file, here we are using
triple-quoted string syntax:
- >>> input = """Ross McFluff: 834.345.1254 155 Elm Street
+ >>> text = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
@@ -1159,7 +1137,7 @@
.. doctest::
:options: +NORMALIZE_WHITESPACE
- >>> entries = re.split("\n+", input)
+ >>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
diff --git a/Lib/test/test_queue.py b/Lib/test/test_queue.py
--- a/Lib/test/test_queue.py
+++ b/Lib/test/test_queue.py
@@ -79,7 +79,7 @@
self.fail("trigger thread ended but event never set")
-class BaseQueueTest(unittest.TestCase, BlockingTestMixin):
+class BaseQueueTest(BlockingTestMixin):
def setUp(self):
self.cum = 0
self.cumlock = threading.Lock()
@@ -191,13 +191,13 @@
self.simple_queue_test(q)
-class QueueTest(BaseQueueTest):
+class QueueTest(BaseQueueTest, unittest.TestCase):
type2test = Queue.Queue
-class LifoQueueTest(BaseQueueTest):
+class LifoQueueTest(BaseQueueTest, unittest.TestCase):
type2test = Queue.LifoQueue
-class PriorityQueueTest(BaseQueueTest):
+class PriorityQueueTest(BaseQueueTest, unittest.TestCase):
type2test = Queue.PriorityQueue
diff --git a/Mac/README b/Mac/README
--- a/Mac/README
+++ b/Mac/README
@@ -70,7 +70,7 @@
$ make
$ make install
-This flag can be used a framework build of python, but also with a classic
+This flag can be used with a framework build of python, but also with a classic
unix build. Either way you will have to build python on Mac OS X 10.4 (or later)
with Xcode 2.1 (or later). You also have to install the 10.4u SDK when
installing Xcode.
@@ -221,8 +221,8 @@
Go to the directory "Mac/OSX/BuildScript". There you'll find a script
"build-installer.py" that does all the work. This will download and build
-a number of 3th-party libaries, configures and builds a framework Python,
-installs it, creates the installer pacakge files and then packs this in a
+a number of 3rd-party libaries, configures and builds a framework Python,
+installs it, creates the installer package files and then packs this in a
DMG image.
The script will build a universal binary, you'll therefore have to run this
@@ -258,8 +258,8 @@
Uninstalling a framework install, including the binary installer
================================================================
-Uninstalling a framework can be done by manually removing all bits that got installed,
-that's true for both installations from source and installations using the binary installer.
+Uninstalling a framework can be done by manually removing all bits that got installed.
+That's true for both installations from source and installations using the binary installer.
Sadly enough OSX does not have a central uninstaller.
The main bit of a framework install is the framework itself, installed in
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -9,6 +9,9 @@
Core and Builtins
-----------------
+- Issue #14331: Use significantly less stack space when importing modules by
+ allocating path buffers on the heap instead of the stack.
+
- Issue #14334: Prevent in a segfault in type.__getattribute__ when it was not
passed strings. Also fix segfaults in the __getattribute__ and __setattr__
methods of old-style classes.
diff --git a/Python/import.c b/Python/import.c
--- a/Python/import.c
+++ b/Python/import.c
@@ -996,7 +996,7 @@
{
struct stat st;
FILE *fpc;
- char buf[MAXPATHLEN+1];
+ char *buf;
char *cpathname;
PyCodeObject *co;
PyObject *m;
@@ -1015,6 +1015,10 @@
*/
st.st_mtime &= 0xFFFFFFFF;
}
+ buf = PyMem_MALLOC(MAXPATHLEN+1);
+ if (buf == NULL) {
+ return PyErr_NoMemory();
+ }
cpathname = make_compiled_pathname(pathname, buf,
(size_t)MAXPATHLEN + 1);
if (cpathname != NULL &&
@@ -1022,9 +1026,9 @@
co = read_compiled_module(cpathname, fpc);
fclose(fpc);
if (co == NULL)
- return NULL;
+ goto error_exit;
if (update_compiled_module(co, pathname) < 0)
- return NULL;
+ goto error_exit;
if (Py_VerboseFlag)
PySys_WriteStderr("import %s # precompiled from %s\n",
name, cpathname);
@@ -1033,7 +1037,7 @@
else {
co = parse_source_module(pathname, fp);
if (co == NULL)
- return NULL;
+ goto error_exit;
if (Py_VerboseFlag)
PySys_WriteStderr("import %s # from %s\n",
name, pathname);
@@ -1046,7 +1050,12 @@
m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname);
Py_DECREF(co);
+ PyMem_FREE(buf);
return m;
+
+error_exit:
+ PyMem_FREE(buf);
+ return NULL;
}
@@ -1066,7 +1075,7 @@
PyObject *file = NULL;
PyObject *path = NULL;
int err;
- char buf[MAXPATHLEN+1];
+ char *buf = NULL;
FILE *fp = NULL;
struct filedescr *fdp;
@@ -1088,8 +1097,13 @@
err = PyDict_SetItemString(d, "__path__", path);
if (err != 0)
goto error;
+ buf = PyMem_MALLOC(MAXPATHLEN+1);
+ if (buf == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
buf[0] = '\0';
- fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL);
+ fdp = find_module(name, "__init__", path, buf, MAXPATHLEN+1, &fp, NULL);
if (fdp == NULL) {
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
PyErr_Clear();
@@ -1107,6 +1121,8 @@
error:
m = NULL;
cleanup:
+ if (buf)
+ PyMem_FREE(buf);
Py_XDECREF(path);
Py_XDECREF(file);
return m;
@@ -1235,7 +1251,7 @@
static struct filedescr fd_frozen = {"", "", PY_FROZEN};
static struct filedescr fd_builtin = {"", "", C_BUILTIN};
static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
- char name[MAXPATHLEN+1];
+ char *name;
#if defined(PYOS_OS2)
size_t saved_len;
size_t saved_namelen;
@@ -1249,6 +1265,10 @@
"module name is too long");
return NULL;
}
+ name = PyMem_MALLOC(MAXPATHLEN+1);
+ if (name == NULL) {
+ return PyErr_NoMemory();
+ }
strcpy(name, subname);
/* sys.meta_path import hook */
@@ -1260,7 +1280,7 @@
PyErr_SetString(PyExc_RuntimeError,
"sys.meta_path must be a list of "
"import hooks");
- return NULL;
+ goto error_exit;
}
Py_INCREF(meta_path); /* zap guard */
npath = PyList_Size(meta_path);
@@ -1273,12 +1293,13 @@
path : Py_None);
if (loader == NULL) {
Py_DECREF(meta_path);
- return NULL; /* true error */
+ goto error_exit; /* true error */
}
if (loader != Py_None) {
/* a loader was found */
*p_loader = loader;
Py_DECREF(meta_path);
+ PyMem_FREE(name);
return &importhookdescr;
}
Py_DECREF(loader);
@@ -1292,7 +1313,7 @@
if (PyString_Size(path) + 1 + strlen(name) >= (size_t)buflen) {
PyErr_SetString(PyExc_ImportError,
"full frozen module name too long");
- return NULL;
+ goto error_exit;
}
strcpy(buf, PyString_AsString(path));
strcat(buf, ".");
@@ -1300,19 +1321,22 @@
strcpy(name, buf);
if (find_frozen(name) != NULL) {
strcpy(buf, name);
+ PyMem_FREE(name);
return &fd_frozen;
}
PyErr_Format(PyExc_ImportError,
"No frozen submodule named %.200s", name);
- return NULL;
+ goto error_exit;
}
if (path == NULL) {
if (is_builtin(name)) {
strcpy(buf, name);
+ PyMem_FREE(name);
return &fd_builtin;
}
if ((find_frozen(name)) != NULL) {
strcpy(buf, name);
+ PyMem_FREE(name);
return &fd_frozen;
}
@@ -1320,6 +1344,7 @@
fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen);
if (fp != NULL) {
*p_fp = fp;
+ PyMem_FREE(name);
return fdp;
}
#endif
@@ -1328,7 +1353,7 @@
if (path == NULL || !PyList_Check(path)) {
PyErr_SetString(PyExc_RuntimeError,
"sys.path must be a list of directory names");
- return NULL;
+ goto error_exit;
}
path_hooks = PySys_GetObject("path_hooks");
@@ -1336,14 +1361,14 @@
PyErr_SetString(PyExc_RuntimeError,
"sys.path_hooks must be a list of "
"import hooks");
- return NULL;
+ goto error_exit;
}
path_importer_cache = PySys_GetObject("path_importer_cache");
if (path_importer_cache == NULL ||
!PyDict_Check(path_importer_cache)) {
PyErr_SetString(PyExc_RuntimeError,
"sys.path_importer_cache must be a dict");
- return NULL;
+ goto error_exit;
}
npath = PyList_Size(path);
@@ -1352,13 +1377,13 @@
PyObject *copy = NULL;
PyObject *v = PyList_GetItem(path, i);
if (!v)
- return NULL;
+ goto error_exit;
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(v)) {
copy = PyUnicode_Encode(PyUnicode_AS_UNICODE(v),
PyUnicode_GET_SIZE(v), Py_FileSystemDefaultEncoding, NULL);
if (copy == NULL)
- return NULL;
+ goto error_exit;
v = copy;
}
else
@@ -1384,7 +1409,7 @@
path_hooks, v);
if (importer == NULL) {
Py_XDECREF(copy);
- return NULL;
+ goto error_exit;
}
/* Note: importer is a borrowed reference */
if (importer != Py_None) {
@@ -1394,10 +1419,11 @@
"s", fullname);
Py_XDECREF(copy);
if (loader == NULL)
- return NULL; /* error */
+ goto error_exit; /* error */
if (loader != Py_None) {
/* a loader was found */
*p_loader = loader;
+ PyMem_FREE(name);
return &importhookdescr;
}
Py_DECREF(loader);
@@ -1421,6 +1447,7 @@
case_ok(buf, len, namelen, name)) { /* case matches */
if (find_init_module(buf)) { /* and has __init__.py */
Py_XDECREF(copy);
+ PyMem_FREE(name);
return &fd_package;
}
else {
@@ -1431,7 +1458,7 @@
if (PyErr_Warn(PyExc_ImportWarning,
warnstr)) {
Py_XDECREF(copy);
- return NULL;
+ goto error_exit;
}
}
}
@@ -1506,10 +1533,15 @@
if (fp == NULL) {
PyErr_Format(PyExc_ImportError,
"No module named %.200s", name);
- return NULL;
+ goto error_exit;
}
*p_fp = fp;
+ PyMem_FREE(name);
return fdp;
+
+error_exit:
+ PyMem_FREE(name);
+ return NULL;
}
/* Helpers for main.c
@@ -2116,7 +2148,7 @@
import_module_level(char *name, PyObject *globals, PyObject *locals,
PyObject *fromlist, int level)
{
- char buf[MAXPATHLEN+1];
+ char *buf;
Py_ssize_t buflen = 0;
PyObject *parent, *head, *next, *tail;
@@ -2130,14 +2162,18 @@
return NULL;
}
+ buf = PyMem_MALLOC(MAXPATHLEN+1);
+ if (buf == NULL) {
+ return PyErr_NoMemory();
+ }
parent = get_parent(globals, buf, &buflen, level);
if (parent == NULL)
- return NULL;
+ goto error_exit;
head = load_next(parent, level < 0 ? Py_None : parent, &name, buf,
&buflen);
if (head == NULL)
- return NULL;
+ goto error_exit;
tail = head;
Py_INCREF(tail);
@@ -2146,7 +2182,7 @@
Py_DECREF(tail);
if (next == NULL) {
Py_DECREF(head);
- return NULL;
+ goto error_exit;
}
tail = next;
}
@@ -2158,7 +2194,7 @@
Py_DECREF(head);
PyErr_SetString(PyExc_ValueError,
"Empty module name");
- return NULL;
+ goto error_exit;
}
if (fromlist != NULL) {
@@ -2168,16 +2204,22 @@
if (fromlist == NULL) {
Py_DECREF(tail);
+ PyMem_FREE(buf);
return head;
}
Py_DECREF(head);
if (!ensure_fromlist(tail, fromlist, buf, buflen, 0)) {
Py_DECREF(tail);
- return NULL;
+ goto error_exit;
}
+ PyMem_FREE(buf);
return tail;
+
+error_exit:
+ PyMem_FREE(buf);
+ return NULL;
}
PyObject *
@@ -2567,7 +2609,7 @@
}
else {
PyObject *path, *loader = NULL;
- char buf[MAXPATHLEN+1];
+ char *buf;
struct filedescr *fdp;
FILE *fp = NULL;
@@ -2582,11 +2624,16 @@
}
}
+ buf = PyMem_MALLOC(MAXPATHLEN+1);
+ if (buf == NULL) {
+ return PyErr_NoMemory();
+ }
buf[0] = '\0';
fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1,
&fp, &loader);
Py_XDECREF(path);
if (fdp == NULL) {
+ PyMem_FREE(buf);
if (!PyErr_ExceptionMatches(PyExc_ImportError))
return NULL;
PyErr_Clear();
@@ -2601,6 +2648,7 @@
Py_XDECREF(m);
m = NULL;
}
+ PyMem_FREE(buf);
}
return m;
@@ -2618,7 +2666,7 @@
PyObject *modules = PyImport_GetModuleDict();
PyObject *path = NULL, *loader = NULL, *existing_m = NULL;
char *name, *subname;
- char buf[MAXPATHLEN+1];
+ char *buf;
struct filedescr *fdp;
FILE *fp = NULL;
PyObject *newm;
@@ -2678,6 +2726,11 @@
if (path == NULL)
PyErr_Clear();
}
+ buf = PyMem_MALLOC(MAXPATHLEN+1);
+ if (buf == NULL) {
+ Py_XDECREF(path);
+ return PyErr_NoMemory();
+ }
buf[0] = '\0';
fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, &loader);
Py_XDECREF(path);
@@ -2685,6 +2738,7 @@
if (fdp == NULL) {
Py_XDECREF(loader);
imp_modules_reloading_clear();
+ PyMem_FREE(buf);
return NULL;
}
@@ -2702,6 +2756,7 @@
PyDict_SetItemString(modules, name, m);
}
imp_modules_reloading_clear();
+ PyMem_FREE(buf);
return newm;
}
@@ -2832,19 +2887,27 @@
extern int fclose(FILE *);
PyObject *fob, *ret;
struct filedescr *fdp;
- char pathname[MAXPATHLEN+1];
+ char *pathname;
FILE *fp = NULL;
+ pathname = PyMem_MALLOC(MAXPATHLEN+1);
+ if (pathname == NULL) {
+ return PyErr_NoMemory();
+ }
pathname[0] = '\0';
if (path == Py_None)
path = NULL;
fdp = find_module(NULL, name, path, pathname, MAXPATHLEN+1, &fp, NULL);
- if (fdp == NULL)
+ if (fdp == NULL) {
+ PyMem_FREE(pathname);
return NULL;
+ }
if (fp != NULL) {
fob = PyFile_FromFile(fp, pathname, fdp->mode, fclose);
- if (fob == NULL)
+ if (fob == NULL) {
+ PyMem_FREE(pathname);
return NULL;
+ }
}
else {
fob = Py_None;
@@ -2853,6 +2916,7 @@
ret = Py_BuildValue("Os(ssi)",
fob, pathname, fdp->suffix, fdp->mode, fdp->type);
Py_DECREF(fob);
+ PyMem_FREE(pathname);
return ret;
}
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list