This now works: ledger --import os eval 'os.path.isdir("/tmp")'
This commit is contained in:
parent
116cbd050b
commit
ddba59b703
4 changed files with 135 additions and 78 deletions
143
src/pyinterp.cc
143
src/pyinterp.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue