#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