1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
import pytest
pytest.skip("This cannot possibly work on pypy3")
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)
|