9 #include <boost/python/exec.hpp> 10 #include <boost/python/extract.hpp> 11 #include <boost/python/dict.hpp> 12 #include <boost/python/make_function.hpp> 13 #include <boost/python/import.hpp> 15 #include <boost/lexical_cast.hpp> 17 #include <boost/mpl/vector.hpp> 19 namespace py = boost::python;
29 py::object make_handler(F
f)
31 return py::make_function(
33 py::default_call_policies(),
34 boost::mpl::vector<std::string, const std::string&>()
39 py::object make_handler0(F f)
41 return py::make_function(
43 py::default_call_policies(),
44 boost::mpl::vector<std::string>()
49 py::object make_handler2(F f)
51 return py::make_function(
53 py::default_call_policies(),
54 boost::mpl::vector<std::string, const std::string&, const std::string&>()
58 static py::object toPython(
const std::string& value)
60 if(value ==
"true" || value ==
"True")
61 return py::object(
true);
63 if(value ==
"false" || value ==
"False")
64 return py::object(
false);
66 try {
return py::object(boost::lexical_cast<int>(value)); }
67 catch(boost::bad_lexical_cast&) {}
69 try {
return py::object(boost::lexical_cast<float>(value)); }
70 catch(boost::bad_lexical_cast&) {}
72 return py::object(value);
75 static py::object pythonArg(
const std::string& name, ParseContext& context)
82 std::string
evaluatePython(
const std::string& input, ParseContext& context)
90 py::object main_module = py::import(
"__main__");
91 py::dict global = py::dict(main_module.attr(
"__dict__"));
96 for(
auto&
arg : context.arguments())
98 local[
arg.first] = toPython(
arg.second);
104 local[
"anon"] = make_handler([&context](
const std::string& name){
107 local[
"arg"] = py::make_function([&context](
const std::string& name) -> py::object{
108 return pythonArg(name, context);
109 }, py::default_call_policies(), boost::mpl::vector<py::object, const std::string&>());
110 local[
"dirname"] = make_handler0([&context](){
121 py::object math = py::import(
"math");
122 py::object mathDict = math.attr(
"__dict__");
123 global.update(mathDict);
128 global[
"true"] = py::object(
true);
129 global[
"false"] = py::object(
false);
135 result = py::eval(input.c_str(), global, local);
137 catch(py::error_already_set&)
139 std::stringstream ss;
140 ss <<
"Caught Python exception while evaluating $(eval " << input <<
"):\n";
143 PyErr_Fetch(&e, &v, &t);
147 py::object t = py::extract<py::object>(e);
148 py::object t_name = t.attr(
"__name__");
149 std::string typestr = py::extract<std::string>(t_name);
151 ss << typestr <<
": ";
153 catch(py::error_already_set
const &)
158 py::object vo = py::extract<py::object>(v);
159 std::string valuestr = py::extract<std::string>(vo.attr(
"__str__")());
163 catch(py::error_already_set
const &)
165 ss <<
"<no str() handler>";
168 throw SubstitutionException(ss.str());
171 #if PY_MAJOR_VERSION >= 3 172 if(PyUnicode_Check(result.ptr()))
174 if(PyUnicode_READY(result.ptr()) != 0)
175 throw SubstitutionException(
"Could not read unicode object");
180 if(PyString_Check(result.ptr()))
181 return py::extract<std::string>(result);
184 if(PyBool_Check(result.ptr()))
186 if(py::extract<bool>(result))
192 #if PY_MAJOR_VERSION >= 3 193 if(PyLong_Check(result.ptr()))
194 return std::to_string(py::extract<int64_t>(result));
196 if(PyInt_Check(result.ptr()) || PyLong_Check(result.ptr()))
198 return std::to_string(py::extract<int64_t>(result));
202 if(PyFloat_Check(result.ptr()))
205 return boost::lexical_cast<std::string>(
206 py::extract<float>(result)()
218 g_initialized =
true;
221 py::object main_module = py::import(
"__main__");
222 py::dict global = py::dict(main_module.attr(
"__dict__"));
227 py::object math = py::import(
"math");
228 py::object mathDict = math.attr(
"__dict__");
229 global.update(mathDict);
235 result = py::eval(input.c_str(), global, local);
237 catch(py::error_already_set&)
239 std::stringstream ss;
240 ss <<
"Caught Python exception while evaluating rosparam expression '" << input <<
"'):\n";
243 PyErr_Fetch(&e, &v, &t);
247 py::object t = py::extract<py::object>(e);
248 py::object t_name = t.attr(
"__name__");
249 std::string typestr = py::extract<std::string>(t_name);
251 ss << typestr <<
": ";
253 catch(py::error_already_set
const &)
258 py::object vo = py::extract<py::object>(v);
259 std::string valuestr = py::extract<std::string>(vo.attr(
"__str__")());
263 catch(py::error_already_set
const &)
265 ss <<
"<no str() handler>";
268 throw SubstitutionException(ss.str());
273 return py::extract<double>(result);
275 catch(py::error_already_set&)
286 "rosmon was built without python support, so I cannot parse $(eval ...) substitution args." 294 return boost::lexical_cast<
double>(input);
296 catch(boost::bad_lexical_cast)
299 "rosmon was built without python support, so I cannot parse complex rosparam expressions (expression: {})",
std::string anon(const std::string &name, ParseContext &context)
static SubstitutionException format(const char *format, const Args &... args)
std::string evaluatePython(const std::string &input, ParseContext &context)
Evaluate a $(eval ...) python expression.
double evaluateROSParamPython(const std::string &input)
Evaluate a deg(...) rosparam expression.
static bool g_initialized
std::string dirname(const ParseContext &context)
std::string optenv(const std::string &name, const std::string &defaultValue)
std::string env(const std::string &name)
std::string arg(const std::string &name, const ParseContext &context)
std::string find_stupid(const std::string &name)
$(find ...) which always gives rospack find results