pydag: fix lazy set iteration

Summary:
The previous code was wrong - it converts the PyObject to iterator every time
(ex. if the PyObject is a set, then it calls `set.__iter__` every time, and
will only get the first element of the set).

For example, it will enter an infinite loop for evaluating this:

  bindings.dag.nameset({'1', '2'})

Fix it by calling `__iter__`, to get the iterator object and use that instead
of the original PyObject.

Reviewed By: markbt

Differential Revision: D21554676

fbshipit-source-id: 0f2adae8f123530cee2d473da37ca1a93a941fde
This commit is contained in:
Jun Wu 2020-05-14 12:01:01 -07:00 committed by Facebook GitHub Bot
parent aeac1551d2
commit 96ac755c06

View File

@ -129,7 +129,7 @@ impl<'a> FromPyObject<'a> for Names {
// Others - convert to LazySet.
let obj = obj.clone_ref(py);
let iter = PyNameIter::new(py, obj)?;
let iter = PyNameIter::new(py, obj.iter(py)?.into_object())?;
let set = NameSet::from_iter(iter);
Ok(Names(set))
}
@ -169,7 +169,10 @@ impl Iterator for PyNameIter {
let value = value.extract::<PyBytes>(py)?;
Ok(Some(VertexName::copy_from(value.data(py))))
}
Some(Err(err)) => Err(err),
Some(Err(err)) => {
self.errored = true;
Err(err)
}
}
})()
.into_anyhow_result()