provide python interpreter for mussa qui via a seperate thread
[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 MussaPython::MussaPython()
13 {
14   try {
15     // add our mussa module to our environment
16     PyImport_AppendInittab("mussa", &initmussa);
17     PyImport_AppendInittab("mussaqui", &initmussaqui);
18     // go ahead and finish initalizing python
19     Py_Initialize();
20     // get reference to the global namespace
21     py::object main_module(
22         (py::handle<>(py::borrowed(PyImport_AddModule("__main__"))))
23     );
24     main_namespace = main_module.attr("__dict__");
25     // FIXME: this really should be a configuration file?
26     run("import __main__\n"
27         "import mussa\n"
28         "import mussaqui");       
29   } catch (py::error_already_set e) {
30     PyErr_Print();
31   }
32 }
33
34 void MussaPython::run(std::string code)
35 {
36   try {
37     PyObject *global_ptr = main_namespace.ptr();
38     py::object result( py::handle<>(
39        (PyRun_String(code.c_str(), Py_file_input, global_ptr, global_ptr)
40     )));
41   } catch( py::error_already_set ) {
42     PyErr_Print();
43   }
44 }
45
46 py::object MussaPython::eval(std::string code)
47 {
48   try {
49     PyObject *global_ptr = main_namespace.ptr();
50     py::object result( py::handle<>(
51        (PyRun_String(code.c_str(), Py_eval_input, global_ptr, global_ptr)
52     )));
53     return result;
54   } catch( py::error_already_set ) {
55     PyErr_Print();
56   }
57   py::object result;
58   return  result;
59 }
60
61
62 void MussaPython::interpreter() 
63 {
64   try {
65     run("import sys\n"
66         "sys.argv = ['Mussa']\n"
67         "banner='Welcome to Mussa'\n"
68         "try:\n"
69         "  from IPython.Shell import IPShellEmbed\n"
70         "  ipshell = IPShellEmbed(banner=banner)\n"
71         "  ipshell()\n"
72         "except ImportError, e:\n"
73         "  import code\n"
74         "  code.interact(banner, local=globals())\n"
75         "print 'exiting interpreter'\n"
76     );
77   } catch (py::error_already_set e) {
78     PyErr_Print();
79   }
80 }
81 void MussaPython::simple_interpreter(FILE *fp)
82 {
83   try {
84     PyRun_InteractiveLoop(fp, "mussa");
85   } catch (py::error_already_set e) {
86     PyErr_Print();
87   }
88 }
89
90 py::object MussaPython::operator[](std::string name)
91
92   typedef std::vector< std::string > string_vector;
93   string_vector split_name;
94   alg::split(split_name, name, alg::is_any_of("."));
95   
96   py::object lookup = main_namespace["__main__"];
97   
98   for (string_vector::const_iterator name_i = split_name.begin();
99        name_i != split_name.end();
100        ++name_i)
101   {
102     lookup = lookup.attr("__dict__")[*name_i];
103   }
104   return lookup;
105 }
106
107 //! return a reference to a single mussa python interpreter
108 MussaPython& get_py()
109 {
110   static MussaPython *py;
111   if (!py) {
112     py = new MussaPython;
113   }
114   return *py;
115 }