// Copyright David Abrahams 2004. Distributed under the Boost // Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include namespace boost { namespace python { namespace detail { namespace { // When returning list objects from methods, it may turn out that the // derived class is returning something else, perhaps something not // even derived from list. Since it is generally harmless for a // Boost.Python wrapper object to hold an object of a different // type, and because calling list() with an object may in fact // perform a conversion, the least-bad alternative is to assume that // we have a Python list object and stuff it into the list result. list assume_list(object const& o) { return list(detail::borrowed_reference(o.ptr())); } // No PyDict_CheckExact; roll our own. inline bool check_exact(dict_base const* p) { return p->ptr()->ob_type == &PyDict_Type; } } detail::new_reference dict_base::call(object const& arg_) { union { PyTypeObject *ptop; PyObject *pop; }pun = { &PyDict_Type }; return (detail::new_reference)PyObject_CallFunction( pun.pop, const_cast("(O)"), arg_.ptr()); } dict_base::dict_base() : object(detail::new_reference(PyDict_New())) {} dict_base::dict_base(object_cref data) : object(call(data)) {} void dict_base::clear() { if (check_exact(this)) PyDict_Clear(this->ptr()); else this->attr("clear")(); } dict dict_base::copy() { if (check_exact(this)) { return dict(detail::new_reference( PyDict_Copy(this->ptr()))); } else { return dict(detail::borrowed_reference( this->attr("copy")().ptr() )); } } object dict_base::get(object_cref k) const { if (check_exact(this)) { PyObject* result = PyDict_GetItem(this->ptr(),k.ptr()); return object(detail::borrowed_reference(result ? result : Py_None)); } else { return this->attr("get")(k); } } object dict_base::get(object_cref k, object_cref d) const { return this->attr("get")(k,d); } bool dict_base::has_key(object_cref k) const { return extract(this->contains(k)); } list dict_base::items() const { if (check_exact(this)) { return list(detail::new_reference( PyDict_Items(this->ptr()))); } else { return assume_list(this->attr("items")()); } } object dict_base::iteritems() const { return this->attr("iteritems")(); } object dict_base::iterkeys() const { return this->attr("iterkeys")(); } object dict_base::itervalues() const { return this->attr("itervalues")(); } list dict_base::keys() const { if (check_exact(this)) { return list(detail::new_reference( PyDict_Keys(this->ptr()))); } else { return assume_list(this->attr("keys")()); } } tuple dict_base::popitem() { return tuple(detail::borrowed_reference( this->attr("popitem")().ptr() )); } object dict_base::setdefault(object_cref k) { return this->attr("setdefault")(k); } object dict_base::setdefault(object_cref k, object_cref d) { return this->attr("setdefault")(k,d); } void dict_base::update(object_cref other) { if (check_exact(this)) { if (PyDict_Update(this->ptr(),other.ptr()) == -1) throw_error_already_set(); } else { this->attr("update")(other); } } list dict_base::values() const { if (check_exact(this)) { return list(detail::new_reference( PyDict_Values(this->ptr()))); } else { return assume_list(this->attr("values")()); } } static struct register_dict_pytype_ptr { register_dict_pytype_ptr() { const_cast( converter::registry::lookup(boost::python::type_id()) ).m_class_object = &PyDict_Type; } }register_dict_pytype_ptr_; }}} // namespace boost::python