generate pytask from string and string from pytask (#188)

* pytask creation from bytestring: saving work

* pytask now works

* documentation and tests

* linting

* Lint and fix test case
This commit is contained in:
Alexey Tumanov
2017-01-08 02:16:40 -08:00
committed by Philipp Moritz
parent c45342e39d
commit 674ec3a3cb
5 changed files with 78 additions and 10 deletions
+49
View File
@@ -68,6 +68,55 @@ PyObject *PyObjectID_make(object_id object_id) {
return (PyObject *) result;
}
/**
* Convert a string to a Ray task specification Python object.
*
* This is called from Python like
*
* task = photon.task_from_string("...")
*
* @param task_string String representation of the task specification.
* @return Python task specification object.
*/
PyObject *PyTask_from_string(PyObject *self, PyObject *args) {
const char *data;
int size;
if (!PyArg_ParseTuple(args, "s#", &data, &size)) {
return NULL;
}
PyTask *result = PyObject_New(PyTask, &PyTaskType);
result = (PyTask *) PyObject_Init((PyObject *) result, &PyTaskType);
result->spec = malloc(size);
memcpy(result->spec, data, size);
/* TODO(pcm): Better error checking once we use flatbuffers. */
if (size != task_spec_size(result->spec)) {
PyErr_SetString(CommonError,
"task_from_string: task specification string malformed");
return NULL;
}
return (PyObject *) result;
}
/**
* Convert a Ray task specification Python object to a string.
*
* This is called from Python like
*
* s = photon.task_to_string(task)
*
* @param task Ray task specification Python object.
* @return String representing the task specification.
*/
PyObject *PyTask_to_string(PyObject *self, PyObject *args) {
PyObject *arg;
if (!PyArg_ParseTuple(args, "O", &arg)) {
return NULL;
}
PyTask *task = (PyTask *) arg;
return PyBytes_FromStringAndSize((char *) task->spec,
task_spec_size(task->spec));
}
static PyObject *PyObjectID_id(PyObject *self) {
PyObjectID *s = (PyObjectID *) self;
return PyBytes_FromStringAndSize((char *) &s->object_id.id[0],
+3
View File
@@ -39,6 +39,9 @@ PyObject *PyObjectID_make(object_id object_id);
PyObject *check_simple_value(PyObject *self, PyObject *args);
PyObject *PyTask_to_string(PyObject *, PyObject *args);
PyObject *PyTask_from_string(PyObject *, PyObject *args);
PyObject *compute_put_id(PyObject *self, PyObject *args);
PyObject *PyTask_make(task_spec *task_spec);
+5
View File
@@ -7,6 +7,11 @@ static PyMethodDef common_methods[] = {
"Should the object be passed by value?"},
{"compute_put_id", compute_put_id, METH_VARARGS,
"Return the object ID for a put call within a task."},
{"task_from_string", PyTask_from_string, METH_VARARGS,
"Creates a Python PyTask object from a string representation of "
"task_spec."},
{"task_to_string", PyTask_to_string, METH_VARARGS,
"Translates a PyTask python object to a byte string."},
{NULL} /* Sentinel */
};
+16 -10
View File
@@ -112,7 +112,18 @@ class TestObjectID(unittest.TestCase):
class TestTask(unittest.TestCase):
def test_create_task(self):
def check_task(self, task, function_id, num_return_vals, args):
self.assertEqual(function_id.id(), task.function_id().id())
retrieved_args = task.arguments()
self.assertEqual(num_return_vals, len(task.returns()))
self.assertEqual(len(args), len(retrieved_args))
for i in range(len(retrieved_args)):
if isinstance(retrieved_args[i], common.ObjectID):
self.assertEqual(retrieved_args[i].id(), args[i].id())
else:
self.assertEqual(retrieved_args[i], args[i])
def test_create_and_serialize_task(self):
# TODO(rkn): The function ID should be a FunctionID object, not an ObjectID.
parent_id = random_task_id()
function_id = random_function_id()
@@ -146,15 +157,10 @@ class TestTask(unittest.TestCase):
for args in args_list:
for num_return_vals in [0, 1, 2, 3, 5, 10, 100]:
task = common.Task(function_id, args, num_return_vals, parent_id, 0)
self.assertEqual(function_id.id(), task.function_id().id())
retrieved_args = task.arguments()
self.assertEqual(num_return_vals, len(task.returns()))
self.assertEqual(len(args), len(retrieved_args))
for i in range(len(retrieved_args)):
if isinstance(retrieved_args[i], common.ObjectID):
self.assertEqual(retrieved_args[i].id(), args[i].id())
else:
self.assertEqual(retrieved_args[i], args[i])
self.check_task(task, function_id, num_return_vals, args)
data = common.task_to_string(task)
task2 = common.task_from_string(data)
self.check_task(task2, function_id, num_return_vals, args)
if __name__ == "__main__":
unittest.main(verbosity=2)
+5
View File
@@ -135,6 +135,11 @@ static PyMethodDef photon_methods[] = {
"Should the object be passed by value?"},
{"compute_put_id", compute_put_id, METH_VARARGS,
"Return the object ID for a put call within a task."},
{"task_from_string", PyTask_from_string, METH_VARARGS,
"Creates a Python PyTask object from a string representation of "
"task_spec."},
{"task_to_string", PyTask_to_string, METH_VARARGS,
"Translates a PyTask python object to a byte string."},
{NULL} /* Sentinel */
};