def fn(): a = Foo() b = Foo() def break_if_a(obj, value): return obj is a pdb.break_on_setattr('bar', condition=break_if_a, set_trace=set_trace)(Foo) b.bar = 10 a.bar = 42
def test_break_on_setattr(): # we don't use a class decorator to keep 2.5 compatibility class Foo(object): pass Foo = pdb.break_on_setattr('x', set_trace=set_trace)(Foo) def fn(): obj = Foo() obj.x = 0 return obj.x check( fn, """ [NUM] > .*fn() -> obj.x = 0 1 frame hidden .* # hasattr(obj, 'x') False # n [NUM] > .*fn() -> return obj.x # p obj.x 0 # c """)
def test_break_on_setattr_overridden(): # we don't use a class decorator to keep 2.5 compatibility class Foo(object): def __setattr__(self, attr, value): object.__setattr__(self, attr, value+1) Foo = pdb.break_on_setattr('x', set_trace=set_trace)(Foo) def fn(): obj = Foo() obj.y = 41 obj.x = 0 return obj.x check(fn, """ [NUM] > .*fn() -> obj.x = 0 1 frame hidden .* # obj.y 42 # hasattr(obj, 'x') False # n [NUM] > .*fn() -> return obj.x # print obj.x 1 # c """)
def test_break_on_setattr_condition(): def mycond(obj, value): return value == 42 # we don't use a class decorator to keep 2.5 compatibility class Foo(object): pass Foo = pdb.break_on_setattr('x', condition=mycond, set_trace=set_trace)(Foo) def fn(): obj = Foo() obj.x = 0 obj.x = 42 return obj.x check(fn, """ [NUM] > .*fn() -> obj.x = 42 1 frame hidden .* # obj.x 0 # n [NUM] > .*fn() -> return obj.x # obj.x 42 # c """)
def test_break_on_setattr(): # we don't use a class decorator to keep 2.5 compatibility class Foo(object): pass Foo = pdb.break_on_setattr('x', set_trace=set_trace)(Foo) def fn(): obj = Foo() obj.x = 0 return obj.x check(fn, """ [NUM] > .*fn() -> obj.x = 0 1 frame hidden .* # hasattr(obj, 'x') False # n [NUM] > .*fn() -> return obj.x # print obj.x 0 # c """)