Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shell commands and function callbacks #1193

Merged
merged 6 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/libs/ascent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ set(ascent_headers
runtimes/flow_filters/ascent_runtime_htg_filters.hpp
runtimes/flow_filters/ascent_runtime_trigger_filters.hpp
runtimes/flow_filters/ascent_runtime_query_filters.hpp
runtimes/flow_filters/ascent_runtime_command_filters.hpp
runtimes/flow_filters/ascent_runtime_vtkh_utils.hpp
runtimes/flow_filters/ascent_runtime_utils.hpp
# utils
Expand Down Expand Up @@ -228,6 +229,7 @@ set(ascent_sources
runtimes/flow_filters/ascent_runtime_htg_filters.cpp
runtimes/flow_filters/ascent_runtime_trigger_filters.cpp
runtimes/flow_filters/ascent_runtime_query_filters.cpp
runtimes/flow_filters/ascent_runtime_command_filters.cpp
runtimes/flow_filters/ascent_runtime_utils.cpp
# utils
utils/ascent_actions_utils.cpp
Expand Down
73 changes: 73 additions & 0 deletions src/libs/ascent/ascent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,79 @@ about(conduit::Node &n)

}

//-----------------------------------------------------------------------------
void
register_callback(const std::string &callback_name,
void (*callback_function)(conduit::Node &, conduit::Node &))
{
if (callback_name == "")
{
ASCENT_ERROR("cannot register an anonymous void callback");
}
else if (m_void_callback_map.count(callback_name) != 0)
{
ASCENT_ERROR("cannot register more than one void callback under the name '" << callback_name << "'");
}
else if (m_bool_callback_map.count(callback_name) != 0)
{
ASCENT_ERROR("cannot register both a void and bool callback under the same name '" << callback_name << "'");
}
m_void_callback_map.insert(std::make_pair(callback_name, callback_function));
}

//-----------------------------------------------------------------------------
void
register_callback(const std::string &callback_name,
bool (*callback_function)(void))
{
if (callback_name == "")
{
ASCENT_ERROR("cannot register an anonymous bool callback");
}
else if (m_bool_callback_map.count(callback_name) != 0)
{
ASCENT_ERROR("cannot register more than one bool callback under the name '" << callback_name << "'");
}
else if (m_void_callback_map.count(callback_name) != 0)
{
ASCENT_ERROR("cannot register both a void and bool callback under the same name '" << callback_name << "'");
}
m_bool_callback_map.insert(std::make_pair(callback_name, callback_function));
}

//-----------------------------------------------------------------------------
void
execute_callback(std::string callback_name,
conduit::Node &params,
conduit::Node &output)
{
if (m_void_callback_map.count(callback_name) != 1)
{
ASCENT_ERROR("requested void callback '" << callback_name << "' was never registered");
}
auto callback_function = m_void_callback_map.at(callback_name);
return callback_function(params, output);
}

//-----------------------------------------------------------------------------
bool
execute_callback(std::string callback_name)
{
if (m_bool_callback_map.count(callback_name) != 1)
{
ASCENT_ERROR("requested bool callback '" << callback_name << "' was never registered");
}
auto callback_function = m_bool_callback_map.at(callback_name);
return callback_function();
}

//-----------------------------------------------------------------------------
void
reset_callbacks()
{
m_void_callback_map.clear();
m_bool_callback_map.clear();
}

//-----------------------------------------------------------------------------
// -- end ascent:: --
Expand Down
21 changes: 21 additions & 0 deletions src/libs/ascent/ascent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,34 @@ class ASCENT_API Ascent
conduit::Node m_info;
};

// Callback maps
static std::map<std::string, void (*)(conduit::Node &, conduit::Node &)> m_void_callback_map;
static std::map<std::string, bool (*)(void)> m_bool_callback_map;
siramok marked this conversation as resolved.
Show resolved Hide resolved

//-----------------------------------------------------------------------------
std::string ASCENT_API about();

//-----------------------------------------------------------------------------
void ASCENT_API about(conduit::Node &node);

//-----------------------------------------------------------------------------
void ASCENT_API register_callback(const std::string &callback_name,
void (*callback_function)(conduit::Node &, conduit::Node &));
//-----------------------------------------------------------------------------
void ASCENT_API register_callback(const std::string &callback_name,
bool (*callback_function)(void));

