#include "python.h" #include namespace python { // void Object::set(PyObject *pyobj, bool owned = false) {{{ void Object::set(PyObject *pyobj, bool owned) { DEBUG("void Object::set(PyObject " << pyobj << ", bool "<< owned<< ")"); release(); object = pyobj; if ( not owned ) { incref(); } validate(); DEBUG("Object set to " << *this); m_owned = owned; } // }}} // void Object::release() {{{ void Object::release() { DEBUG("void Object::release()"); decref(); object = NULL; } // }}} // void Object::validate() {{{ void Object::validate() { if ( not accepts( object ) ) { // We have the wrong type DEBUG(*this); release(); check_errors(); // Use RTTI to get the type std::string s("Error creating object of type "); s += (typeid (*this)).name(); throw TypeError(s); } } // }}} // Object::Object(const Object & obj) {{{ Object::Object(const Object & obj) { set(obj.object); } // }}} // Object::Object(PyObject * obj) {{{ Object::Object(PyObject * obj, bool owned) : object (obj) { set(obj, owned); } // }}} // Object & Object::operator=(const Object & obj) {{{ Object & Object::operator=(const Object & obj) { DEBUG("Object & Object::operator=(const Object & "<< obj << ")"); if (&obj != this) { set(obj.object); } return *this; } // }}} // Object & Object::operator=(PyObject * obj) {{{ Object & Object::operator=(PyObject * obj) { set(obj); return *this; } // }}} // Object::~Object() {{{ Object::~Object() { release(); } // }}} // void Object::incref() {{{ void Object::incref() { Py_XINCREF(object); } // }}} // void Object::decref() {{{ void Object::decref() { if (not m_owned) { // only dec it if we inced it //if ( reference_count() == 1 ) { // throw RuntimeError("Object::decref() decreasing count too much on "+ this->as_string()); //} else { // Py_XDECREF(object); //} } } // }}} // PyObject * Object::ptr() const {{{ PyObject * Object::ptr() const { return object; } // }}} // PyObject * Object::operator*() const {{{ PyObject * Object::operator*() const { return object; } // }}} // bool Object::accepts(PyObject * pyobj) const {{{ bool Object::accepts(PyObject * pyobj) const { return not (pyobj == NULL); } // }}} // std::string Object::as_string() const{{{ std::string Object::as_string() const { // build a std::string without building and python objects so we // can call this in emergencies PyObject * string_rep = PyObject_Str(object); return std::string( PyString_AsString( string_rep ), PyString_Size( string_rep ) ); // + " type " + (typeid (*this)).name(); } // }}} // int Object::reference_count() const{{{ int Object::reference_count() const{ // \warning This could break very hard if PyObject changes if ( object ) { return object->ob_refcnt; } else { return 0; } } // }}} // Type Object::type() const{{{ Type Object::type() const{ return Type( PyObject_Type(object) ); } // }}} // String Object::str () const{{{ String Object::str () const { return String( PyObject_Str(object) ); } // }}} // String Object::repr () const{{{ String Object::repr () const{ return String ( PyObject_Repr(object) ); } // }}} // bool Object::has_attr (const std::string& s) const {{{ bool Object::has_attr (const std::string& s) const { return PyObject_HasAttrString( object, const_cast( s.c_str() ) ); } // }}} // Object Object::get_attr (const std::string& s) const{{{ Object Object::get_attr (const std::string& s) const{ PyObject *tmp = PyObject_GetAttrString( object, const_cast( s.c_str() ) ); if ( tmp == NULL ) { throw NameError(s + " does not exist in " + this->as_string()); } return Object( tmp, true ); } // }}} // Object Object::get_item (const Object& key) const {{{ Object Object::get_item (const Object& key) const { return Object ( PyObject_GetAttr( object, *key ), true); } // }}} // long Object::hash_value () const{{{ long Object::hash_value () const{ return PyObject_Hash(object); } // }}} // void Object::set_attr (const std::string& s, const Object& value) {{{ void Object::set_attr (const std::string& s, const Object& value) { if ( PyObject_SetAttrString( object, const_cast( s.c_str() ), *value) == -1) { throw AttributeError("Object::set_attr(" + s + ", " + value.as_string() + ") failed"); } } // }}} // void Object::del_attr (const std::string& s){{{ void Object::del_attr (const std::string& s){ if ( PyObject_DelAttrString(object, const_cast( s.c_str() ) ) == -1 ) { throw AttributeError("Object::del_attr(" + s + ") failed"); } } // }}} // void Object::del_item (const Object& key){{{ void Object::del_item (const Object& key){ if ( PyObject_DelAttr(object, *key ) == -1 ) { throw KeyError("Object::del_item(" + key.as_string() + ") failed"); ; } } // }}} // bool Object::is_callable () const{{{ bool Object::is_callable () const{ return PyCallable_Check(object); } // }}} // bool Object::is_list () const{{{ bool Object::is_list () const{ return PyList_Check(object); } // }}} // bool Object::is_mapping () const{{{ bool Object::is_mapping () const{ return PyMapping_Check(object); } // }}} // bool Object::is_numeric () const{{{ bool Object::is_numeric () const{ return PyNumber_Check(object); } // }}} // bool Object::is_sequence () const{{{ bool Object::is_sequence () const{ return PySequence_Check(object); } // }}} // bool Object::is_true () const{{{ bool Object::is_true () const{ return PyObject_IsTrue(object); } // }}} // bool Object::is_type (const Type& t) const{{{ bool Object::is_type (const Type& t) const{ return t==type(); } // }}} // bool Object::is_tuple() const{{{ bool Object::is_tuple() const { return PyTuple_Check(object); } // }}} // bool Object::is_string() const{{{ bool Object::is_string() const{ return PyString_Check(object); } // }}} // bool Object::is_dict() const{{{ bool Object::is_dict() const{ return PyDict_Check(object); } // }}} // bool Object::is_null() const {{{ bool Object::is_null() const { return NULL==object; } // }}} // bool Object::is(PyObject* pother) const{{{ bool Object::is(PyObject* pother) const{ return object == pother; } // }}} // bool Object::is(const Object& other) const{{{ bool Object::is(const Object& other) const { return object == other.ptr(); } // }}} // bool Object::operator==(const Object& o2) const{{{ bool Object::operator==(const Object& o2) const { int k = PyObject_Compare(object,*o2); check_errors(); return k == 0; } // }}} // bool Object::operator!=(const Object& o2) const{{{ bool Object::operator!=(const Object& o2) const{ int k = PyObject_Compare(object,*o2); check_errors(); return not k == 0; } // }}} // bool Object::operator>=(const Object& o2) const{{{ bool Object::operator>=(const Object& o2) const{ int k = PyObject_Compare(object,*o2); check_errors(); return k >= 0; } // }}} // bool Object::operator<=(const Object& o2) const{{{ bool Object::operator<=(const Object& o2) const{ int k = PyObject_Compare(object,*o2); check_errors(); return k <= 0; } // }}} // bool Object::operator<(const Object& o2) const{{{ bool Object::operator<(const Object& o2) const{ int k = PyObject_Compare(object,*o2); check_errors(); return k < 0; } // }}} // bool Object::operator>(const Object& o2) const{{{ bool Object::operator>(const Object& o2) const{ int k = PyObject_Compare(object,*o2); check_errors(); return k > 0; } // }}} std::ostream& operator<< (std::ostream& out, const Object& obj) { out << obj.as_string(); return out; } // These functions are ugly, and I don't like them. They change // Py_Objects ref count by going around the class. They are used to // increase the reference count on a const Object PyObject* new_reference_to(PyObject* p) { // TODO remove this Py_XINCREF(p); return p; } PyObject* new_reference_to(const Object& g) { PyObject* p = g.ptr(); Py_XINCREF(p); return p; } // It may be nice to change this to a factory, but that may // have problems like having to use pointers, when the rest of the // library normally uses non-pointers Object asObject (PyObject *p) { return Object(p, true); } }