Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete the iterator interface: error handling and STL algorithms #662

Merged
merged 4 commits into from
Feb 26, 2017

Conversation

dean0x7d
Copy link
Member

This PR fills in some of the missing bits in py::iterator:

  • PyObject_GetIter and PyIter_Next errors are now being handled properly.
  • Add the required type aliases to py::iterator so that it can use used with <algorithm>. It models an InputIterator (std::input_iterator_tag) which is perfectly in line with the restrictions of py::iterator: copying doesn't clone the internal state, i.e. no multipass guarantee.

py::iterator works for any py::object, but the sequence types can get specialized implementations which are simultaneously slimmer and more capable:

  • py::tuple, py::list get a PySequence_Fast iterator.
  • py::sequence gets a slower but more generic sequence iterator.
  • These model RandomAccessIterator and are STL-compatible.
  • The slimmer iterators reduce binary size of the test module by ~0.3% (measured without the new tests).

py::dict already had a specialized iterator. This PR just folds it in with the others. It models a ForwardIterator (input + multipass).

Before this, `py::iterator` didn't do any error handling, so code like:
```c++
for (auto item : py::int_(1)) {
    // ...
}
```
would just silently skip the loop. The above now throws `TypeError` as
expected. This is a breaking behavior change, but any code which relied
on the silent skip was probably broken anyway.

Also, errors returned by `PyIter_Next()` are now properly handled.
The added type aliases are required by `std::iterator_traits`.
Python iterators satisfy the `InputIterator` concept in C++.
Slightly reduces binary size (range for loops over tuple/list benefit
a lot). The iterators are compatible with std algorithms.
* The definition of `PySequence_Fast` is more restrictive on PyPy, so
  use the slow path instead.
* `PyDict_Next` has been fixed in PyPy -> remove workaround.
@wjakob
Copy link
Member

wjakob commented Feb 26, 2017

This looks good to me. @jagerman?

@jagerman
Copy link
Member

Looks good to me.

@wjakob wjakob merged commit 5fe9908 into pybind:master Feb 26, 2017
@wjakob
Copy link
Member

wjakob commented Feb 26, 2017

Merged! Thank you, @dean0x7d

@dean0x7d dean0x7d deleted the iter branch February 27, 2017 14:00
@jagerman jagerman modified the milestone: v2.1 Mar 19, 2017
@rwgk rwgk mentioned this pull request Feb 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants