This now works: ledger --import os eval 'os.path.isdir("/tmp")'

This commit is contained in:
John Wiegley 2012-03-02 01:36:58 -06:00
parent 116cbd050b
commit ddba59b703
4 changed files with 135 additions and 78 deletions

View file

@ -84,16 +84,56 @@ struct python_run
python_run(python_interpreter_t * intepreter,
const string& str, int input_mode)
: result(handle<>(borrowed(PyRun_String(str.c_str(), input_mode,
intepreter->main_nspace.ptr(),
intepreter->main_nspace.ptr())))) {}
: result
(handle<>
(borrowed
(PyRun_String(str.c_str(), input_mode,
intepreter->main_module->module_globals.ptr(),
intepreter->main_module->module_globals.ptr())))) {}
operator object() {
return result;
}
};
python_module_t::python_module_t(const string& name)
: scope_t(), module_name(name), module_globals()
{
import_module(name);
}
python_module_t::python_module_t(const string& name, python::object obj)
: scope_t(), module_name(name), module_globals()
{
module_object = obj;
module_globals = extract<dict>(module_object.attr("__dict__"));
}
void python_module_t::import_module(const string& name, bool import_direct)
{
object mod = python::import(name.c_str());
if (! mod)
throw_(std::runtime_error,
_("Module import failed (couldn't find %1)") << name);
dict globals = extract<dict>(mod.attr("__dict__"));
if (! globals)
throw_(std::runtime_error,
_("Module import failed (couldn't find %1)") << name);
if (! import_direct) {
module_object = mod;
module_globals = globals;
} else {
// Import all top-level entries directly into the namespace
module_globals.update(mod.attr("__dict__"));
}
}
void python_interpreter_t::initialize()
{
if (is_initialized)
return;
TRACE_START(python_init, 1, "Initialized Python");
try {
@ -104,15 +144,7 @@ void python_interpreter_t::initialize()
hack_system_paths();
main_module = python::import("__main__");
if (! main_module)
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::runtime_error,
_("Python failed to initialize (couldn't find __dict__)"));
main_module = import_module("__main__");
python::detail::init_module("ledger", &initialize_for_python);
@ -170,28 +202,6 @@ void python_interpreter_t::hack_system_paths()
#endif
}
object python_interpreter_t::import_into_main(const string& str)
{
if (! is_initialized)
initialize();
try {
object mod = python::import(str.c_str());
if (! mod)
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__"));
return mod;
}
catch (const error_already_set&) {
PyErr_Print();
}
return object();
}
object python_interpreter_t::import_option(const string& str)
{
if (! is_initialized)
@ -229,13 +239,10 @@ object python_interpreter_t::import_option(const string& str)
}
try {
if (contains(str, ".py")) {
import_into_main(name);
} else {
object obj = python::import(python::str(name.c_str()));
main_nspace[name.c_str()] = obj;
return obj;
}
if (contains(str, ".py"))
main_module->import_module(name, true);
else
import_module(str);
}
catch (const error_already_set&) {
PyErr_Print();
@ -399,6 +406,40 @@ python_interpreter_t::lookup_option(const char * p)
return NULL;
}
expr_t::ptr_op_t python_module_t::lookup(const symbol_t::kind_t kind,
const string& name)
{
switch (kind) {
case symbol_t::FUNCTION:
DEBUG("python.interp", "Python lookup: " << name);
if (module_globals.has_key(name.c_str())) {
if (python::object obj = module_globals.get(name.c_str())) {
if (PyModule_Check(obj.ptr())) {
shared_ptr<python_module_t> mod;
python_module_map_t::iterator i =
python_session->modules_map.find(obj.ptr());
if (i == python_session->modules_map.end()) {
mod.reset(new python_module_t(name, obj));
python_session->modules_map.insert
(python_module_map_t::value_type(obj.ptr(), mod));
} else {
mod = (*i).second;
}
return expr_t::op_t::wrap_value(scope_value(mod.get()));
} else {
return WRAP_FUNCTOR(python_interpreter_t::functor_t(obj, name));
}
}
}
break;
default:
break;
}
return NULL;
}
expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
const string& name)
{
@ -408,28 +449,16 @@ expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
switch (kind) {
case symbol_t::FUNCTION:
if (option_t<python_interpreter_t> * handler = lookup_option(name.c_str()))
return MAKE_OPT_FUNCTOR(python_interpreter_t, handler);
if (is_initialized && main_nspace.has_key(name.c_str())) {
DEBUG("python.interp", "Python lookup: " << name);
if (python::object obj = main_nspace.get(name.c_str()))
return WRAP_FUNCTOR(functor_t(obj, name));
}
if (is_initialized)
return main_module->lookup(kind, name);
break;
case symbol_t::OPTION: {
if (option_t<python_interpreter_t> * handler = lookup_option(name.c_str()))
return MAKE_OPT_HANDLER(python_interpreter_t, handler);
string option_name(string("option_") + name);
if (is_initialized && main_nspace.has_key(option_name.c_str())) {
DEBUG("python.interp", "Python lookup option: " << option_name);
if (python::object obj = main_nspace.get(option_name.c_str()))
return WRAP_FUNCTOR(functor_t(obj, option_name));
}
if (is_initialized)
return main_module->lookup(symbol_t::FUNCTION, string("option_") + name);
break;
}

View file

@ -38,21 +38,52 @@
namespace ledger {
class python_module_t : public scope_t, public noncopyable
{
public:
string module_name;
python::object module_object;
python::dict module_globals;
explicit python_module_t(const string& name);
explicit python_module_t(const string& name, python::object obj);
void import_module(const string& name, bool import_direct = false);
virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
const string& name);
void define_global(const string& name, python::object obj) {
module_globals[name] = obj;
}
virtual string description() {
return module_name;
}
};
typedef std::map<PyObject *, shared_ptr<python_module_t> > python_module_map_t;
class python_interpreter_t : public session_t
{
public:
python::object main_module;
python::dict main_nspace;
bool is_initialized;
bool is_initialized;
python_interpreter_t()
: session_t(), main_nspace(), is_initialized(false) {
shared_ptr<python_module_t> main_module;
python_module_map_t modules_map;
shared_ptr<python_module_t> import_module(const string& name) {
shared_ptr<python_module_t> mod(new python_module_t(name));
if (name != "__main__")
main_module->define_global(name, mod->module_object);
return mod;
}
python_interpreter_t() : session_t(), is_initialized(false) {
TRACE_CTOR(python_interpreter_t, "");
}
virtual ~python_interpreter_t() {
TRACE_DTOR(python_interpreter_t);
if (is_initialized)
Py_Finalize();
}
@ -60,7 +91,6 @@ public:
void initialize();
void hack_system_paths();
python::object import_into_main(const string& name);
python::object import_option(const string& name);
enum py_eval_mode_t {
@ -69,14 +99,10 @@ public:
PY_EVAL_MULTI
};
python::object eval(std::istream& in,
py_eval_mode_t mode = PY_EVAL_EXPR);
python::object eval(const string& str,
py_eval_mode_t mode = PY_EVAL_EXPR);
python::object eval(const char * c_str,
py_eval_mode_t mode = PY_EVAL_EXPR) {
string str(c_str);
return eval(str, mode);
python::object eval(std::istream& in, py_eval_mode_t mode = PY_EVAL_EXPR);
python::object eval(const string& str, py_eval_mode_t mode = PY_EVAL_EXPR);
python::object eval(const char * c_str, py_eval_mode_t mode = PY_EVAL_EXPR) {
return eval(string(c_str), mode);
}
value_t python_command(call_scope_t& scope);

View file

@ -1156,8 +1156,8 @@ void instance_t::python_directive(char * line)
if (! python_session->is_initialized)
python_session->initialize();
python_session->main_nspace["journal"] =
python::object(python::ptr(context.journal));
python_session->main_module->define_global
("journal", python::object(python::ptr(context.journal)));
python_session->eval(script.str(), python_interpreter_t::PY_EVAL_MULTI);
}
#endif // HAVE_BOOST_PYTHON

View file

@ -1,10 +1,11 @@
python
import os
def check_path(path_value):
return os.path.isfile(path_value)
def check_path(path):
return os.path.isfile(path)
tag PATH
check check_path(value)
check os.path.isfile(value)
2012-02-29 KFC
; PATH: test/baseline/feat-import_py.test
@ -22,5 +23,6 @@ test reg
12-Feb-29 KFC Expenses:Food $20 $20
Assets:Cash $-20 0
__ERROR__
Warning: "$sourcepath/test/baseline/dir-python_py.test", line 17: Metadata check failed for (PATH: test/baseline/feat-import_noexist.test): check_path(value)
Warning: "$sourcepath/test/baseline/dir-python_py.test", line 18: Metadata check failed for (PATH: test/baseline/feat-import_noexist.test): check_path(value)
Warning: "$sourcepath/test/baseline/dir-python_py.test", line 18: Metadata check failed for (PATH: test/baseline/feat-import_noexist.test): ((os.path).isfile(value))
end test