import pytest import sys try: import __pypy__ except ImportError: pass else: pytest.skip("makes no sense under pypy!") try: from hypothesis import given, strategies, settings except ImportError: pytest.skip("requires hypothesis") base_initargs = strategies.sampled_from([ ("object", (), False), ("type(sys)", ("fake", ), True), ("NewBase", (), True), ("OldBase", (), False), ("object, OldBase", (), False), ("type(sys), OldBase", ("fake", ), True), ]) attrnames = strategies.sampled_from(["a", "b", "c"]) def make_value_attr(val): return val, str(val) def make_method(val): return (lambda self, val=val: val, "lambda self: %d" % val) def make_property(val): return ( property(lambda self: val, lambda self, val: None, lambda self: None), "property(lambda self: %d, lambda self, val: None, lambda self: None)" % val) value_attrs = strategies.builds(make_value_attr, strategies.integers()) methods = strategies.builds(make_method, strategies.integers()) properties = strategies.builds(make_property, strategies.integers()) class_attrs = strategies.one_of(value_attrs, methods, properties) @strategies.composite def make_code(draw): baseclass, initargs, hasdict = draw(base_initargs) code = ["import sys", "class OldBase:pass", "class NewBase(object):pass", "class A(%s):" % baseclass] dct = {} if draw(strategies.booleans()): slots = draw(strategies.lists(attrnames)) if not hasdict and draw(strategies.booleans()): slots.append("__dict__") dct["__slots__"] = slots code.append(" __slots__ = %s" % (slots, )) for name in ["a", "b", "c"]: if not draw(strategies.booleans()): continue dct[name], codeval = draw(class_attrs) code.append(" %s = %s" % (name, codeval)) class OldBase: pass class NewBase(object): pass evaldct = {'OldBase': OldBase, 'NewBase': NewBase} if baseclass == 'OldBase': metaclass = type(OldBase) else: metaclass = type cls = metaclass("A", eval(baseclass+',', globals(), evaldct), dct) inst = cls(*initargs) code.append(" pass") code.append("a = A(*%s)" % (initargs, )) for attr in draw(strategies.lists(attrnames, min_size=1)): op = draw(strategies.sampled_from(["read", "read", "read", "write", "writemeth", "writeclass", "writebase", "del", "delclass"])) if op == "read": try: res = getattr(inst, attr) except AttributeError: code.append("raises(AttributeError, 'a.%s')" % (attr, )) else: if callable(res): code.append("assert a.%s() == %s" % (attr, res())) else: code.append("assert a.%s == %s" % (attr, res)) elif op == "write": val = draw(strategies.integers()) try: setattr(inst, attr, val) except AttributeError: code.append("raises(AttributeError, 'a.%s=%s')" % (attr, val)) else: code.append("a.%s = %s" % (attr, val)) elif op == "writemeth": val = draw(strategies.integers()) try: setattr(inst, attr, lambda val=val: val) except AttributeError: code.append("raises(AttributeError, 'a.%s=0')" % (attr, )) else: code.append("a.%s = lambda : %s" % (attr, val)) elif op == "writeclass": val, codeval = draw(class_attrs) setattr(cls, attr, val) code.append("A.%s = %s" % (attr, codeval)) elif op == "writebase": val, codeval = draw(class_attrs) setattr(OldBase, attr, val) setattr(NewBase, attr, val) code.append("OldBase.%s = NewBase.%s = %s" % (attr, attr , codeval)) elif op == "del": try: delattr(inst, attr) except AttributeError: code.append("raises(AttributeError, 'del a.%s')" % (attr, )) else: code.append("del a.%s" % (attr, )) elif op == "delclass": try: delattr(cls, attr) except AttributeError: code.append("raises(AttributeError, 'del A.%s')" % (attr, )) else: code.append("del A.%s" % (attr, )) return "\n ".join(code) @given(code=make_code()) #@settings(max_examples=5000) def test_random_attrs(code, space): print code exec "if 1:\n " + code space.appexec([], "():\n " + code)