Merge to tip.

This commit is contained in:
Brian Quinlan 2011-04-08 08:30:41 +10:00
commit d08b330a15
7 changed files with 61 additions and 21 deletions

View File

@ -28,7 +28,7 @@ tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*')
# make it correctly strict without breaking backward compatibility. # make it correctly strict without breaking backward compatibility.
attrfind = re.compile( attrfind = re.compile(
r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*' r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*'
r'(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~@]*))?') r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?')
attrfind_tolerant = re.compile( attrfind_tolerant = re.compile(
r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*' r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*'
r'(\'[^\']*\'|"[^"]*"|[^>\s]*))?') r'(\'[^\']*\'|"[^"]*"|[^>\s]*))?')

View File

@ -240,7 +240,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
findleaks=False, use_resources=None, trace=False, coverdir='coverage', findleaks=False, use_resources=None, trace=False, coverdir='coverage',
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False, runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
random_seed=None, use_mp=None, verbose3=False, forever=False, random_seed=None, use_mp=None, verbose3=False, forever=False,
header=False, timeout=30*60): header=False, timeout=60*60):
"""Execute a test suite. """Execute a test suite.
This also parses command-line options and modifies its behavior This also parses command-line options and modifies its behavior

View File

@ -8,6 +8,12 @@ from test import support, script_helper
import tempfile import tempfile
import unittest import unittest
try:
import threading
HAVE_THREADS = True
except ImportError:
HAVE_THREADS = False
TIMEOUT = 0.5 TIMEOUT = 0.5
try: try:
@ -279,6 +285,7 @@ funcA()
with temporary_filename() as filename: with temporary_filename() as filename:
self.check_dump_traceback(filename) self.check_dump_traceback(filename)
@unittest.skipIf(not HAVE_THREADS, 'need threads')
def check_dump_traceback_threads(self, filename): def check_dump_traceback_threads(self, filename):
""" """
Call explicitly dump_traceback(all_threads=True) and check the output. Call explicitly dump_traceback(all_threads=True) and check the output.

View File

