convenience wrapper for constructing iterators (fixes #142)

This commit is contained in:
Wenzel Jakob
2016-04-13 23:33:00 +02:00
parent 5a6aa49105
commit b282595bba
7 changed files with 100 additions and 49 deletions

View File

@@ -546,9 +546,12 @@ protected:
internals.registered_types_cpp[std::type_index(*(rec->type))] = tinfo;
internals.registered_types_py[type] = tinfo;
auto scope_module = (object) rec->scope.attr("__module__");
if (!scope_module)
scope_module = (object) rec->scope.attr("__name__");
object scope_module;
if (rec->scope) {
scope_module = (object) rec->scope.attr("__module__");
if (!scope_module)
scope_module = (object) rec->scope.attr("__name__");
}
std::string full_name = (scope_module ? ((std::string) scope_module.str() + "." + rec->name)
: std::string(rec->name));
@@ -560,7 +563,9 @@ protected:
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
/* Qualified names for Python >= 3.3 */
auto scope_qualname = (object) rec->scope.attr("__qualname__");
object scope_qualname;
if (rec->scope)
scope_qualname = (object) rec->scope.attr("__qualname__");
if (scope_qualname) {
type->ht_qualname = PyUnicode_FromFormat(
"%U.%U", scope_qualname.ptr(), name.ptr());
@@ -608,7 +613,8 @@ protected:
attr("__module__") = scope_module;
/* Register type with the parent scope */
rec->scope.attr(handle(type->ht_name)) = *this;
if (rec->scope)
rec->scope.attr(handle(type->ht_name)) = *this;
type_holder.release();
}
@@ -985,10 +991,28 @@ PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, handle arg
(void) wr.release();
}
template <typename Iterator> struct iterator_state { Iterator it, end; };
NAMESPACE_END(detail)
template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); }
template <typename Iterator, typename... Extra> iterator make_iterator(Iterator first, Iterator last, Extra&&... extra) {
typedef detail::iterator_state<Iterator> state;
if (!detail::get_type_info(typeid(state))) {
class_<state>(handle(), "")
.def("__iter__", [](state &s) -> state& { return s; })
.def("__next__", [](state &s) -> decltype(*std::declval<Iterator>()) & {
if (s.it == s.end)
throw stop_iteration();
return *s.it++;
}, return_value_policy::reference_internal, std::forward<Extra>(extra)...);
}
return (iterator) cast(state { first, last });
}
template <typename InputType, typename OutputType> void implicitly_convertible() {
auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * {
if (!detail::type_caster<InputType>().load(obj, false))

View File

@@ -86,22 +86,6 @@ public:
}
};
class iterator : public object {
public:
iterator(handle obj, bool borrowed = false) : object(obj, borrowed) { ++*this; }
iterator& operator++() {
if (ptr())
value = object(PyIter_Next(m_ptr), false);
return *this;
}
bool operator==(const iterator &it) const { return *it == **this; }
bool operator!=(const iterator &it) const { return *it != **this; }
const handle &operator*() const { return value; }
bool check() const { return PyIter_Check(ptr()); }
private:
object value;
};
NAMESPACE_BEGIN(detail)
inline handle get_function(handle value) {
if (value) {
@@ -230,12 +214,6 @@ private:
NAMESPACE_END(detail)
inline detail::accessor handle::operator[](handle key) const { return detail::accessor(ptr(), key.ptr(), false); }
inline detail::accessor handle::operator[](const char *key) const { return detail::accessor(ptr(), key, false); }
inline detail::accessor handle::attr(handle key) const { return detail::accessor(ptr(), key.ptr(), true); }
inline detail::accessor handle::attr(const char *key) const { return detail::accessor(ptr(), key, true); }
inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr())); }
inline iterator handle::end() const { return iterator(nullptr); }
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, CvtStmt) \
Name(const handle &h, bool borrowed) : Parent(h, borrowed) { CvtStmt; } \
@@ -252,6 +230,33 @@ inline iterator handle::end() const { return iterator(nullptr); }
PYBIND11_OBJECT(Name, Parent, CheckFun) \
Name() : Parent() { }
class iterator : public object {
public:
PYBIND11_OBJECT_DEFAULT(iterator, object, PyIter_Check)
iterator(handle obj, bool borrowed = false) : object(obj, borrowed) { }
iterator& operator++() {
if (ptr())
value = object(PyIter_Next(m_ptr), false);
return *this;
}
bool operator==(const iterator &it) const { return *it == **this; }
bool operator!=(const iterator &it) const { return *it != **this; }
const handle &operator*() const {
if (m_ptr && !value)
value = object(PyIter_Next(m_ptr), false);
return value;
}
private:
mutable object value;
};
inline detail::accessor handle::operator[](handle key) const { return detail::accessor(ptr(), key.ptr(), false); }
inline detail::accessor handle::operator[](const char *key) const { return detail::accessor(ptr(), key, false); }
inline detail::accessor handle::attr(handle key) const { return detail::accessor(ptr(), key.ptr(), true); }
inline detail::accessor handle::attr(const char *key) const { return detail::accessor(ptr(), key, true); }
inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr())); }
inline iterator handle::end() const { return iterator(nullptr); }
class str : public object {
public:
PYBIND11_OBJECT_DEFAULT(str, object, PyUnicode_Check)