#include "py/python.hpp"
+namespace py = boost::python;
#include <iostream>
+#include <string>
+#include <vector>
+
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+namespace alg = boost::algorithm;
-namespace py = boost::python;
MussaPython::MussaPython()
+{
+}
+
+void MussaPython::add_module(const std::string &name, python_module_init initfunc)
+{
+ python_modules.push_back( module_item(name, initfunc) );
+}
+
+void MussaPython::AppendInittab(const module_item &item)
+{
+ PyImport_AppendInittab(const_cast<char *>(item.first.c_str()), item.second);
+}
+
+void MussaPython::init_interpreter()
{
try {
- // add our mussa module to our environment
- PyImport_AppendInittab("mussa", &initmussa);
+ // add any compiled in modules to our environment
+ for_each(python_modules.begin(), python_modules.end(), AppendInittab);
// go ahead and finish initalizing python
Py_Initialize();
// get reference to the global namespace
py::object main_module(
(py::handle<>(py::borrowed(PyImport_AddModule("__main__"))))
);
+ // setting the main_namespace must come before any calls to run or eval
main_namespace = main_module.attr("__dict__");
- // FIXME: this really should be a configuration file?
- run("import __main__\n"
- "import mussa\n"
- "import webbrowser\n");
+ run("import __main__\n");
+ // import modules that were added to us into the interpreter
+ for(module_list::const_iterator item = python_modules.begin();
+ item != python_modules.end();
+ ++item)
+ {
+ std::string code("import " + item->first);
+ run(code);
+ }
} catch (py::error_already_set e) {
PyErr_Print();
}
}
+py::object MussaPython::get_namespace()
+{
+ if (main_namespace.ptr() == Py_None) {
+ init_interpreter();
+ }
+ return main_namespace;
+}
+
void MussaPython::run(std::string code)
{
try {
- PyObject *global_ptr = main_namespace.ptr();
+ PyObject *global_ptr = get_namespace().ptr();
py::object result( py::handle<>(
(PyRun_String(code.c_str(), Py_file_input, global_ptr, global_ptr)
)));
py::object MussaPython::eval(std::string code)
{
try {
- PyObject *global_ptr = main_namespace.ptr();
+ PyObject *global_ptr = get_namespace().ptr();
py::object result( py::handle<>(
(PyRun_String(code.c_str(), Py_eval_input, global_ptr, global_ptr)
)));
}
-void MussaPython::interpreter(FILE *fp)
+void MussaPython::interpreter()
+{
+ try {
+ run("import sys\n"
+ "sys.argv = ['Mussa']\n"
+ "banner='Welcome to Mussa'\n"
+ "try:\n"
+ " from IPython.Shell import IPShellEmbed\n"
+ " ipshell = IPShellEmbed(banner=banner)\n"
+ " ipshell()\n"
+ "except ImportError, e:\n"
+ " import code\n"
+ " code.interact(banner, local=globals())\n"
+ "print 'exiting interpreter'\n"
+ );
+ } catch (py::error_already_set e) {
+ PyErr_Print();
+ }
+}
+void MussaPython::simple_interpreter(FILE *fp)
{
try {
PyRun_InteractiveLoop(fp, "mussa");
py::object MussaPython::operator[](std::string name)
{
- std::string code = "reduce(lambda m,n: m.__dict__[n], [__main__] + '";
- code += name;
- code += "'.split('.'))";
- return eval(code);
- /*
- py::object py_name(name);
- py::object name_list = py_name.attr("split")(".");
- int name_list_len = extract<int>(name_list.attr("__len__")());
- py::object lookup = main_namespace["__main__"];
- for(int i=0; i < name_list_len; ++i) {
- lookup = lookup.attr("__dict__")(name_list[i]);
- //std::cout << lookup << std::endl;
+ typedef std::vector< std::string > string_vector;
+ string_vector split_name;
+ alg::split(split_name, name, alg::is_any_of("."));
+
+ py::object lookup = get_namespace()["__main__"];
+
+ for (string_vector::const_iterator name_i = split_name.begin();
+ name_i != split_name.end();
+ ++name_i)
+ {
+ lookup = lookup.attr("__dict__")[*name_i];
}
return lookup;
- */
}
//! return a reference to a single mussa python interpreter
-MussaPython& get_py()
+MussaPython *get_py_ptr()
{
- static MussaPython py;
+ static MussaPython *py;
+ if (!py) {
+ py = new MussaPython;
+ }
return py;
}
-
+MussaPython &get_py()
+{
+ return *get_py_ptr();
+}