Fixes to Python importing; removed "hello" precommand

This commit is contained in:
John Wiegley 2009-11-10 14:16:40 -05:00
parent 5ffa987daf
commit 91e8378f04
7 changed files with 144 additions and 117 deletions

View file

@ -1,7 +0,0 @@
import ledger
def precmd_hello():
hello = ledger.Value()
hello.set_string("Well, hello yourself! This is Ledger, coming to you from Python Land.")
print hello
return hello

View file

@ -20,7 +20,7 @@ class LedgerHandler(BaseHTTPRequestHandler):
except Exception:
print "Saw exception in POST handler"
def cmd_server():
def main(*args):
try:
port = 9000
server = HTTPServer(('', port), LedgerHandler)
@ -31,3 +31,6 @@ def cmd_server():
print "Shutting down server"
server.socket.close()
print __name__
if __name__ == '__main__':
main()

View file

@ -99,66 +99,75 @@ void python_interpreter_t::initialize()
Py_Initialize();
assert(Py_IsInitialized());
hack_system_paths();
object main_module = python::import("__main__");
if (! main_module)
throw_(std::logic_error,
throw_(std::runtime_error,
_("Python failed to initialize (couldn't find __main__)"));
main_nspace = extract<dict>(main_module.attr("__dict__"));
if (! main_nspace)
throw_(std::logic_error,
throw_(std::runtime_error,
_("Python failed to initialize (couldn't find __dict__)"));
python::detail::init_module("ledger", &initialize_for_python);
is_initialized = true;
// Hack ledger.__path__ so it points to a real location
python::object module_sys = import("sys");
python::object sys_dict = module_sys.attr("__dict__");
python::list paths(sys_dict["path"]);
bool path_initialized = false;
int n = python::extract<int>(paths.attr("__len__")());
for (int i = 0; i < n; i++) {
python::extract<std::string> str(paths[i]);
path pathname(str);
DEBUG("python.interp", "sys.path = " << pathname);
if (exists(pathname / "ledger" / "__init__.py")) {
if (python::object module_ledger = import("ledger")) {
DEBUG("python.interp",
"Setting ledger.__path__ = " << (pathname / "ledger"));
python::object ledger_dict = module_ledger.attr("__dict__");
python::list temp_list;
temp_list.append((pathname / "ledger").string());
ledger_dict["__path__"] = temp_list;
} else {
throw_(std::logic_error,
_("Python failed to initialize (couldn't find ledger)"));
}
path_initialized = true;
break;
}
}
#if defined(DEBUG_ON)
if (! path_initialized)
DEBUG("python.init",
"Ledger failed to find 'ledger/__init__.py' on the PYTHONPATH");
#endif
}
catch (const error_already_set&) {
PyErr_Print();
throw_(std::logic_error, _("Python failed to initialize"));
throw_(std::runtime_error, _("Python failed to initialize"));
}
TRACE_FINISH(python_init, 1);
}
object python_interpreter_t::import(const string& str)
void python_interpreter_t::hack_system_paths()
{
// Hack ledger.__path__ so it points to a real location
python::object sys_module = python::import("sys");
python::object sys_dict = sys_module.attr("__dict__");
python::list paths(sys_dict["path"]);
#if defined(DEBUG_ON)
bool path_initialized = false;
#endif
int n = python::extract<int>(paths.attr("__len__")());
for (int i = 0; i < n; i++) {
python::extract<std::string> str(paths[i]);
path pathname(str);
DEBUG("python.interp", "sys.path = " << pathname);
if (exists(pathname / "ledger" / "__init__.py")) {
if (python::object module_ledger = python::import("ledger")) {
DEBUG("python.interp",
"Setting ledger.__path__ = " << (pathname / "ledger"));
python::object ledger_dict = module_ledger.attr("__dict__");
python::list temp_list;
temp_list.append((pathname / "ledger").string());
ledger_dict["__path__"] = temp_list;
} else {
throw_(std::runtime_error,
_("Python failed to initialize (couldn't find ledger)"));
}
#if defined(DEBUG_ON)
path_initialized = true;
#endif
break;
}
}
#if defined(DEBUG_ON)
if (! path_initialized)
DEBUG("python.init",
"Ledger failed to find 'ledger/__init__.py' on the PYTHONPATH");
#endif
}
object python_interpreter_t::import_into_main(const string& str)
{
if (! is_initialized)
initialize();
@ -166,7 +175,8 @@ object python_interpreter_t::import(const string& str)
try {
object mod = python::import(str.c_str());
if (! mod)
throw_(std::logic_error, _("Failed to import Python module %1") << str);
throw_(std::runtime_error,
_("Failed to import Python module %1") << str);
// Import all top-level entries directly into the main namespace
main_nspace.update(mod.attr("__dict__"));
@ -179,6 +189,32 @@ object python_interpreter_t::import(const string& str)
return object();
}
object python_interpreter_t::import_option(const string& str)
{
path file(str);
python::object sys_module = python::import("sys");
python::object sys_dict = sys_module.attr("__dict__");
python::list paths(sys_dict["path"]);
#if BOOST_VERSION >= 103700
paths.insert(0, file.parent_path().string());
sys_dict["path"] = paths;
string name = file.filename();
if (contains(name, ".py"))
name = file.stem();
#else // BOOST_VERSION >= 103700
paths.insert(0, file.branch_path().string());
sys_dict["path"] = paths;
string name = file.leaf();
#endif // BOOST_VERSION >= 103700
return python::import(python::str(name.c_str()));
}
object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode)
{
bool first = true;
@ -212,7 +248,7 @@ object python_interpreter_t::eval(std::istream& in, py_eval_mode_t mode)
}
catch (const error_already_set&) {
PyErr_Print();
throw_(std::logic_error, _("Failed to evaluate Python code"));
throw_(std::runtime_error, _("Failed to evaluate Python code"));
}
return object();
}
@ -234,7 +270,7 @@ object python_interpreter_t::eval(const string& str, py_eval_mode_t mode)
}
catch (const error_already_set&) {
PyErr_Print();
throw_(std::logic_error, _("Failed to evaluate Python code"));
throw_(std::runtime_error, _("Failed to evaluate Python code"));
}
return object();
}
@ -255,7 +291,7 @@ value_t python_interpreter_t::python_command(call_scope_t& args)
std::strcpy(argv[i + 1], arg.c_str());
}
int status;
int status = 1;
try {
status = Py_Main(static_cast<int>(args.size()) + 1, argv);
@ -277,6 +313,44 @@ value_t python_interpreter_t::python_command(call_scope_t& args)
return NULL_VALUE;
}
value_t python_interpreter_t::server_command(call_scope_t& args)
{
if (! is_initialized)
initialize();
python::object server_module;
try {
server_module = python::import("ledger.server");
if (! server_module)
throw_(std::runtime_error,
_("Could not import ledger.server; please check your PYTHONPATH"));
}
catch (const error_already_set&) {
PyErr_Print();
throw_(std::runtime_error,
_("Could not import ledger.server; please check your PYTHONPATH"));
}
if (python::object main_function = server_module.attr("main")) {
functor_t func(main_function, "main");
try {
func(args);
}
catch (const error_already_set&) {
PyErr_Print();
throw_(std::runtime_error,
_("Error while invoking ledger.server's main() function"));
}
return true;
} else {
throw_(std::runtime_error,
_("The ledger.server module is missing its main() function!"));
}
return false;
}
option_t<python_interpreter_t> *
python_interpreter_t::lookup_option(const char * p)
{
@ -304,7 +378,7 @@ expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
DEBUG("python.interp", "Python lookup: " << name);
if (python::object obj = main_nspace.get(name.c_str()))
return WRAP_FUNCTOR(functor_t(name, obj));
return WRAP_FUNCTOR(functor_t(obj, name));
}
break;
@ -320,6 +394,11 @@ expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
if (is_eq(p, "python"))
return MAKE_FUNCTOR(python_interpreter_t::python_command);
break;
case 's':
if (is_eq(p, "server"))
return MAKE_FUNCTOR(python_interpreter_t::server_command);
break;
}
}
@ -349,7 +428,7 @@ namespace {
dynamic_cast<const auto_xact_t *>(scope))
lst.append(ptr(auto_xact));
else
throw_(std::runtime_error,
throw_(std::logic_error,
_("Cannot downcast scoped object to specific type"));
} else {
lst.append(value);

View file

@ -57,8 +57,10 @@ public:
}
void initialize();
void hack_system_paths();
python::object import(const string& name);
python::object import_into_main(const string& name);
python::object import_option(const string& name);
enum py_eval_mode_t {
PY_EVAL_EXPR,
@ -67,16 +69,17 @@ public:
};
python::object eval(std::istream& in,
py_eval_mode_t mode = PY_EVAL_EXPR);
py_eval_mode_t mode = PY_EVAL_EXPR);
python::object eval(const string& str,
py_eval_mode_t mode = PY_EVAL_EXPR);
py_eval_mode_t mode = PY_EVAL_EXPR);
python::object eval(const char * c_str,
py_eval_mode_t mode = PY_EVAL_EXPR) {
py_eval_mode_t mode = PY_EVAL_EXPR) {
string str(c_str);
return eval(str, mode);
}
value_t python_command(call_scope_t& scope);
value_t server_command(call_scope_t& args);
class functor_t {
functor_t();
@ -87,9 +90,9 @@ public:
public:
string name;
functor_t(const string& _name, python::object _func)
functor_t(python::object _func, const string& _name)
: func(_func), name(_name) {
TRACE_CTOR(functor_t, "const string&, python::object");
TRACE_CTOR(functor_t, "python::object, const string&");
}
functor_t(const functor_t& other)
: func(other.func), name(other.name) {
@ -106,41 +109,10 @@ public:
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
const string& name);
#if BOOST_VERSION >= 103700
OPTION_(python_interpreter_t, import_, DO_(scope) {
interactive_t args(scope, "s");
path file(args.get<string>(0));
python::object module_sys = parent->import("sys");
python::object sys_dict = module_sys.attr("__dict__");
python::list paths(sys_dict["path"]);
paths.insert(0, file.parent_path().string());
sys_dict["path"] = paths;
string name = file.filename();
if (contains(name, ".py"))
parent->import(file.stem());
else
parent->import(name);
interactive_t args(scope, "ss");
parent->import_option(args.get<string>(1));
});
#else // BOOST_VERSION >= 103700
OPTION_(python_interpreter_t, import_, DO_(scope) {
interactive_t args(scope, "s");
path file(args.get<string>(0));
python::object module_sys = parent->import("sys");
python::object sys_dict = module_sys.attr("__dict__");
python::list paths(sys_dict["path"]);
paths.insert(0, file.branch_path().string());
sys_dict["path"] = paths;
parent->import(file.leaf());
});
#endif // BOOST_VERSION >= 103700
};
extern shared_ptr<python_interpreter_t> python_session;

