#ifndef __PYTHON_H__
#define __PYTHON_H__
#pragma interface
#include <ctype.h>
#undef isalnum
#undef isalpha
#undef iscntrl
#undef isdigit
#undef isgraph
#undef islower
#undef isprint
#undef ispunct
#undef isspace
#undef isupper
#undef isxdigit
#undef tolower
#undef toupper
#include <iostream>
#include <Python.h>
#include <string>
#include <iterator>
#include <utility>
#include <sstream>
#include "exceptions.h"
#include "debug.h"
// I hate #define macros, seee if I can remove this
#define STANDARD_LIBRARY_HAS_RANDOM_ACCESS_ITERATOR 1
#ifdef MS_WIN32
# undef STANDARD_LIBRARY_HAS_RANDOM_ACCESS_ITERATOR
# define STANDARD_LIBRARY_HAS_RANDOM_ACCESS_ITERATOR 0
#endif
#if defined (__GNUG__) && (__GNUG__ >= 3)
# undef STANDARD_LIBRARY_HAS_RANDOM_ACCESS_ITERATOR
#endif
#if STANDARD_LIBRARY_HAS_RANDOM_ACCESS_ITERATOR
# define random_access_iterator_parent(itemtype) std::random_access_iterator<itemtype, int>
#else
# define random_access_iterator_parent(itemtype) std::iterator<std::random_access_iterator_tag,itemtype,int>
#endif
namespace python {
using namespace std;
// function to check for errors and throw an exception
// if there was any
typedef int sequence_index_type;
template<class T> class SeqBase;
template<class T> class MapBase;
class Object;
class Module;
class Dict;
class Type;
class Int;
class Long;
class Float;
class Char;
class String;
class Tuple;
PyObject* new_reference_to(const Object& g) ;
PyObject* new_reference_to(PyObject* p) ; // TODO remove this
Object asObject (PyObject *p);
std::ostream& operator<< (std::ostream& oout, const Object& obj);
void check_errors();
// class Python {{{
/*
* Create a Python interpreter class to wrap the python embedding api
*
* Make the class a Singleton to prevent more than one instance of
* the class.
*
* This is based on pyembed[0..4].c from Programming Python, Mark
* Lutz, pp571-639
*/
class Python {
public:
static Python * Instance();
~Python();
int run_interactive_one(string prompt);
int run_interactive_loop(string prompt);
void run_string(string cmd);
void set_debug(bool d) { m_debug = d;}
void set_reload(bool r) { m_reload = r; }
void reset();
void add_directory_to_path(string directory);
const string get_program_name() { return Py_GetProgramName(); }
const string get_prefix() { return Py_GetPrefix(); }
const string get_exec_prefix() { return Py_GetExecPrefix(); }
const string get_program_full_path() { return Py_GetProgramFullPath(); }
const string get_path() { return Py_GetPath(); }
const string get_version() { return Py_GetVersion(); }
const string get_platform() { return Py_GetPlatform(); }
const string get_copyright() { return Py_GetCopyright(); }
const string get_compiler() { return Py_GetCompiler(); }
const string get_build_info() { return Py_GetBuildInfo(); }
void set_argv(int argc, char *argv[]);
int make_dummy_module(string modname);
Module load_module(string modname = "__main__");
Module add_module(string modname);
Module import_module(string modname);
Object load_attribute(string modname,string attrname);
Dict get_module_dict() ;
protected:
Python();
private:
bool m_debug;
bool m_reload;
static Python * m_instance;
char** m_argv;
int m_argc;
};
// TODO move implementation to .cc files
// }}}
// class Object {{{
class Object {
private:
PyObject *object;
bool m_owned;
protected:
void set(PyObject *pyobj = Py_None, bool owned = false);
void release();
void validate();
public:
Object(const Object & obj);
Object(PyObject * pyobj = Py_None, bool owned = false);
Object & operator=(const Object & obj);
Object & operator=(PyObject * pyobj) ;
virtual ~Object() ;
void incref() ;
void decref() ;
PyObject * operator*() const;
PyObject * ptr() const;
virtual bool accepts(PyObject * pyobj) const;
std::string as_string() const;
int reference_count() const;
Type type() const;
String str () const;
String repr () const;
bool has_attr (const std::string& s) const ;
Object get_attr (const std::string& s) const;
Object get_item (const Object& key) const ;
long hash_value () const;
void set_attr (const std::string& s, const Object& value) ;
void del_attr (const std::string& s);
void del_item (const Object& key);
bool is_callable () const;
bool is_list () const;
bool is_mapping () const;
bool is_numeric () const;
bool is_sequence () const;
bool is_true () const;
bool is_type (const Type& t) const;
bool is_tuple() const;
bool is_string() const;
bool is_dict() const;
bool is_null() const;
bool is(PyObject* pother) const;
bool is(const Object& other) const;
bool operator==(const Object& o2) const;
bool operator!=(const Object& o2) const;
bool operator>=(const Object& o2) const;
bool operator<=(const Object& o2) const;
bool operator<(const Object& o2) const;
bool operator>(const Object& o2) const;
void print(FILE *fp, int flags = 0) ;
};
// }}}
// class Type {{{
class Type : public Object {
private:
protected:
public:
Type(const Type & obj) : Object( *obj ) { } ;
Type(const Object & obj) : Object( obj ) { } ;
Type(PyObject * obj, bool owned = false) : Object(obj, owned) { } ;
Type & operator=(const Object & obj);
Type & operator=(PyObject * obj);
virtual bool accepts(PyObject * pyobj) const;
};
// }}}
// class Module {{{
class Module : public Object {
private:
protected:
public:
// TODO constructor from std::string to load module
Module(const Module & obj) : Object( obj ) { } ;
Module(const Object & obj) : Object( obj ) { } ;
Module(PyObject * obj, bool owned = false) : Object(obj, owned) { } ;
Module & operator=(PyObject * obj) ;
Module & operator=(const Object & obj) ;
void reload() ;
bool accepts(PyObject * pyobj) const;
Dict get_dict() ;
Object run_method(string method_name,string argfmt,...);
Object run_method(string method_name,Tuple & args);
};
typedef Module Class;
// }}}
// class Int {{{
class Int : public Object {
private:
protected:
public:
Int(long v = 0L) : Object( PyInt_FromLong( v ), true ) { } ;
Int(int v);
Int(const Int & obj) : Object( *obj ) { } ;
Int(const Object & obj);
Int(PyObject * obj, bool owned = false) : Object(obj, owned) { } ;
Int & operator=(const Object & obj);
Int & operator=(PyObject * obj);
Int & operator=(int v);
Int & operator=(long v);
operator long() const ;
virtual bool accepts(PyObject *pyobj) const;
};
// }}}
// class Long {{{
class Long : public Object {
private:
protected:
public:
Long(long v = 0L) : Object( PyLong_FromLong( v ), true ) { } ;
Long(int v);
Long(const Long & obj) : Object( *obj ) { } ;
Long(const Object & obj);
Long(PyObject * obj, bool owned = false) : Object(obj, owned) { } ;
Long & operator=(const Object & obj);
Long & operator=(PyObject * obj);
Long & operator=(int v);
Long & operator=(long v);
operator long() const;
virtual bool accepts(PyObject *pyobj) const;
};
// }}}
// class Float {{{
class Float : public Object {
private:
protected:
public:
Float(double v = 0.0) : Object( PyFloat_FromDouble( v ), true ) { } ;
Float(const Float & obj) : Object( *obj ) { } ;
Float(const Object & obj);
Float(PyObject * obj, bool owned = false) : Object(obj, owned) { } ;
Float & operator=(const Object & obj);
Float & operator=(PyObject * obj);
Float & operator=(int v);
Float & operator=(long v);
Float & operator=(const Int & v);
Float & operator=(double v);
operator double() const;
virtual bool accepts(PyObject *pyobj) const;
};
// }}}
// class seqref {{{
template<class T>
class seqref {
protected:
SeqBase<T>& s; // the sequence
int offset; // item number
T the_item; // lvalue
public:
seqref (SeqBase<T>& seq, sequence_index_type j);
seqref (const seqref<T>& r);
~seqref() {};
operator T() const;
seqref<T>& operator=(const seqref<T>& rhs);
seqref<T>& operator=(const T& ob);
// forward everything else to the item
PyObject* ptr () const;
int reference_count () const ;
Type type () const ;
String str () const ;
String repr () const ;
bool has_attr (const std::string& attr_name) const ;
Object get_attr (const std::string& attr_name) const ;
Object get_item (const Object& key) const ;
long hash_value () const ;
bool is_callable () const ;
bool is_dict () const ;
bool is_list () const ;
bool is_mapping () const ;
bool is_numeric () const ;
bool is_sequence () const ;
bool is_true () const ;
bool is_type (const Type& t) const ;
bool is_tuple() const ;
bool is_string() const ;
// Commands
void set_attr (const std::string& attr_name, const Object& value) ;
void del_attr (const std::string& attr_name) ;
void del_item (const Object& key) ;
bool operator==(const Object& o2) const ;
bool operator!=(const Object& o2) const ;
bool operator>=(const Object& o2) const ;
bool operator<=(const Object& o2) const ;
bool operator<(const Object& o2) const ;
bool operator>(const Object& o2) const ;
};
// }}}
// SeqBase {{{
// class SeqBase<T>
// ...the base class for all sequence types
template<class T>
class SeqBase: public Object {
public:
// STL definitions
typedef int size_type;
typedef seqref<T> reference;
typedef T const_reference;
typedef seqref<T>* pointer;
typedef int difference_type;
size_type max_size() const {
return std::string::npos; // ?
}
size_type capacity() const {
return size();
}
void swap(SeqBase<T>& c) {
SeqBase<T> temp = c;
c = ptr();
set(temp.ptr());
}
size_type size () const {
return PySequence_Length (ptr());
}
SeqBase<T> ()
:Object(PyTuple_New(0), true)
{
validate();
}
SeqBase<T> (PyObject* pyob, bool owned)
: Object(pyob, owned)
{
validate();
}
SeqBase<T> (const Object& ob): Object(ob) {
validate();
}
// Assignment acquires new ownership of pointer
SeqBase<T>& operator= (const Object& rhs) {
return (*this = *rhs);
}
SeqBase<T>& operator= (PyObject* rhsp) {
if(ptr() == rhsp) return *this;
set (rhsp);
return *this;
}
bool accepts (PyObject *pyob) const {
return pyob && PySequence_Check (pyob);
}
size_type length () const {
return PySequence_Length (ptr());
}
// Element access
const T operator[](sequence_index_type index) const {
return getItem(index);
}
seqref<T> operator[](sequence_index_type index) {
return seqref<T>(*this, index);
}
T getItem (sequence_index_type i) const {
return T(asObject(PySequence_GetItem (ptr(), i)));
}
void setItem (sequence_index_type i, const T& ob) {
if (PySequence_SetItem (ptr(), i, *ob) == -1) {
throw Exception();
}
}
SeqBase<T> repeat (int count) const {
return SeqBase<T> (PySequence_Repeat (ptr(), count), true);
}
SeqBase<T> concat (const SeqBase<T>& other) const {
return SeqBase<T> (PySequence_Concat(ptr(), *other), true);
}
// more STL compatability
const T front () const {
return getItem(0);
}
seqref<T> front() {
return seqref<T>(this, 0);
}
const T back () const {
return getItem(size()-1);
}
seqref<T> back() {
return seqref<T>(this, size()-1);
}
void verify_length(size_type required_size) const
{
if (size() != required_size)
throw IndexError ("Unexpected SeqBase<T> length.");
}
void verify_length(size_type min_size, size_type max_size) const
{
size_type n = size();
if (n < min_size || n > max_size)
throw IndexError ("Unexpected SeqBase<T> length.");
}
#if 0
virtual size_type max_size() const ;
virtual size_type capacity() const ;
virtual void swap(SeqBase<T>& c) ;
virtual size_type size () const ;
explicit SeqBase<T> ();
explicit SeqBase<T> (PyObject* pyob, bool owned=false);
SeqBase<T> (const Object& ob);
// Assignment acquires new ownership of pointer
SeqBase<T>& operator= (const Object& rhs) ;
SeqBase<T>& operator= (PyObject* rhsp) ;
virtual bool accepts (PyObject *pyob) const ;
size_type length () const ;
// Element access
const T operator[](sequence_index_type index) const ;
seqref<T> operator[](sequence_index_type index) ;
virtual T getItem (sequence_index_type i) const ;
virtual void setItem (sequence_index_type i, const T& ob) ;
SeqBase<T> repeat (int count) const ;
SeqBase<T> concat (const SeqBase<T>& other) const ;
// more STL compatability
const T front () const ;
seqref<T> front() ;
const T back () const ;
seqref<T> back() ;
void verify_length(size_type required_size) const;
void verify_length(size_type min_size, size_type max_size) const;
#endif
// class iterator {{{
class iterator
: public random_access_iterator_parent(seqref<T>) {
protected:
friend class SeqBase<T>;
SeqBase<T>* seq;
int count;
public:
~iterator () ;
iterator () ;
iterator (SeqBase<T>* s, int where) ;
iterator (const iterator& other) ;
bool operator== (const iterator& other) ;
bool operator!= (const iterator& other) ;
bool operator< (const iterator& other) ;
bool operator> (const iterator& other) ;
bool operator<= (const iterator& other) ;
bool operator>= (const iterator& other) ;
seqref<T> operator*() ;
seqref<T> operator[] (sequence_index_type i) ;
iterator& operator=(const iterator& other) ;
iterator operator+(int n) const ;
iterator operator-(int n) const ;
iterator& operator+=(int n) ;
iterator& operator-=(int n) ;
int operator-(const iterator& other) const ;
iterator& operator++ () ;
iterator operator++ (int) ;
iterator& operator-- () ;
iterator operator-- (int) ;
std::string diagnose() const ;
};
// }}}
iterator begin () {
return iterator(this, 0);
}
iterator end () {
return iterator(this, length());
}
// class const_iterator {{{
class const_iterator
: public random_access_iterator_parent(const Object) {
protected:
friend class SeqBase<T>;
const SeqBase<T>* seq;
sequence_index_type count;
public:
~const_iterator () ;
const_iterator () ;
const_iterator (const SeqBase<T>* s, int where) ;
const_iterator(const const_iterator& other) ;
bool operator== (const const_iterator& other) ;
bool operator!= (const const_iterator& other) ;
bool operator< (const const_iterator& other) ;
bool operator> (const const_iterator& other) ;
bool operator<= (const const_iterator& other) ;
bool operator>= (const const_iterator& other) ;
const T operator*() const ;
const T operator[] (sequence_index_type i) const ;
const_iterator& operator=(const const_iterator& other) ;
const_iterator operator+(int n) const ;
const_iterator operator-(int n) const ;
const_iterator& operator+=(int n) ;
const_iterator& operator-=(int n) ;
int operator-(const const_iterator& other) const ;
const_iterator& operator++ () ;
const_iterator operator++ (int) ;
const_iterator& operator-- () ;
const_iterator operator-- (int) ;
};
// }}}
const_iterator begin () const {
return const_iterator(this, 0);
}
const_iterator end () const {
return const_iterator(this, length());
}
};
// }}}
typedef SeqBase<Object> Sequence;
// Char {{{
// ==================================================
// class Char
// Python strings return strings as individual elements.
// I'll try having a class Char which is a String of length 1
//
class Char: public Object {
public:
explicit Char (PyObject *pyob, bool owned = false): Object(pyob, owned) {
validate();
}
Char (const Object& ob): Object(ob) {
validate();
}
Char (const std::string& v = "")
:Object(PyString_FromStringAndSize (const_cast<char*>(v.c_str()),1), true)
{
validate();
}
Char (char v)
: Object(PyString_FromStringAndSize (&v, 1), true)
{
validate();
}
// Assignment acquires new ownership of pointer
Char& operator= (const Object& rhs) {
return (*this = *rhs);
}
Char& operator= (PyObject* rhsp) {
if(ptr() == rhsp) return *this;
set (rhsp);
return *this;
}
// Membership
virtual bool accepts (PyObject *pyob) const {
return pyob && PyString_Check (pyob) &&
(PySequence_Length (pyob) == 1);
}
// Assignment from C string
Char& operator= (const std::string& v) {
set(PyString_FromStringAndSize (const_cast<char*>(v.c_str()),1), true);
return *this;
}
Char& operator= (char v) {
set(PyString_FromStringAndSize (&v, 1), true);
return *this;
}
// Conversion
operator String() const;
operator std::string () const {
return std::string(PyString_AsString (ptr()));
}
};
// }}}
// String {{{
class String: public SeqBase<Char> {
public:
virtual int capacity() const ;
explicit String (PyObject *pyob, bool owned = false);
String (const Object& ob);
String();
String (const std::string& v );
String (const std::string& v, std::string::size_type vsize);
String (const char *v, int vsize);
String (const char* v);
// Assignment acquires new ownership of pointer
String& operator= (const Object& rhs) ;
String& operator= (PyObject* rhsp) ;
// Membership
virtual bool accepts (PyObject *pyob) const ;
// Assignment from C string
String& operator= (const std::string& v) ;
// Queries
virtual int size () const ;
operator std::string () const ;
std::string as_std_string() const ;
};
// }}}
// Tuple {{{
// ==================================================
// class Tuple
class Tuple: public Sequence {
private:
bool locked;
public:
virtual void setItem (sequence_index_type offset, const Object&ob) {
// note PyTuple_SetItem is a thief...
if(PyTuple_SetItem (ptr(), offset, new_reference_to(ob)) == -1) {
throw Exception();
}
}
// Constructor
explicit Tuple (PyObject *pyob, bool owned = false): Sequence (pyob, owned), locked(false){
validate();
}
Tuple (const Object& ob): Sequence(ob), locked(false){
validate();
}
// New tuple of a given size
explicit Tuple (int size = 0) {
locked = false;
set(PyTuple_New (size), true);
validate ();
for (sequence_index_type i=0; i < size; i++) {
if(PyTuple_SetItem (ptr(), i, new_reference_to(Py_None)) == -1) {
throw Exception();
}
}
}
// Tuple from any sequence
explicit Tuple (const Sequence& s) {
set(PyTuple_New (s.length()), true);
validate();
for(sequence_index_type i=0;
i < s.length();
i++) {
if(PyTuple_SetItem (ptr(), i, new_reference_to(s[i])) == -1) {
throw Exception();
}
}
}
// Assignment acquires new ownership of pointer
Tuple& operator= (const Object& rhs) {
return (*this = *rhs);
}
Tuple& operator= (PyObject* rhsp) {
if(ptr() == rhsp) return *this;
set (rhsp);
return *this;
}
// Membership
virtual bool accepts (PyObject *pyob) const {
return pyob && PyTuple_Check (pyob);
}
Tuple getSlice (int i, int j) const {
return Tuple (PySequence_GetSlice (ptr(), i, j), true);
}
};
// }}}
// List {{{
// ==================================================
// class List
class List: public Sequence {
public:
// Constructor
explicit List (PyObject *pyob, bool owned = false): Sequence(pyob, owned) {
validate();
}
List (const Object& ob): Sequence(ob) {
validate();
}
// Creation at a fixed size
List (int size = 0) {
set(PyList_New (size), true);
validate();
for (sequence_index_type i=0; i < size; i++) {
if(PyList_SetItem (ptr(), i, new_reference_to(Py_None)) == -1) {
throw Exception();
}
}
}
// List from a sequence
List (const Sequence& s): Sequence() {
int n = s.length();
set(PyList_New (n), true);
validate();
for (sequence_index_type i=0; i < n; i++) {
if(PyList_SetItem (ptr(), i, new_reference_to(s[i])) == -1) {
throw Exception();
}
}
}
virtual size_type capacity() const {
return max_size();
}
// Assignment acquires new ownership of pointer
List& operator= (const Object& rhs) {
return (*this = *rhs);
}
List& operator= (PyObject* rhsp) {
if(ptr() == rhsp) return *this;
set (rhsp);
return *this;
}
// Membership
virtual bool accepts (PyObject *pyob) const {
return pyob && PyList_Check (pyob);
}
List getSlice (int i, int j) const {
return List (PyList_GetSlice (ptr(), i, j), true);
}
void setSlice (int i, int j, const Object& v) {
if(PyList_SetSlice (ptr(), i, j, *v) == -1) {
throw Exception();
}
}
void append (const Object& ob) {
if(PyList_Append (ptr(), *ob) == -1) {
throw Exception();
}
}
void insert (int i, const Object& ob) {
if(PyList_Insert (ptr(), i, *ob) == -1) {
throw Exception();
}
}
void sort () {
if(PyList_Sort(ptr()) == -1) {
throw Exception();
}
}
void reverse () {
if(PyList_Reverse(ptr()) == -1) {
throw Exception();
}
}
};
// }}}
// class mapref {{{
template<class T>
class mapref {
protected:
MapBase<T>& s; // the map
Object key; // item key
T the_item;
public:
mapref<T> (MapBase<T>& map, const std::string& k);
mapref<T> (MapBase<T>& map, const Object& k);
~mapref<T>() ;
mapref<T>& operator=(const mapref<T>& other) ;
mapref<T>& operator= (const T& ob) ;
operator T() const ;
PyObject* ptr () const ;
int reference_count () const ; // the mapref count
Type type () const ;
String str () const ;
String repr () const ;
bool has_attr (const std::string& attr_name) const ;
Object get_attr (const std::string& attr_name) const ;
Object get_item (const Object& k) const ;
long hash_value () const ;
bool is_callable () const ;
bool is_list () const ;
bool is_mapping () const ;
bool is_numeric () const ;
bool is_sequence () const ;
bool is_true () const ;
bool is_type (const Type& t) const ;
bool is_tuple() const ;
bool is_string() const ;
void set_attr (const std::string& attr_name, const Object& value) ;
void del_attr (const std::string& attr_name) ;
void del_item (const Object& k) ;
};
// }}}
// class MapBase {{{
template<class T>
class MapBase: public Object {
protected:
public:
explicit MapBase<T>(){} // This was private, should it still be
explicit MapBase<T> (PyObject *pyob, bool owned = false);
MapBase<T> (const MapBase<T>& ob) ;
MapBase<T>& operator= (const Object& rhs) ;
MapBase<T>& operator= (PyObject* rhsp) ;
virtual bool accepts (PyObject *pyob) const ;
void clear () ;
T operator[](const std::string& key) const ;
T operator[](const Object& key) const ;
mapref<T> operator[](const std::string& key) ;
mapref<T> operator[](const Object& key) ;
int length () const ;
virtual int has_key (const std::string& s) const ;
virtual int has_key (const Object& s) const ;
virtual T get_item (const std::string& s) const ;
virtual T get_item (const Object& s) const ;
virtual void set_item (const std::string& s, const Object& ob) ;
virtual void set_item (const Object& s, const Object& ob) ;
void del_item (const std::string& s) ;
void del_item (const Object& s) ;
List keys () const ;
List values () const ; // each returned item is a (key, value) pair
List items () const ;
};
// }}}
typedef MapBase<Object> Mapping;
// Dict {{{
// ==================================================
// class Dict
class Dict: public Mapping {
public:
// Constructor
explicit Dict (PyObject *pyob, bool owned=false): Mapping (pyob, owned) {
validate();
}
Dict (const Dict& ob): Mapping(ob) {
validate();
}
// Creation
Dict () {
set(PyDict_New (), true);
validate();
}
// Assignment acquires new ownership of pointer
Dict& operator= (const Object& rhs) {
return (*this = *rhs);
}
Dict& operator= (PyObject* rhsp) {
if(ptr() == rhsp) return *this;
set(rhsp);
return *this;
}
// Membership
virtual bool accepts (PyObject *pyob) const {
return pyob && PyDict_Check (pyob);
}
};
// }}}
}
#endif // __PYTHON_H__
syntax highlighted by Code2HTML, v. 0.9.1