Commit d2f33c5e authored by Kevin Modzelewski's avatar Kevin Modzelewski

More set stuff

symmetric_difference, in-place binops, etc
parent 9df41bb5
# expected: fail
doctests = """
########### Tests mostly copied from test_listcomps.py ############
......
......@@ -3463,9 +3463,13 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
BoxedDict* d_kwargs = static_cast<BoxedDict*>(kwargs);
BoxedDict* okwargs = NULL;
if (d_kwargs->d.size())
if (d_kwargs->d.size()) {
okwargs = get_okwargs();
if (!okwargs && (!param_names || !param_names->takes_param_names))
raiseExcHelper(TypeError, "%s() doesn't take keyword arguments", func_name);
}
for (const auto& p : *d_kwargs) {
auto k = coerceUnicodeToStr(p.first);
......
......@@ -198,66 +198,111 @@ static Box* setRepr(BoxedSet* self) {
return boxString(llvm::StringRef(&chars[0], chars.size()));
}
Box* setOrSet(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
RELEASE_ASSERT(PyAnySet_Check(rhs), "");
static void _setSymmetricDifferenceUpdate(BoxedSet* self, Box* other) {
if (!PyAnySet_Check(other))
other = makeNewSet(self->cls, other);
BoxedSet* other_set = static_cast<BoxedSet*>(other);
for (auto elt : other_set->s) {
bool found = self->s.erase(elt);
if (!found)
self->s.insert(elt);
}
}
BoxedSet* rtn = new (lhs->cls) BoxedSet();
static BoxedSet* setIntersection2(BoxedSet* self, Box* container) {
RELEASE_ASSERT(PyAnySet_Check(self), "");
for (auto&& elt : lhs->s) {
rtn->s.insert(elt);
}
for (auto&& elt : rhs->s) {
rtn->s.insert(elt);
BoxedSet* rtn = new BoxedSet();
for (auto elt : container->pyElements()) {
if (self->s.count(elt))
rtn->s.insert(elt);
}
return rtn;
}
Box* setAndSet(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
RELEASE_ASSERT(PyAnySet_Check(rhs), "");
static Box* setIntersectionUpdate2(BoxedSet* self, Box* other) {
Box* tmp = setIntersection2(self, other);
std::swap(self->s, ((BoxedSet*)tmp)->s);
return None;
}
BoxedSet* rtn = new (lhs->cls) BoxedSet();
Box* setIOr(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
for (auto&& elt : lhs->s) {
if (rhs->s.count(elt))
rtn->s.insert(elt);
// TODO just [write and] call setUnionUpdate2
for (auto&& elt : rhs->s) {
lhs->s.insert(elt);
}
return rtn;
return lhs;
}
Box* setSubSet(BoxedSet* lhs, BoxedSet* rhs) {
Box* setOr(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
RELEASE_ASSERT(PyAnySet_Check(rhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
BoxedSet* rtn = new (lhs->cls) BoxedSet();
BoxedSet* rtn = makeNewSet(lhs->cls, lhs);
return setIOr(rtn, rhs);
}
for (auto&& elt : lhs->s) {
// TODO if len(rhs) << len(lhs), it might be more efficient
// to delete the elements of rhs from lhs?
if (rhs->s.count(elt) == 0)
rtn->s.insert(elt);
}
return rtn;
Box* setIAnd(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
setIntersectionUpdate2(lhs, rhs);
return lhs;
}
Box* setXorSet(BoxedSet* lhs, BoxedSet* rhs) {
Box* setAnd(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
RELEASE_ASSERT(PyAnySet_Check(rhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
BoxedSet* rtn = new (lhs->cls) BoxedSet();
return setIntersection2(lhs, rhs);
}
for (auto&& elt : lhs->s) {
if (rhs->s.count(elt) == 0)
rtn->s.insert(elt);
}
Box* setISub(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
// TODO: write and call setDifferenceUpdate2
for (auto&& elt : rhs->s) {
if (lhs->s.count(elt) == 0)
rtn->s.insert(elt);
lhs->s.erase(elt);
}
return lhs;
}
return rtn;
Box* setSub(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
BoxedSet* rtn = makeNewSet(lhs->cls, lhs);
return setISub(rtn, rhs);
}
Box* setIXor(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
_setSymmetricDifferenceUpdate(lhs, rhs);
return lhs;
}
Box* setXor(BoxedSet* lhs, BoxedSet* rhs) {
RELEASE_ASSERT(PyAnySet_Check(lhs), "");
if (!PyAnySet_Check(rhs))
return NotImplemented;
BoxedSet* rtn = makeNewSet(lhs->cls, lhs);
return setIXor(rtn, rhs);
}
Box* setIter(BoxedSet* self) noexcept {
......@@ -368,36 +413,53 @@ Box* setUnion(BoxedSet* self, BoxedTuple* args) {
return rtn;
}
static void _setDifferenceUpdate(BoxedSet* self, BoxedTuple* args) {
for (auto container : *args) {
for (auto elt : container->pyElements()) {
self->s.erase(elt);
}
}
}
Box* setDifferenceUpdate(BoxedSet* self, BoxedTuple* args) {
if (!PySet_Check(self))
raiseExcHelper(TypeError, "descriptor 'difference_update' requires a 'set' object but received a '%s'",
getTypeName(self));
_setDifferenceUpdate(self, args);
return None;
}
Box* setDifference(BoxedSet* self, BoxedTuple* args) {
if (!PyAnySet_Check(self))
raiseExcHelper(TypeError, "descriptor 'difference' requires a 'set' object but received a '%s'",
getTypeName(self));
BoxedSet* rtn = makeNewSet(self->cls, self);
for (auto container : args->pyElements()) {
for (auto elt : container->pyElements()) {
rtn->s.erase(elt);
}
}
_setDifferenceUpdate(rtn, args);
return rtn;
}
Box* setDifferenceUpdate(BoxedSet* self, BoxedTuple* args) {
Box* setSymmetricDifferenceUpdate(BoxedSet* self, Box* other) {
if (!PySet_Check(self))
raiseExcHelper(TypeError, "descriptor 'difference' requires a 'set' object but received a '%s'",
raiseExcHelper(TypeError,
"descriptor 'symmetric_difference_update' requires a 'set' object but received a '%s'",
getTypeName(self));
for (auto container : args->pyElements()) {
for (auto elt : container->pyElements()) {
self->s.erase(elt);
}
}
_setSymmetricDifferenceUpdate(self, other);
return None;
}
Box* setSymmetricDifference(BoxedSet* self, Box* other) {
if (!PyAnySet_Check(self))
raiseExcHelper(TypeError, "descriptor 'symmetric_difference' requires a 'set' object but received a '%s'",
getTypeName(self));
BoxedSet* rtn = makeNewSet(self->cls, self);
_setSymmetricDifferenceUpdate(rtn, other);
return rtn;
}
static Box* setIssubset(BoxedSet* self, Box* container) {
RELEASE_ASSERT(PyAnySet_Check(self), "");
......@@ -437,24 +499,16 @@ static Box* setIsdisjoint(BoxedSet* self, Box* container) {
return True;
}
static BoxedSet* setIntersection2(BoxedSet* self, Box* container) {
RELEASE_ASSERT(PyAnySet_Check(self), "");
BoxedSet* rtn = new BoxedSet();
for (auto elt : container->pyElements()) {
if (self->s.count(elt))
rtn->s.insert(elt);
}
return rtn;
}
static Box* setIntersection(BoxedSet* self, BoxedTuple* args) {
if (!PyAnySet_Check(self))
raiseExcHelper(TypeError, "descriptor 'intersection' requires a 'set' object but received a '%s'",
getTypeName(self));
if (args->size() == 0)
return makeNewSet(self->cls, self);
BoxedSet* rtn = self;
for (auto container : args->pyElements()) {
for (auto container : *args) {
rtn = setIntersection2(rtn, container);
}
return rtn;
......@@ -633,19 +687,29 @@ void setupSet() {
v_fu.push_back(UNKNOWN);
auto add = [&](const char* name, void* func) {
CLFunction* func_obj = createRTFunction(2, false, false);
auto func_obj = new BoxedFunction(boxRTFunction((void*)func, UNKNOWN, 2, false, false));
set_cls->giveAttr(name, func_obj);
frozenset_cls->giveAttr(name, func_obj);
/*
CLFunction* func_obj = boxRTFunction(2, false, false);
addRTFunction(func_obj, (void*)func, SET, v_ss);
addRTFunction(func_obj, (void*)func, SET, v_sf);
addRTFunction(func_obj, (void*)func, FROZENSET, v_fs);
addRTFunction(func_obj, (void*)func, FROZENSET, v_ff);
set_cls->giveAttr(name, new BoxedFunction(func_obj));
frozenset_cls->giveAttr(name, set_cls->getattr(internStringMortal(name)));
*/
};
add("__or__", (void*)setOrSet);
add("__sub__", (void*)setSubSet);
add("__xor__", (void*)setXorSet);
add("__and__", (void*)setAndSet);
add("__or__", (void*)setOr);
add("__sub__", (void*)setSub);
add("__xor__", (void*)setXor);
add("__and__", (void*)setAnd);
add("__ior__", (void*)setIOr);
add("__isub__", (void*)setISub);
add("__ixor__", (void*)setIXor);
add("__iand__", (void*)setIAnd);
set_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)setIter, typeFromClass(set_iterator_cls), 1)));
frozenset_cls->giveAttr("__iter__", set_cls->getattr(internStringMortal("__iter__")));
......@@ -688,11 +752,15 @@ void setupSet() {
frozenset_cls->giveAttr("intersection", set_cls->getattr(internStringMortal("intersection")));
set_cls->giveAttr("intersection_update",
new BoxedFunction(boxRTFunction((void*)setIntersectionUpdate, UNKNOWN, 1, true, false)));
frozenset_cls->giveAttr("intersection_update", set_cls->getattr(internStringMortal("intersection_update")));
set_cls->giveAttr("difference", new BoxedFunction(boxRTFunction((void*)setDifference, UNKNOWN, 1, true, false)));
frozenset_cls->giveAttr("difference", set_cls->getattr(internStringMortal("difference")));
set_cls->giveAttr("difference_update",
new BoxedFunction(boxRTFunction((void*)setDifferenceUpdate, UNKNOWN, 1, true, false)));
set_cls->giveAttr("symmetric_difference",
new BoxedFunction(boxRTFunction((void*)setSymmetricDifference, UNKNOWN, 2, false, false)));
frozenset_cls->giveAttr("symmetric_difference", set_cls->getattr(internStringMortal("symmetric_difference")));
set_cls->giveAttr("symmetric_difference_update",
new BoxedFunction(boxRTFunction((void*)setSymmetricDifferenceUpdate, UNKNOWN, 2, false, false)));
set_cls->giveAttr("issubset", new BoxedFunction(boxRTFunction((void*)setIssubset, UNKNOWN, 2)));
frozenset_cls->giveAttr("issubset", set_cls->getattr(internStringMortal("issubset")));
set_cls->giveAttr("issuperset", new BoxedFunction(boxRTFunction((void*)setIssuperset, UNKNOWN, 2)));
......
......@@ -62,8 +62,7 @@ test_random long("invalid number")
test_repr complex.__hash__; some unknown issues
test_richcmp PyObject_Not
test_scope eval of code object from existing function (not currently supported)
test_set weird function-picking issue
test_setcomps parser not raising a SyntaxError when assigning to a setcomp
test_set lots of set issues
test_sort argument specification issue in listSort?
test_str memory leak?
test_string infinite loops in test_replace
......
......@@ -12,7 +12,6 @@ def relpath(fn):
r = os.path.join(os.path.dirname(__file__), fn)
return r
print glob.glob("../from_cpython/Include/*.h")
builtin_headers = map(relpath, glob.glob("../../from_cpython/Include/*.h"))
for m in extensions:
......
......@@ -117,6 +117,22 @@ class MySet(set):
class MyFrozenset(frozenset):
pass
s = s1 = set()
s |= MySet(range(2))
print sorted(s), sorted(s1)
s &= MySet(range(1))
print sorted(s), sorted(s1)
s ^= MySet(range(4))
print sorted(s), sorted(s1)
s -= MySet(range(3))
print sorted(s), sorted(s1)
try:
set() | range(5)
assert 0
except TypeError as e:
print e
compare_to = []
for i in xrange(10):
compare_to.append(set(range(i)))
......@@ -125,10 +141,11 @@ for i in xrange(10):
compare_to.append(MyFrozenset(range(i)))
compare_to.append(range(i))
compare_to.append(range(i, 10))
compare_to.append([0, 0, 1, 1])
for s1 in set(range(5)), frozenset(range(5)):
for s2 in compare_to:
print type(s2), sorted(s2), s1.issubset(s2), s1.issuperset(s2), sorted(s1.difference(s2)), s1.isdisjoint(s2), sorted(s1.union(s2)), sorted(s1.intersection(s2))
print type(s2), sorted(s2), s1.issubset(s2), s1.issuperset(s2), sorted(s1.difference(s2)), s1.isdisjoint(s2), sorted(s1.union(s2)), sorted(s1.intersection(s2)), sorted(s1.symmetric_difference(s2))
print s1 == s2, s1 != s2
try:
print s1 < s2, s1 <= s2, s1 > s2, s1 >= s2
......@@ -138,11 +155,14 @@ f = float('nan')
s = set([f])
print f in s, f == list(s)[0]
s1 = set([3, 5])
s2 = set([1, 5])
s1.intersection_update(s2)
print sorted(s1)
for fn in (set.intersection_update, set.difference_update, set.symmetric_difference_update, set.__sub__,
set.__or__, set.__xor__, set.__and__):
s1 = set([3, 5])
s2 = set([1, 5])
r = fn(s1, s2)
if r:
print r,
print sorted(s1), sorted(s2)
def test_set_creation(base):
print "Testing with base =", base
......@@ -173,3 +193,9 @@ def test_set_creation(base):
print MySet(g())
test_set_creation(set)
test_set_creation(frozenset)
set(**{})
try:
set(**dict(a=1))
except TypeError:
print "TypeError"
# expected: fail
print hasattr(set, "__ior__")
print hasattr(set, "__isub__")
print hasattr(set, "__iand__")
print hasattr(set, "__ixor__")
s1 = set() | set(range(3))
s2 = set(range(1, 5))
s3 = s1
s1 -= s2
print s1, s2, s3
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