View file

@ -453,15 +453,6 @@ value_t report_t::echo_command(call_scope_t& scope)
return true;
}
bool report_t::maybe_import(const string& module)
{
if (lookup(symbol_t::OPTION, "import_")) {
expr_t(string("import_(\"") + module + "\")").calc(*this);
return true;
}
return false;
}
option_t<report_t> * report_t::lookup_option(const char * p)
{
switch (*p) {
@ -930,8 +921,6 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
(reporter<post_t, post_handler_ptr, &report_t::commodities_report>
(new format_posts(*this, report_format(HANDLER(pricesdb_format_))),
*this, "#pricesdb"));
else if (is_eq(p, "python") && maybe_import("ledger.interp"))
return session.lookup(symbol_t::COMMAND, "python");
break;
case 'r':
@ -947,9 +936,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
case 's':
if (is_eq(p, "stats") || is_eq(p, "stat"))
return WRAP_FUNCTOR(report_statistics);
else
if (is_eq(p, "server") && maybe_import("ledger.server"))
return session.lookup(symbol_t::COMMAND, "server");
else if (is_eq(p, "server"))
return session.lookup(symbol_t::COMMAND, "server");
break;
case 'x':
@ -981,10 +969,6 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
(reporter<post_t, post_handler_ptr, &report_t::generate_report>
(new format_posts(*this, report_format(HANDLER(print_format_)),
false), *this, "#generate"));
case 'h':
if (is_eq(p, "hello") && maybe_import("ledger.hello"))
return session.lookup(symbol_t::PRECOMMAND, "hello");
break;
case 'p':
if (is_eq(p, "parse"))
return WRAP_FUNCTOR(parse_command);

View file

@ -183,8 +183,6 @@ public:
HANDLED(lots_actual));
}
bool maybe_import(const string& module);
void report_options(std::ostream& out)
{
HANDLER(abbrev_len_).report(out);

View file

@ -235,9 +235,7 @@ ledger_la_DEPENDENCIES = $(lib_LTLIBRARIES)
ledger_la_LDFLAGS = -avoid-version -module
ledger_la_LIBADD = $(LIBOBJS) $(lib_LTLIBRARIES) $(INTLLIBS)
pkgpython_PYTHON = python/__init__.py \
python/hello.py \
python/server.py
pkgpython_PYTHON = python/__init__.py python/server.py
endif