Commit a83e98b7 authored by Michael Droettboom's avatar Michael Droettboom

Refactor python2js

parent 02e59bb2
...@@ -118,129 +118,161 @@ int ...@@ -118,129 +118,161 @@ int
_python2js_cache(PyObject* x, PyObject* map); _python2js_cache(PyObject* x, PyObject* map);
static int static int
_python2js(PyObject* x, PyObject* map) _python2js_float(PyObject* x)
{ {
if (x == Py_None) { double x_double = PyFloat_AsDouble(x);
return hiwire_undefined(); if (x_double == -1.0 && PyErr_Occurred()) {
} else if (x == Py_True) { return HW_ERROR;
return hiwire_true(); }
} else if (x == Py_False) { return hiwire_double(x_double);
return hiwire_false(); }
} else if (PyLong_Check(x)) {
int overflow; static int
long x_long = PyLong_AsLongAndOverflow(x, &overflow); _python2js_long(PyObject* x)
if (x_long == -1) { {
if (overflow) { int overflow;
PyObject* py_float = PyNumber_Float(x); long x_long = PyLong_AsLongAndOverflow(x, &overflow);
if (py_float == NULL) { if (x_long == -1) {
return HW_ERROR; if (overflow) {
} PyObject* py_float = PyNumber_Float(x);
double x_double = PyFloat_AsDouble(py_float); if (py_float == NULL) {
Py_DECREF(py_float);
if (x_double == -1.0 && PyErr_Occurred()) {
return HW_ERROR;
}
return hiwire_double(x_double);
} else if (PyErr_Occurred()) {
return HW_ERROR; return HW_ERROR;
} }
} return _python2js_float(py_float);
return hiwire_int(x_long); } else if (PyErr_Occurred()) {
} else if (PyFloat_Check(x)) {
double x_double = PyFloat_AsDouble(x);
if (x_double == -1.0 && PyErr_Occurred()) {
return HW_ERROR; return HW_ERROR;
} }
return hiwire_double(x_double); }
} else if (PyUnicode_Check(x)) { return hiwire_int(x_long);
int kind = PyUnicode_KIND(x); }
int data = (int)PyUnicode_DATA(x);
int length = (int)PyUnicode_GET_LENGTH(x); static int
switch (kind) { _python2js_unicode(PyObject* x)
case PyUnicode_1BYTE_KIND: {
return hiwire_string_ucs1(data, length); int kind = PyUnicode_KIND(x);
case PyUnicode_2BYTE_KIND: int data = (int)PyUnicode_DATA(x);
return hiwire_string_ucs2(data, length); int length = (int)PyUnicode_GET_LENGTH(x);
case PyUnicode_4BYTE_KIND: switch (kind) {
return hiwire_string_ucs4(data, length); case PyUnicode_1BYTE_KIND:
default: return hiwire_string_ucs1(data, length);
PyErr_SetString(PyExc_ValueError, "Unknown Unicode KIND"); case PyUnicode_2BYTE_KIND:
return HW_ERROR; return hiwire_string_ucs2(data, length);
} case PyUnicode_4BYTE_KIND:
} else if (PyBytes_Check(x)) { return hiwire_string_ucs4(data, length);
char* x_buff; default:
Py_ssize_t length; PyErr_SetString(PyExc_ValueError, "Unknown Unicode KIND");
if (PyBytes_AsStringAndSize(x, &x_buff, &length)) {
return HW_ERROR; return HW_ERROR;
} }
return hiwire_bytes((int)(void*)x_buff, length); }
} else if (JsProxy_Check(x)) {
return JsProxy_AsJs(x); static int
} else if (PyList_Check(x) || is_type_name(x, "<class 'numpy.ndarray'>")) { _python2js_bytes(PyObject* x)
int jsarray = hiwire_array(); {
if (_python2js_add_to_cache(map, x, jsarray)) { char* x_buff;
Py_ssize_t length;
if (PyBytes_AsStringAndSize(x, &x_buff, &length)) {
return HW_ERROR;
}
return hiwire_bytes((int)(void*)x_buff, length);
}
static int
_python2js_sequence(PyObject* x, PyObject* map)
{
int jsarray = hiwire_array();
if (_python2js_add_to_cache(map, x, jsarray)) {
hiwire_decref(jsarray);
return HW_ERROR;
}
size_t length = PySequence_Size(x);
for (size_t i = 0; i < length; ++i) {
PyObject* pyitem = PySequence_GetItem(x, i);
if (pyitem == NULL) {
// If something goes wrong converting the sequence (as is the case with
// Pandas data frames), fallback to the Python object proxy
_python2js_remove_from_cache(map, x);
hiwire_decref(jsarray); hiwire_decref(jsarray);
return HW_ERROR; PyErr_Clear();
Py_INCREF(x);
return pyproxy_new((int)x);
} }
size_t length = PySequence_Size(x); int jsitem = _python2js_cache(pyitem, map);
for (size_t i = 0; i < length; ++i) { if (jsitem == HW_ERROR) {
PyObject* pyitem = PySequence_GetItem(x, i); _python2js_remove_from_cache(map, x);
if (pyitem == NULL) {
// If something goes wrong converting the sequence (as is the case with
// Pandas data frames), fallback to the Python object proxy
_python2js_remove_from_cache(map, x);
hiwire_decref(jsarray);
PyErr_Clear();
Py_INCREF(x);
return pyproxy_new((int)x);
}
int jsitem = _python2js_cache(pyitem, map);
if (jsitem == HW_ERROR) {
_python2js_remove_from_cache(map, x);
Py_DECREF(pyitem);
hiwire_decref(jsarray);
return HW_ERROR;
}
Py_DECREF(pyitem); Py_DECREF(pyitem);
hiwire_push_array(jsarray, jsitem);
hiwire_decref(jsitem);
}
if (_python2js_remove_from_cache(map, x)) {
hiwire_decref(jsarray); hiwire_decref(jsarray);
return HW_ERROR; return HW_ERROR;
} }
return jsarray; Py_DECREF(pyitem);
} else if (PyDict_Check(x)) { hiwire_push_array(jsarray, jsitem);
int jsdict = hiwire_object(); hiwire_decref(jsitem);
if (_python2js_add_to_cache(map, x, jsdict)) { }
if (_python2js_remove_from_cache(map, x)) {
hiwire_decref(jsarray);
return HW_ERROR;
}
return jsarray;
}
static int
_python2js_dict(PyObject* x, PyObject* map)
{
int jsdict = hiwire_object();
if (_python2js_add_to_cache(map, x, jsdict)) {
hiwire_decref(jsdict);
return HW_ERROR;
}
PyObject *pykey, *pyval;
Py_ssize_t pos = 0;
while (PyDict_Next(x, &pos, &pykey, &pyval)) {
int jskey = _python2js_cache(pykey, map);
if (jskey == HW_ERROR) {
_python2js_remove_from_cache(map, x);
hiwire_decref(jsdict); hiwire_decref(jsdict);
return HW_ERROR; return HW_ERROR;
} }
PyObject *pykey, *pyval; int jsval = _python2js_cache(pyval, map);
Py_ssize_t pos = 0; if (jsval == HW_ERROR) {
while (PyDict_Next(x, &pos, &pykey, &pyval)) { _python2js_remove_from_cache(map, x);
int jskey = _python2js_cache(pykey, map);
if (jskey == HW_ERROR) {
_python2js_remove_from_cache(map, x);
hiwire_decref(jsdict);
return HW_ERROR;
}
int jsval = _python2js_cache(pyval, map);
if (jsval == HW_ERROR) {
_python2js_remove_from_cache(map, x);
hiwire_decref(jskey);
hiwire_decref(jsdict);
return HW_ERROR;
}
hiwire_push_object_pair(jsdict, jskey, jsval);
hiwire_decref(jskey); hiwire_decref(jskey);
hiwire_decref(jsval);
}
if (_python2js_remove_from_cache(map, x)) {
hiwire_decref(jsdict); hiwire_decref(jsdict);
return HW_ERROR; return HW_ERROR;
} }
return jsdict; hiwire_push_object_pair(jsdict, jskey, jsval);
hiwire_decref(jskey);
hiwire_decref(jsval);
}
if (_python2js_remove_from_cache(map, x)) {
hiwire_decref(jsdict);
return HW_ERROR;
}
return jsdict;
}
static int
_python2js(PyObject* x, PyObject* map)
{
if (x == Py_None) {
return hiwire_undefined();
} else if (x == Py_True) {
return hiwire_true();
} else if (x == Py_False) {
return hiwire_false();
} else if (PyLong_Check(x)) {
return _python2js_long(x);
} else if (PyFloat_Check(x)) {
return _python2js_float(x);
} else if (PyUnicode_Check(x)) {
return _python2js_unicode(x);
} else if (PyBytes_Check(x)) {
return _python2js_bytes(x);
} else if (JsProxy_Check(x)) {
return JsProxy_AsJs(x);
} else if (PyList_Check(x) || PyTuple_Check(x) ||
is_type_name(x, "<class 'numpy.ndarray'>")) {
return _python2js_sequence(x, map);
} else if (PyDict_Check(x)) {
return _python2js_dict(x, map);
} else { } else {
Py_INCREF(x); Py_INCREF(x);
return pyproxy_new((int)x); return pyproxy_new((int)x);
...@@ -265,25 +297,21 @@ _python2js_add_to_cache(PyObject* map, PyObject* pyparent, int jsparent) ...@@ -265,25 +297,21 @@ _python2js_add_to_cache(PyObject* map, PyObject* pyparent, int jsparent)
/* Use the pointer converted to an int so cache is by identity, not hash */ /* Use the pointer converted to an int so cache is by identity, not hash */
PyObject* pyparentid = PyLong_FromSize_t((size_t)pyparent); PyObject* pyparentid = PyLong_FromSize_t((size_t)pyparent);
PyObject* jsparentid = PyLong_FromLong(jsparent); PyObject* jsparentid = PyLong_FromLong(jsparent);
if (PyDict_SetItem(map, pyparentid, jsparentid)) { int result = PyDict_SetItem(map, pyparentid, jsparentid);
Py_DECREF(pyparentid);
Py_DECREF(jsparentid);
return HW_ERROR;
}
Py_DECREF(pyparentid); Py_DECREF(pyparentid);
Py_DECREF(jsparentid); Py_DECREF(jsparentid);
return 0;
return result ? HW_ERROR : 0;
} }
int int
_python2js_remove_from_cache(PyObject* map, PyObject* pyparent) _python2js_remove_from_cache(PyObject* map, PyObject* pyparent)
{ {
PyObject* pyparentid = PyLong_FromSize_t((size_t)pyparent); PyObject* pyparentid = PyLong_FromSize_t((size_t)pyparent);
if (PyDict_DelItem(map, pyparentid)) { int result = PyDict_DelItem(map, pyparentid);
return HW_ERROR;
}
Py_DECREF(pyparentid); Py_DECREF(pyparentid);
return 0;
return result ? HW_ERROR : 0;
} }
int int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment