#ifndef __PYTHON_H__ #define __PYTHON_H__ #pragma interface #include #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 #include #include #include #include #include #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 #else # define random_access_iterator_parent(itemtype) std::iterator #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 SeqBase; template 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 seqref { protected: SeqBase& s; // the sequence int offset; // item number T the_item; // lvalue public: seqref (SeqBase& seq, sequence_index_type j); seqref (const seqref& r); ~seqref() {}; operator T() const; seqref& operator=(const seqref& rhs); seqref& 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 // ...the base class for all sequence types template class SeqBase: public Object { public: // STL definitions typedef int size_type; typedef seqref reference; typedef T const_reference; typedef seqref* pointer; typedef int difference_type; size_type max_size() const { return std::string::npos; // ? } size_type capacity() const { return size(); } void swap(SeqBase& c) { SeqBase temp = c; c = ptr(); set(temp.ptr()); } size_type size () const { return PySequence_Length (ptr()); } SeqBase () :Object(PyTuple_New(0), true) { validate(); } SeqBase (PyObject* pyob, bool owned) : Object(pyob, owned) { validate(); } SeqBase (const Object& ob): Object(ob) { validate(); } // Assignment acquires new ownership of pointer SeqBase& operator= (const Object& rhs) { return (*this = *rhs); } SeqBase& 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 operator[](sequence_index_type index) { return seqref(*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 repeat (int count) const { return SeqBase (PySequence_Repeat (ptr(), count), true); } SeqBase concat (const SeqBase& other) const { return SeqBase (PySequence_Concat(ptr(), *other), true); } // more STL compatability const T front () const { return getItem(0); } seqref front() { return seqref(this, 0); } const T back () const { return getItem(size()-1); } seqref back() { return seqref(this, size()-1); } void verify_length(size_type required_size) const { if (size() != required_size) throw IndexError ("Unexpected SeqBase 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 length."); } #if 0 virtual size_type max_size() const ; virtual size_type capacity() const ; virtual void swap(SeqBase& c) ; virtual size_type size () const ; explicit SeqBase (); explicit SeqBase (PyObject* pyob, bool owned=false); SeqBase (const Object& ob); // Assignment acquires new ownership of pointer SeqBase& operator= (const Object& rhs) ; SeqBase& operator= (PyObject* rhsp) ; virtual bool accepts (PyObject *pyob) const ; size_type length () const ; // Element access const T operator[](sequence_index_type index) const ; seqref operator[](sequence_index_type index) ; virtual T getItem (sequence_index_type i) const ; virtual void setItem (sequence_index_type i, const T& ob) ; SeqBase repeat (int count) const ; SeqBase concat (const SeqBase& other) const ; // more STL compatability const T front () const ; seqref front() ; const T back () const ; seqref 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) { protected: friend class SeqBase; SeqBase* seq; int count; public: ~iterator () ; iterator () ; iterator (SeqBase* 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 operator*() ; seqref 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; const SeqBase* seq; sequence_index_type count; public: ~const_iterator () ; const_iterator () ; const_iterator (const SeqBase* 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 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(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(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 { 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 mapref { protected: MapBase& s; // the map Object key; // item key T the_item; public: mapref (MapBase& map, const std::string& k); mapref (MapBase& map, const Object& k); ~mapref() ; mapref& operator=(const mapref& other) ; mapref& 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 MapBase: public Object { protected: public: explicit MapBase(){} // This was private, should it still be explicit MapBase (PyObject *pyob, bool owned = false); MapBase (const MapBase& ob) ; MapBase& operator= (const Object& rhs) ; MapBase& 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 operator[](const std::string& key) ; mapref 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 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__