//-----------------------------------------------------------------------------
void ASCENT_API execute_callback(std::string callback_name,
conduit::Node &params,
conduit::Node &output);

//-----------------------------------------------------------------------------
bool ASCENT_API execute_callback(std::string callback_name);

//-----------------------------------------------------------------------------
void ASCENT_API reset_callbacks();

};
//-----------------------------------------------------------------------------
// -- end ascent:: --
Expand Down
94 changes: 94 additions & 0 deletions src/libs/ascent/python/ascent_module/ascent_mpi_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,29 @@ struct PyAscent_MPI_Ascent
Ascent *ascent; // NoteIterator is light weight, we can deal with copies
};

//---------------------------------------------------------------------------//
// Helper that promotes ascent error to python error
//---------------------------------------------------------------------------//
static void
PyAscent_MPI_Ascent_Error_To_PyErr(const conduit::Error &e)
{
std::ostringstream oss;
oss << "Ascent Error: " << e.message();
PyErr_SetString(PyExc_RuntimeError,
oss.str().c_str());
}

//---------------------------------------------------------------------------//
// Helper that promotes ascent error to python error
//---------------------------------------------------------------------------//
static void
PyAscent_MPI_Cpp_Error_To_PyErr(const char *msg)
{
std::ostringstream oss;
oss << "Ascent Error: " << msg;
PyErr_SetString(PyExc_RuntimeError,
oss.str().c_str());
}

//---------------------------------------------------------------------------//
static PyObject *
Expand Down Expand Up @@ -465,6 +488,72 @@ PyAscent_MPI_about()
return (PyObject*)py_node_res;
}

//---------------------------------------------------------------------------//
// ascent::execute_callback
//---------------------------------------------------------------------------//
static PyObject *
PyAscent_MPI_execute_callback(PyObject *self,
PyObject *args)
{
char *callback_name;
PyObject *py_params = NULL;
PyObject *py_output = NULL;

if (!PyArg_ParseTuple(args,
"sOO",
&callback_name,
&py_params,
&py_output))
{
return NULL;
}

try
{
if(py_params != NULL && py_output != NULL)
{
if(!PyConduit_Node_Check(py_params))
{
PyErr_SetString(PyExc_TypeError,
"Ascent::execute_callback 'params' argument must be a "
"conduit::Node");
return NULL;
}
else if (!PyConduit_Node_Check(py_output))
{
PyErr_SetString(PyExc_TypeError,
"Ascent::execute_callback 'output' argument must be a "
"conduit::Node");
return NULL;
}
std::string callback_name_string = callback_name;
Node *params = PyConduit_Node_Get_Node_Ptr(py_params);
Node *output = PyConduit_Node_Get_Node_Ptr(py_output);
ascent::execute_callback(callback_name, *params, *output);
Py_RETURN_NONE;
}
}
catch(conduit::Error e)
{
PyAscent_MPI_Ascent_Error_To_PyErr(e);
return NULL;
}
// also try to bottle other errors, to prevent python
// from crashing due to uncaught exception
catch(std::exception &e)
{
PyAscent_MPI_Cpp_Error_To_PyErr(e.what());
return NULL;
}
catch(...)
{
PyAscent_MPI_Cpp_Error_To_PyErr("unknown cpp exception thrown");
return NULL;
}

Py_RETURN_NONE;
}

//---------------------------------------------------------------------------//
// Python Module Method Defs
//---------------------------------------------------------------------------//
Expand All @@ -476,6 +565,11 @@ static PyMethodDef ascent_mpi_python_funcs[] =
METH_NOARGS,
NULL},
//-----------------------------------------------------------------------//
{"execute_callback",
(PyCFunction)PyAscent_MPI_execute_callback,
METH_VARARGS,
NULL},
//-----------------------------------------------------------------------//
// end ascent methods table
//-----------------------------------------------------------------------//
{NULL, NULL, METH_VARARGS, NULL}
Expand Down
73 changes: 72 additions & 1 deletion src/libs/ascent/python/ascent_module/ascent_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ static PyMethodDef PyAscent_Ascent_METHODS[] = {
METH_VARARGS | METH_KEYWORDS,
"{todo}"},
//-----------------------------------------------------------------------//
{"execute",
{"execute",
(PyCFunction)PyAscent_Ascent_execute,
METH_VARARGS | METH_KEYWORDS,
"{todo}"},
Expand Down Expand Up @@ -596,6 +596,72 @@ PyAscent_about()
return (PyObject*)py_node_res;
}