@ -217,6 +217,23 @@ DOCTYPE html [
("starttag", "a", [("href", "mailto:xyz@example.com")]), ("starttag", "a", [("href", "mailto:xyz@example.com")]),
]) ])
def test_attr_nonascii(self):
# see issue 7311
self._run_check("<img src=/foo/bar.png alt=\u4e2d\u6587>", [
("starttag", "img", [("src", "/foo/bar.png"),
("alt", "\u4e2d\u6587")]),
])
self._run_check("<a title='\u30c6\u30b9\u30c8' "
"href='\u30c6\u30b9\u30c8.html'>", [
("starttag", "a", [("title", "\u30c6\u30b9\u30c8"),
("href", "\u30c6\u30b9\u30c8.html")]),
])
self._run_check('<a title="\u30c6\u30b9\u30c8" '
'href="\u30c6\u30b9\u30c8.html">', [
("starttag", "a", [("title", "\u30c6\u30b9\u30c8"),
("href", "\u30c6\u30b9\u30c8.html")]),
])
def test_attr_entity_replacement(self): def test_attr_entity_replacement(self):
self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [ self._run_check("""<a b='&amp;&gt;&lt;&quot;&apos;'>""", [
("starttag", "a", [("b", "&><\"'")]), ("starttag", "a", [("b", "&><\"'")]),

View File

@ -94,6 +94,8 @@ Core and Builtins
Library Library
------- -------
- Issue #7311: fix html.parser to accept non-ASCII attribute values.
- Issue #11605: email.parser.BytesFeedParser was incorrectly converting multipart - Issue #11605: email.parser.BytesFeedParser was incorrectly converting multipart
subpararts with an 8bit CTE into unicode instead of preserving the bytes. subpararts with an 8bit CTE into unicode instead of preserving the bytes.

View File

@ -5,6 +5,9 @@
#include <frameobject.h> #include <frameobject.h>
#include <signal.h> #include <signal.h>
/* Allocate at maximum 100 MB of the stack to raise the stack overflow */
#define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
#ifdef WITH_THREAD #ifdef WITH_THREAD
# define FAULTHANDLER_LATER # define FAULTHANDLER_LATER
#endif #endif
@ -16,9 +19,6 @@
# define FAULTHANDLER_USER # define FAULTHANDLER_USER
#endif #endif
/* Allocate at maximum 100 MB of the stack to raise the stack overflow */
#define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
#define PUTS(fd, str) write(fd, str, strlen(str)) #define PUTS(fd, str) write(fd, str, strlen(str))
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
@ -218,12 +218,7 @@ faulthandler_dump_traceback_py(PyObject *self,
This function is signal safe and should only call signal safe functions. */ This function is signal safe and should only call signal safe functions. */
static void static void
faulthandler_fatal_error( faulthandler_fatal_error(int signum)
int signum
#ifdef HAVE_SIGACTION
, siginfo_t *siginfo, void *ucontext
#endif
)
{ {
const int fd = fatal_error.fd; const int fd = fatal_error.fd;
unsigned int i; unsigned int i;
@ -255,6 +250,7 @@ faulthandler_fatal_error(
PUTS(fd, handler->name); PUTS(fd, handler->name);
PUTS(fd, "\n\n"); PUTS(fd, "\n\n");
#ifdef WITH_THREAD
/* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and
so are delivered to the thread that caused the fault. Get the Python so are delivered to the thread that caused the fault. Get the Python
thread state of the current thread. thread state of the current thread.
@ -264,6 +260,9 @@ faulthandler_fatal_error(
used. Read the thread local storage (TLS) instead: call used. Read the thread local storage (TLS) instead: call
PyGILState_GetThisThreadState(). */ PyGILState_GetThisThreadState(). */
tstate = PyGILState_GetThisThreadState(); tstate = PyGILState_GetThisThreadState();
#else
tstate = PyThreadState_Get();
#endif
if (tstate == NULL) if (tstate == NULL)
return; return;
@ -320,7 +319,7 @@ faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
for (i=0; i < faulthandler_nsignals; i++) { for (i=0; i < faulthandler_nsignals; i++) {
handler = &faulthandler_handlers[i]; handler = &faulthandler_handlers[i];
#ifdef HAVE_SIGACTION #ifdef HAVE_SIGACTION
action.sa_sigaction = faulthandler_fatal_error; action.sa_handler = faulthandler_fatal_error;
sigemptyset(&action.sa_mask); sigemptyset(&action.sa_mask);
/* Do not prevent the signal from being received from within /* Do not prevent the signal from being received from within
its own signal handler */ its own signal handler */
@ -451,8 +450,8 @@ faulthandler_cancel_dump_tracebacks_later(void)
} }
static PyObject* static PyObject*
faulthandler_dump_traceback_later(PyObject *self, faulthandler_dump_tracebacks_later(PyObject *self,
PyObject *args, PyObject *kwargs) PyObject *args, PyObject *kwargs)
{ {
static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL}; static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL};
double timeout; double timeout;
@ -461,6 +460,7 @@ faulthandler_dump_traceback_later(PyObject *self,
PyObject *file = NULL; PyObject *file = NULL;
int fd; int fd;
int exit = 0; int exit = 0;
PyThreadState *tstate;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"d|iOi:dump_tracebacks_later", kwlist, "d|iOi:dump_tracebacks_later", kwlist,
@ -477,6 +477,13 @@ faulthandler_dump_traceback_later(PyObject *self,
return NULL; return NULL;
} }
tstate = PyThreadState_Get();
if (tstate == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"unable to get the current thread state");
return NULL;
}
file = faulthandler_get_fileno(file, &fd); file = faulthandler_get_fileno(file, &fd);
if (file == NULL) if (file == NULL)
return NULL; return NULL;
@ -490,7 +497,7 @@ faulthandler_dump_traceback_later(PyObject *self,
thread.fd = fd; thread.fd = fd;
thread.timeout_ms = timeout_ms; thread.timeout_ms = timeout_ms;
thread.repeat = repeat; thread.repeat = repeat;
thread.interp = PyThreadState_Get()->interp; thread.interp = tstate->interp;
thread.exit = exit; thread.exit = exit;
/* Arm these locks to serve as events when released */ /* Arm these locks to serve as events when released */
@ -537,10 +544,14 @@ faulthandler_user(int signum)
if (!user->enabled) if (!user->enabled)
return; return;
#ifdef WITH_THREAD
/* PyThreadState_Get() doesn't give the state of the current thread if /* PyThreadState_Get() doesn't give the state of the current thread if
the thread doesn't hold the GIL. Read the thread local storage (TLS) the thread doesn't hold the GIL. Read the thread local storage (TLS)
instead: call PyGILState_GetThisThreadState(). */ instead: call PyGILState_GetThisThreadState(). */
tstate = PyGILState_GetThisThreadState(); tstate = PyGILState_GetThisThreadState();
#else
tstate = PyThreadState_Get();
#endif
if (user->all_threads) if (user->all_threads)
_Py_DumpTracebackThreads(user->fd, user->interp, tstate); _Py_DumpTracebackThreads(user->fd, user->interp, tstate);
@ -826,7 +837,7 @@ static int
faulthandler_traverse(PyObject *module, visitproc visit, void *arg) faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
{ {
#ifdef FAULTHANDLER_USER #ifdef FAULTHANDLER_USER
unsigned int index; unsigned int signum;
#endif #endif
#ifdef FAULTHANDLER_LATER #ifdef FAULTHANDLER_LATER
@ -834,8 +845,8 @@ faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
#endif #endif
#ifdef FAULTHANDLER_USER #ifdef FAULTHANDLER_USER
if (user_signals != NULL) { if (user_signals != NULL) {
for (index=0; index < NSIG; index++) for (signum=0; signum < NSIG; signum++)
Py_VISIT(user_signals[index].file); Py_VISIT(user_signals[signum].file);
} }
#endif #endif
Py_VISIT(fatal_error.file); Py_VISIT(fatal_error.file);
@ -861,10 +872,11 @@ static PyMethodDef module_methods[] = {
"if all_threads is True, into file")}, "if all_threads is True, into file")},
#ifdef FAULTHANDLER_LATER #ifdef FAULTHANDLER_LATER
{"dump_tracebacks_later", {"dump_tracebacks_later",
(PyCFunction)faulthandler_dump_traceback_later, METH_VARARGS|METH_KEYWORDS, (PyCFunction)faulthandler_dump_tracebacks_later, METH_VARARGS|METH_KEYWORDS,
PyDoc_STR("dump_tracebacks_later(timeout, repeat=False, file=sys.stderr):\n" PyDoc_STR("dump_tracebacks_later(timeout, repeat=False, file=sys.stderrn, exit=False):\n"
"dump the traceback of all threads in timeout seconds,\n" "dump the traceback of all threads in timeout seconds,\n"
"or each timeout seconds if repeat is True.")}, "or each timeout seconds if repeat is True. If exit is True, "
"call _exit(1) which is not safe.")},
{"cancel_dump_tracebacks_later", {"cancel_dump_tracebacks_later",
(PyCFunction)faulthandler_cancel_dump_tracebacks_later_py, METH_NOARGS, (PyCFunction)faulthandler_cancel_dump_tracebacks_later_py, METH_NOARGS,
PyDoc_STR("cancel_dump_tracebacks_later():\ncancel the previous call " PyDoc_STR("cancel_dump_tracebacks_later():\ncancel the previous call "

View File

@ -373,6 +373,8 @@ class PyBuildExt(build_ext):
def add_multiarch_paths(self): def add_multiarch_paths(self):
# Debian/Ubuntu multiarch support. # Debian/Ubuntu multiarch support.
# https://wiki.ubuntu.com/MultiarchSpec # https://wiki.ubuntu.com/MultiarchSpec
if not find_executable('dpkg-architecture'):
return
tmpfile = os.path.join(self.build_temp, 'multiarch') tmpfile = os.path.join(self.build_temp, 'multiarch')
if not os.path.exists(self.build_temp): if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp) os.makedirs(self.build_temp)