#include "python.h"
#include <typeinfo>
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<char *>( 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<char *>( 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<char *>( 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<char *>( 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);
}
}
syntax highlighted by Code2HTML, v. 0.9.1