//---------------------------------------------------------------------------//
// ascent::execute_callback
//---------------------------------------------------------------------------//
static PyObject *
PyAscent_execute_callback(PyObject *self,
PyObject *args)
{
char *callback_name;
PyObject *py_params = NULL;
PyObject *py_output = NULL;

if (!PyArg_ParseTuple(args,
"sOO",
&callback_name,
&py_params,
&py_output))
{
return NULL;
}

try
{
if(py_params != NULL && py_output != NULL)
{
if(!PyConduit_Node_Check(py_params))
{
PyErr_SetString(PyExc_TypeError,
"Ascent::execute_callback 'params' argument must be a "
"conduit::Node");
return NULL;
}
else if (!PyConduit_Node_Check(py_output))
{
PyErr_SetString(PyExc_TypeError,
"Ascent::execute_callback 'output' argument must be a "
"conduit::Node");
return NULL;
}
std::string callback_name_string = callback_name;
Node *params = PyConduit_Node_Get_Node_Ptr(py_params);
Node *output = PyConduit_Node_Get_Node_Ptr(py_output);
ascent::execute_callback(callback_name, *params, *output);
Py_RETURN_NONE;
}
}
catch(conduit::Error e)
{
PyAscent_Ascent_Error_To_PyErr(e);
return NULL;
}
// also try to bottle other errors, to prevent python
// from crashing due to uncaught exception
catch(std::exception &e)
{
PyAscent_Cpp_Error_To_PyErr(e.what());
return NULL;
}
catch(...)
{
PyAscent_Cpp_Error_To_PyErr("unknown cpp exception thrown");
return NULL;
}

Py_RETURN_NONE;
}

//---------------------------------------------------------------------------//
// Python Module Method Defs
//---------------------------------------------------------------------------//
Expand All @@ -607,6 +673,11 @@ static PyMethodDef ascent_python_funcs[] =
METH_NOARGS,
NULL},
//-----------------------------------------------------------------------//
{"execute_callback",
(PyCFunction)PyAscent_execute_callback,
METH_VARARGS,
NULL},
//-----------------------------------------------------------------------//
// end ascent methods table
//-----------------------------------------------------------------------//
{NULL, NULL, METH_VARARGS, NULL}
Expand Down
8 changes: 8 additions & 0 deletions src/libs/ascent/python/ascent_module/py_src/ascent.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ def about():
raise ImportError('failed to import ascent_python, was Ascent built with serial support ENABLE_SERIAL=ON ?')
return None

def execute_callback(callback_name, params, output):
try:
from .ascent_python import execute_callback as ascent_execute_callback
return ascent_execute_callback(callback_name, params, output)
except ImportError:
raise ImportError('failed to import ascent_python, was Ascent built with serial support ENABLE_SERIAL=ON ?')
return None

def Ascent():
try:
from .ascent_python import Ascent as ascent_obj
Expand Down
7 changes: 7 additions & 0 deletions src/libs/ascent/python/ascent_module/py_src/mpi/ascent_mpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ def about():
raise ImportError('failed to import ascent_mpi_python, was Ascent built with mpi support?')
return None

def execute_callback(callback_name, params, output):
try:
from .ascent_mpi_python import execute_callback as ascent_execute_callback
return ascent_execute_callback(callback_name, params, output)
except ImportError:
raise ImportError('failed to import ascent_mpi_python, was Ascent built with serial support ENABLE_SERIAL=ON ?')
siramok marked this conversation as resolved.
Show resolved Hide resolved
return None

def Ascent():
try:
Expand Down
1 change: 0 additions & 1 deletion src/libs/ascent/runtimes/ascent_empty_runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ EmptyRuntime::Info()
return m_info;
}


//-----------------------------------------------------------------------------
void
EmptyRuntime::Cleanup()
Expand Down
2 changes: 1 addition & 1 deletion src/libs/ascent/runtimes/ascent_flow_runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,11 @@ FlowRuntime::Info()
return m_info;
}


//-----------------------------------------------------------------------------
void
FlowRuntime::Cleanup()
{

}

//-----------------------------------------------------------------------------
Expand Down
Loading