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 namespace py = boost::python;
27 py::object make_handler(F
f)
29 return py::make_function(
31 py::default_call_policies(),
32 boost::mpl::vector<std::string, const std::string&>()
37 py::object make_handler0(F f)
39 return py::make_function(
41 py::default_call_policies(),
42 boost::mpl::vector<std::string>()
47 py::object make_handler2(F f)
49 return py::make_function(
51 py::default_call_policies(),
52 boost::mpl::vector<std::string, const std::string&, const std::string&>()
56 static py::object toPython(
const std::string& value)
58 if(value ==
"true" || value ==
"True")
59 return py::object(
true);
61 if(value ==
"false" || value ==
"False")
62 return py::object(
false);
64 try {
return py::object(boost::lexical_cast<int>(value)); }
65 catch(boost::bad_lexical_cast&) {}
67 try {
return py::object(boost::lexical_cast<float>(value)); }
68 catch(boost::bad_lexical_cast&) {}
70 return py::object(value);
73 static py::object pythonArg(
const std::string& name, ParseContext& context)
80 std::string
evaluatePython(
const std::string& input, ParseContext& context)
88 py::object main_module = py::import(
"__main__");
89 py::dict global = py::dict(main_module.attr(
"__dict__"));
94 for(
auto&
arg : context.arguments())
96 local[
arg.first] = toPython(
arg.second);
102 local[
"anon"] = make_handler([&context](
const std::string& name){
105 local[
"arg"] = py::make_function([&context](
const std::string& name) -> py::object{
106 return pythonArg(name, context);
107 }, py::default_call_policies(), boost::mpl::vector<py::object, const std::string&>());
108 local[
"dirname"] = make_handler0([&context](){
119 py::object math = py::import(
"math");
120 py::object mathDict = math.attr(
"__dict__");
121 global.update(mathDict);
126 global[
"true"] = py::object(
true);
127 global[
"false"] = py::object(
false);
133 result = py::eval(input.c_str(), global, local);
135 catch(py::error_already_set&)
137 std::stringstream ss;
138 ss <<
"Caught Python exception while evaluating $(eval " << input <<
"):\n";
141 PyErr_Fetch(&e, &v, &t);
145 py::object t = py::extract<py::object>(e);
146 py::object t_name = t.attr(
"__name__");
147 std::string typestr = py::extract<std::string>(t_name);
149 ss << typestr <<
": ";
151 catch(py::error_already_set
const &)
156 py::object vo = py::extract<py::object>(v);
157 std::string valuestr = py::extract<std::string>(vo.attr(
"__str__")());
161 catch(py::error_already_set
const &)
163 ss <<
"<no str() handler>";
166 throw SubstitutionException(ss.str());
169 #if PY_MAJOR_VERSION >= 3 170 if(PyUnicode_Check(result.ptr()))
172 if(PyUnicode_READY(result.ptr()) != 0)
173 throw SubstitutionException(
"Could not read unicode object");
178 if(PyString_Check(result.ptr()))
179 return py::extract<std::string>(result);
182 if(PyBool_Check(result.ptr()))
184 if(py::extract<bool>(result))
190 #if PY_MAJOR_VERSION >= 3 191 if(PyLong_Check(result.ptr()))
192 return std::to_string(py::extract<int64_t>(result));
194 if(PyInt_Check(result.ptr()) || PyLong_Check(result.ptr()))
196 return std::to_string(py::extract<int64_t>(result));
200 if(PyFloat_Check(result.ptr()))
203 return boost::lexical_cast<std::string>(
204 py::extract<float>(result)()
216 g_initialized =
true;
219 py::object main_module = py::import(
"__main__");
220 py::dict global = py::dict(main_module.attr(
"__dict__"));
225 py::object math = py::import(
"math");
226 py::object mathDict = math.attr(
"__dict__");
227 global.update(mathDict);
233 result = py::eval(input.c_str(), global, local);
235 catch(py::error_already_set&)
237 std::stringstream ss;
238 ss <<
"Caught Python exception while evaluating rosparam expression '" << input <<
"'):\n";
241 PyErr_Fetch(&e, &v, &t);
245 py::object t = py::extract<py::object>(e);
246 py::object t_name = t.attr(
"__name__");
247 std::string typestr = py::extract<std::string>(t_name);
249 ss << typestr <<
": ";
251 catch(py::error_already_set
const &)
256 py::object vo = py::extract<py::object>(v);
257 std::string valuestr = py::extract<std::string>(vo.attr(
"__str__")());
261 catch(py::error_already_set
const &)
263 ss <<
"<no str() handler>";
266 throw SubstitutionException(ss.str());
271 return py::extract<double>(result);
273 catch(py::error_already_set)
284 "rosmon was built without python support, so I cannot parse $(eval ...) substitution args." 292 return boost::lexical_cast<
double>(input);
294 catch(boost::bad_lexical_cast)
297 "rosmon was built without python support, so I cannot parse complex rosparam expressions (expression: {})",
std::string anon(const std::string &name, ParseContext &context)
std::string evaluatePython(const std::string &input, ParseContext &context)
Evaluate a $(eval ...) python expression.
static SubstitutionException format(const char *format, const Args &...args)
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