Add and remove some PyPy iterator workarounds

* 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.
This commit is contained in:
Dean Moldovan 2017-02-10 12:20:24 +01:00 committed by Wenzel Jakob
parent 5637af7b67
commit 5fe9908b7a
2 changed files with 9 additions and 22 deletions

View File

@ -1177,29 +1177,10 @@ public:
/// Export enumeration entries into the parent scope
enum_ &export_values() {
#if !defined(PYPY_VERSION)
PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict;
PyObject *key, *value;
ssize_t pos = 0;
while (PyDict_Next(dict, &pos, &key, &value)) {
if (PyObject_IsInstance(value, this->m_ptr))
m_parent.attr(key) = value;
for (auto item : reinterpret_borrow<dict>(((PyTypeObject *) this->m_ptr)->tp_dict)) {
if (isinstance(item.second, this->m_ptr))
m_parent.attr(item.first) = item.second;
}
#else
/* PyPy's cpyext still has difficulties with the above
CPython API calls; emulate using Python code. */
dict d; d["t"] = *this; d["p"] = m_parent;
PyObject *result = PyRun_String(
"for k, v in t.__dict__.items():\n"
" if isinstance(v, t):\n"
" setattr(p, k, v)\n",
Py_file_input, d.ptr(), d.ptr());
if (result == nullptr)
throw error_already_set();
Py_DECREF(result);
#endif
return *this;
}

View File

@ -613,8 +613,14 @@ private:
};
NAMESPACE_END(iterator_policies)
#if !defined(PYPY_VERSION)
using tuple_iterator = generic_iterator<iterator_policies::sequence_fast_readonly>;
using list_iterator = generic_iterator<iterator_policies::sequence_fast_readonly>;
#else
using tuple_iterator = generic_iterator<iterator_policies::sequence_slow_readwrite>;
using list_iterator = generic_iterator<iterator_policies::sequence_slow_readwrite>;
#endif
using sequence_iterator = generic_iterator<iterator_policies::sequence_slow_readwrite>;
using dict_iterator = generic_iterator<iterator_policies::dict_readonly>;