Store Sequence sequence location in a shared_ptr class
[mussa.git] / py / python.cpp
1 #include "py/python.hpp"
2 namespace py = boost::python;
3
4 #include <iostream>
5 #include <string>
6 #include <vector>
7
8 #include <boost/algorithm/string/split.hpp>
9 #include <boost/algorithm/string/classification.hpp>
10 namespace alg = boost::algorithm;
11
12
13 MussaPython::MussaPython()
14 {
15 }
16
17 void MussaPython::add_module(const std::string &name, python_module_init initfunc)
18 {
19   python_modules.push_back( module_item(name, initfunc) );
20 }
21
22 void MussaPython::AppendInittab(const module_item &item)
23 {
24   PyImport_AppendInittab(const_cast<char *>(item.first.c_str()), item.second);
25 }
26
27 void MussaPython::init_interpreter()
28 {
29   try {
30     // add any compiled in modules to our environment
31     for_each(python_modules.begin(), python_modules.end(), AppendInittab);
32     // go ahead and finish initalizing python
33     Py_Initialize();
34     // get reference to the global namespace
35     py::object main_module(
36         (py::handle<>(py::borrowed(PyImport_AddModule("__main__"))))
37     );
38     // setting the main_namespace must come before any calls to run or eval
39     main_namespace = main_module.attr("__dict__");
40     run("import __main__\n");
41     // import modules that were added to us into the interpreter
42     for(module_list::const_iterator item = python_modules.begin();
43         item != python_modules.end();
44         ++item)
45     {
46       std::string code("import " + item->first);
47       run(code);
48     }
49   } catch (py::error_already_set e) {
50     PyErr_Print();
51   }
52 }
53
54 py::object MussaPython::get_namespace()
55 {
56   if (main_namespace.ptr() == Py_None) {
57     init_interpreter();
58   }
59   return main_namespace;
60 }
61
62 void MussaPython::run(std::string code)
63 {
64   try {
65     PyObject *global_ptr = get_namespace().ptr();
66     py::object result( py::handle<>(
67        (PyRun_String(code.c_str(), Py_file_input, global_ptr, global_ptr)
68     )));
69   } catch( py::error_already_set ) {
70     PyErr_Print();
71   }
72 }
73
74 py::object MussaPython::eval(std::string code)
75 {
76   try {
77     PyObject *global_ptr = get_namespace().ptr();
78     py::object result( py::handle<>(
79        (PyRun_String(code.c_str(), Py_eval_input, global_ptr, global_ptr)
80     )));
81     return result;
82   } catch( py::error_already_set ) {
83     PyErr_Print();
84   }
85   py::object result;
86   return  result;
87 }
88
89
90 void MussaPython::interpreter() 
91 {
92   try {
93     run("import sys\n"
94         "sys.argv = ['Mussa']\n"
95         "banner='Welcome to Mussa'\n"
96         "try:\n"
97         "  from IPython.Shell import IPShellEmbed\n"
98         "  ipshell = IPShellEmbed(banner=banner)\n"
99         "  ipshell()\n"
100         "except ImportError, e:\n"
101         "  import code\n"
102         "  code.interact(banner, local=globals())\n"
103         "print 'exiting interpreter'\n"
104     );
105   } catch (py::error_already_set e) {
106     PyErr_Print();
107   }
108 }
109 void MussaPython::simple_interpreter(FILE *fp)
110 {
111   try {
112     PyRun_InteractiveLoop(fp, "mussa");
113   } catch (py::error_already_set e) {
114     PyErr_Print();
115   }
116 }
117
118 py::object MussaPython::operator[](std::string name)
119
120   typedef std::vector< std::string > string_vector;
121   string_vector split_name;
122   alg::split(split_name, name, alg::is_any_of("."));
123   
124   py::object lookup = get_namespace()["__main__"];
125   
126   for (string_vector::const_iterator name_i = split_name.begin();
127        name_i != split_name.end();
128        ++name_i)
129   {
130     lookup = lookup.attr("__dict__")[*name_i];
131   }
132   return lookup;
133 }
134
135 //! return a reference to a single mussa python interpreter
136 MussaPython *get_py_ptr()
137 {
138   static MussaPython *py;
139   if (!py) {
140     py = new MussaPython;
141   }
142   return py;
143 }
144
145 MussaPython &get_py()
146 {
147   return *get_py_ptr();
148 }