Commit fa5ce439 authored by Kevin Modzelewski's avatar Kevin Modzelewski

more tests

parent c16acd39
......@@ -6155,8 +6155,9 @@ extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs*
extern "C" void delattrInternal(Box* obj, BoxedString* attr, DelattrRewriteArgs* rewrite_args) {
static BoxedString* delattr_str = getStaticString("__delattr__");
Box* delAttr = typeLookup(obj->cls, delattr_str);
assert(0 && "how to keep delAttr alive (esp in rewrite)");
if (delAttr != NULL) {
KEEP_ALIVE(delAttr);
Box* rtn = runtimeCallInternal<CXX, NOT_REWRITABLE>(delAttr, NULL, ArgPassSpec(2), obj, attr, NULL, NULL, NULL);
Py_DECREF(rtn);
return;
......
......@@ -1647,7 +1647,7 @@ static void functionSetDefaults(Box* b, Box* v, void*) {
auto old_defaults = func->defaults;
func->defaults = incref(t);
Py_DECREF(old_defaults);
Py_XDECREF(old_defaults);
func->dependent_ics.invalidateAll();
}
......
......@@ -379,6 +379,8 @@ template <typename B> DecrefHandle<B, true> autoXDecref(B* b) {
#define AUTO_DECREF(x) DecrefHandle<Box, false> CAT(_autodecref_, __LINE__)((x))
#define AUTO_XDECREF(x) DecrefHandle<Box, true> CAT(_autodecref_, __LINE__)((x))
#define KEEP_ALIVE(x) AUTO_DECREF(incref(x))
template <bool Nullable = false> class AutoDecrefArray {
private:
Box** array;
......
......@@ -9,10 +9,24 @@
# since most of the metadata is stored on another structure that has a longer lifetime.
# So to try to get around that, this test adds some "other_arg" default arguments, since those
# will get collected when the function gets destroyed.
# Actually, I guess it can run ok since the defaults will get incref'd before the function gets called.
# So also test it by creating a closure and make sure that that stays alive.
# - This file wraps each individual test in a function and then calls it twice -- this is to try to test
# any rewritten (traced) variants as well.
import sys
def make_closure(f):
def inner(*args, **kw):
print f.__name__
r = f(*args, **kw)
print f.__name__
return r
return inner
# The standard case, when the function is obtained via standard evaluation rules:
class C(object):
@make_closure
def f(self, other_arg=2.5**10):
print "f"
print other_arg
......@@ -21,78 +35,104 @@ class C(object):
c = C()
c.f()
class C(object):
def __delattr__(self, attr, other_arg=2.3**10):
print "__delattr__"
print other_arg
del C.__delattr__
print other_arg
sys._clear_type_cache()
print other_arg
c = C()
del c.a
try:
def f():
class C(object):
@make_closure
def __delattr__(self, attr, other_arg=2.3**10):
print "__delattr__"
print other_arg
del C.__delattr__
print other_arg
sys._clear_type_cache()
print other_arg
c = C()
del c.a
except Exception as e:
print e
try:
del c.a
except Exception as e:
print e
f()
f()
class C(object):
def __getattr__(self, attr, other_arg=2.2**10):
print "__getattr__"
print other_arg
del C.__getattr__
print other_arg
sys._clear_type_cache()
print other_arg
return attr
c = C()
print c.a
try:
def f():
class C(object):
@make_closure
def __getattr__(self, attr, other_arg=2.2**10):
print "__getattr__"
print other_arg
del C.__getattr__
print other_arg
sys._clear_type_cache()
print other_arg
return attr
c = C()
print c.a
except Exception as e:
print e
try:
print c.a
except Exception as e:
print e
f()
f()
class C(object):
def __setattr__(self, attr, val, other_arg=2.1**10):
print "__setattr__", attr, val
print other_arg
del C.__setattr__
print other_arg
sys._clear_type_cache()
print other_arg
c = C()
c.a = 1
try:
c.a = 2
except Exception as e:
print e
def f():
class C(object):
@make_closure
def __setattr__(self, attr, val, other_arg=2.1**10):
print "__setattr__", attr, val
print other_arg
del C.__setattr__
print other_arg
sys._clear_type_cache()
print other_arg
c = C()
c.a = 1
try:
c.a = 2
except Exception as e:
print e
f()
f()
class D(object):
def __get__(self, obj, type, other_arg=2.4**10):
print "D.__get__"
print other_arg
del D.__get__
print other_arg
sys._clear_type_cache()
print other_arg
return 1
def f():
class D(object):
@make_closure
def __get__(self, obj, type, other_arg=2.4**10):
print "D.__get__"
print other_arg
del D.__get__
print other_arg
sys._clear_type_cache()
print other_arg
return 1
def __set__(self, obj, value, other_arg=2.0**10):
print "D.__set__", obj, value
print other_arg
del D.__set__
print other_arg
sys._clear_type_cache()
print other_arg
return 1
@make_closure
def __set__(self, obj, value, other_arg=2.0**10):
print "D.__set__", obj, value
print other_arg
del D.__set__
print other_arg
sys._clear_type_cache()
print other_arg
return 1
C.x = D()
c = C()
c.x = 0
print c.x
c.x = 0
print c.x
C.x = D()
c = C()
c.x = 0
print c.x
c.x = 0
print c.x
f()
f()
# TODO: lots of other cases that could/should get tested.
# Related:
@make_closure
def f(a1=2.0**10, a2=2.1**10):
f.func_defaults = ()
print a1, a2
del globals()['f']
f()
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