Commit 2c71d548 authored by scoder's avatar scoder

Merge pull request #106 from vitek/master

Regression fixes
parents 7ef9c72f d099cfe2
...@@ -1789,10 +1789,8 @@ class AnalyseExpressionsTransform(CythonTransform): ...@@ -1789,10 +1789,8 @@ class AnalyseExpressionsTransform(CythonTransform):
return node return node
def visit_AttributeNode(self, node): def visit_AttributeNode(self, node):
# Note: Expression analysis for attributes has already happened self.visitchildren(node)
# at this point (by recursive calls starting from FuncDefNode)
#print node.dump()
#return node
type = node.obj.type type = node.obj.type
if type.is_extension_type and type.objstruct_cname == 'PyArrayObject': if type.is_extension_type and type.objstruct_cname == 'PyArrayObject':
from NumpySupport import numpy_transform_attribute_node from NumpySupport import numpy_transform_attribute_node
......
...@@ -23,6 +23,7 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_GeneratorObject ...@@ -23,6 +23,7 @@ static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_GeneratorObject
//////////////////// Generator.proto //////////////////// //////////////////// Generator.proto ////////////////////
#define __Pyx_Generator_USED #define __Pyx_Generator_USED
#include <structmember.h> #include <structmember.h>
#include <frameobject.h>
typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *); typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *);
...@@ -186,19 +187,43 @@ PyObject *__Pyx_Generator_SendEx(__pyx_GeneratorObject *self, PyObject *value) { ...@@ -186,19 +187,43 @@ PyObject *__Pyx_Generator_SendEx(__pyx_GeneratorObject *self, PyObject *value) {
} }
if (value) if (value) {
__Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback); /* Generators always return to their most recent caller, not
else * necessarily their creator. */
if (self->exc_traceback) {
PyThreadState *tstate = PyThreadState_GET();
PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
PyFrameObject *f = tb->tb_frame;
Py_XINCREF(tstate->frame);
assert(f->f_back == NULL);
f->f_back = tstate->frame;
}
__Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
&self->exc_traceback);
} else {
__Pyx_Generator_ExceptionClear(self); __Pyx_Generator_ExceptionClear(self);
}
self->is_running = 1; self->is_running = 1;
retval = self->body((PyObject *) self, value); retval = self->body((PyObject *) self, value);
self->is_running = 0; self->is_running = 0;
if (retval) if (retval) {
__Pyx_ExceptionSwap(&self->exc_type, &self->exc_value, &self->exc_traceback); __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
else &self->exc_traceback);
/* Don't keep the reference to f_back any longer than necessary. It
* may keep a chain of frames alive or it could create a reference
* cycle. */
if (self->exc_traceback) {
PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
PyFrameObject *f = tb->tb_frame;
Py_CLEAR(f->f_back);
}
} else {
__Pyx_Generator_ExceptionClear(self); __Pyx_Generator_ExceptionClear(self);
}
return retval; return retval;
} }
...@@ -546,7 +571,7 @@ static PyTypeObject __pyx_GeneratorType_type = { ...@@ -546,7 +571,7 @@ static PyTypeObject __pyx_GeneratorType_type = {
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags*/
0, /*tp_doc*/ 0, /*tp_doc*/
(traverseproc) __Pyx_Generator_traverse, /*tp_traverse*/ (traverseproc) __Pyx_Generator_traverse, /*tp_traverse*/
(inquiry) __Pyx_Generator_clear, /*tp_clear*/ 0, /*tp_clear*/
0, /*tp_richcompare*/ 0, /*tp_richcompare*/
offsetof(__pyx_GeneratorObject, gi_weakreflist), /* tp_weaklistoffse */ offsetof(__pyx_GeneratorObject, gi_weakreflist), /* tp_weaklistoffse */
PyObject_SelfIter, /*tp_iter*/ PyObject_SelfIter, /*tp_iter*/
......
# mode: run
# tags: lambda, attribute, regression
class TestClass(object):
bar = 123
def test_attribute_and_lambda(f):
"""
>>> test_attribute_and_lambda(lambda _: TestClass())
123
"""
return f(lambda x: x).bar
# mode: run
# tags: generator
import sys
def _next(it):
if sys.version_info[0] >= 3:
return next(it)
else:
return it.next()
def test_generator_frame_cycle():
"""
>>> test_generator_frame_cycle()
("I'm done",)
"""
testit = []
def whoo():
try:
yield
except:
yield
finally:
testit.append("I'm done")
g = whoo()
_next(g)
# Frame object cycle
eval('g.throw(ValueError)', {'g': g})
del g
return tuple(testit)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment