16#include <boost/python/call_method.hpp>
17#include <boost/python/exec.hpp>
18#include <boost/python/extract.hpp>
19#include <boost/python/import.hpp>
20#include <boost/python/to_python_value.hpp>
21#include <boost/regex.hpp>
27using namespace Kernel;
53 "An input workspace that the python code will modify."
54 "The workspace will be in the python variable named 'input'.");
57 "A File containing a python script");
60 "An output workspace to be produced by the python code."
61 "The workspace will be in the python variable named 'output'.");
65 std::map<std::string, std::string> out;
71 if ((!hasCode) && (!hasFile)) {
72 msg =
"Must specify python to execute";
77 out[
"Filename"] = msg;
88 setProperty<Workspace_sptr>(
"OutputWorkspace", outputWS);
109 if (userCode.empty() && (!filename.empty())) {
110 std::ifstream handle(filename.c_str(), std::ios_base::in);
111 if (!handle.is_open()) {
113 std::stringstream errss;
114 errss <<
"Unable to open file " << filename;
115 throw std::runtime_error(errss.str());
118 std::stringstream buffer;
119 buffer << handle.rdbuf();
120 userCode = buffer.str();
123 if (userCode.empty()) {
124 throw std::runtime_error(
"Python script is empty");
128 boost::regex eol(
"\\R");
129 userCode = boost::regex_replace(userCode, eol,
"\n");
132 std::istringstream is(userCode);
133 std::ostringstream os;
134 const char *indent =
" ";
135 os <<
"import mantid\n"
136 <<
"from mantid.simpleapi import *\n"
137 <<
"class _DUMMY_ALG(mantid.api.PythonAlgorithm):\n"
138 << indent <<
"def PyExec(self, input=None,output=None):\n";
140 while (getline(is, line)) {
141 os << indent << indent << line <<
"\n";
143 os << indent << indent <<
"return input,output\n";
145 os <<
"input,output = _DUMMY_ALG().PyExec(input,output)";
147 if (
g_log.
is(Kernel::Logger::Priority::PRIO_DEBUG))
148 g_log.
debug() <<
"Full code to be executed:\n" << os.str() <<
"\n";
183 auto main = boost::python::import(
"__main__");
185 boost::python::object globals(
main.attr(
"__dict__"));
188 boost::python::exec(script.c_str(), globals, locals);
189 }
catch (boost::python::error_already_set &) {
209 locals[
"input"] = object();
210 locals[
"output"] = object();
214 locals[
"input"] = object(handle<>(to_python_value<API::Workspace_sptr>()(inputWS)));
217 if (!outputWSName.empty()) {
218 locals[
"output"] = object(handle<>(to_python_value<const std::string &>()(outputWSName)));
234 auto pyoutput = locals.get(
"output");
239 if (ptrExtract.check()) {
242 extract<std::string> extractString(pyoutput);
243 if (extractString.check()) {
250 throw std::runtime_error(
"Invalid type assigned to 'output' variable. Must "
251 "be a string or a Workspace object");
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
A property class for workspaces.
void debug(const std::string &msg)
Logs at debug level.
bool is(int level) const
Returns true if at least the given log level is set.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Defines a structure for acquiring/releasing the Python GIL using the RAII pattern.
Exception type that captures the current Python error state as a generic C++ exception for any genera...
boost::python::dict doExecuteScript(const std::string &script) const
Execute the code in the given local context.
void exec() override
Execute the algorithm.
const std::string summary() const override
function returns a summary message that will be displayed in the default GUI, and in the help.
int version() const override
Algorithm's version for identification.
void init() override
Initialize the algorithm's properties.
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
std::shared_ptr< API::Workspace > executeScript(const std::string &script) const
Sets up the code context & executes it.
const std::string name() const override
Algorithm's name for identification.
std::shared_ptr< API::Workspace > extractOutputWorkspace(const boost::python::dict &locals) const
Extracts any output workspace pointer that was created.
std::string scriptCode() const
Return the code string to execute.
bool checkGroups() override
Override standard group behaviour so that the algorithm is only called once for the whole group.
boost::python::dict buildLocals() const
Builds the local dictionary that defines part of the execution context of the script.
const std::string category() const override
Algorithm's category for identification.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
bool isNone(PyObject *ptr)
@ Input
An input workspace.
@ Output
An output workspace.