Exemplo n.º 1
0
static int
Command_setattr(twopence_Command *self, char *name, PyObject *v)
{
	if (!strcmp(name, "stdout")) {
		if (v != Py_None && !PyByteArray_Check(v))
			goto bad_attr;
		assign_object(&self->stdout, v);
		return 0;
	}
	if (!strcmp(name, "stderr")) {
		if (v != Py_None && !PyByteArray_Check(v))
			goto bad_attr;
		assign_object(&self->stderr, v);
		return 0;
	}
	if (!strcmp(name, "user")) {
		char *s;

		if (!PyString_Check(v) || (s = PyString_AsString(v)) == NULL)
			goto bad_attr;
		assign_string(&self->user, s);
		return 0;
	}
	if (!strcmp(name, "timeout")) {
		if (PyInt_Check(v))
			self->timeout = PyInt_AsLong(v);
		else if (PyLong_Check(v))
			self->timeout = PyLong_AsLongLong(v);
		else
			goto bad_attr;
		return 0;
	}
	if (!strcmp(name, "quiet")) {
		self->quiet = !!(PyObject_IsTrue(v));
		return 0;
	}
	if (!strcmp(name, "useTty")) {
		self->useTty = !!(PyObject_IsTrue(v));
		return 0;
	}
	if (!strcmp(name, "background")) {
		self->background = !!(PyObject_IsTrue(v));
		return 0;
	}

	(void) PyErr_Format(PyExc_AttributeError, "Unknown attribute: %s", name);
	return -1;

bad_attr:
	(void) PyErr_Format(PyExc_AttributeError, "Incompatible value for attribute: %s", name);
	return -1;

}
Exemplo n.º 2
0
/* Convert a Python string (including Unicode in Py2 and Bytes in Py3) to a QString */
QString PyString_AsQString(PyObject *pystr)
{
    // Unicode
    if (PyUnicode_Check(pystr))
    {
#if PY_MAJOR_VERSION >= 3
        QString s = QString::fromUtf8(PyUnicode_AsUTF8(pystr));
#else
        PyObject *utf8str = PyUnicode_AsUTF8String(pystr);
        QString s = QString::fromUtf8(PyString_AsString(utf8str));
        Py_DecRef(utf8str);
#endif
        return s;
    }

    // Bytes
#if PY_MAJOR_VERSION >= 3
    else if (PyByteArray_Check(pystr))
        return QString::fromUtf8(PyByteArray_AsString(pystr));
#else
    else if (PyString_Check(pystr))
        return QString::fromUtf8(PyString_AsString(pystr));
#endif
    else
        return QString();
}
Exemplo n.º 3
0
static long __Pyx__PyObject_Ord(PyObject* c) {
    Py_ssize_t size;
    if (PyBytes_Check(c)) {
        size = PyBytes_GET_SIZE(c);
        if (likely(size == 1)) {
            return (unsigned char) PyBytes_AS_STRING(c)[0];
        }
#if PY_MAJOR_VERSION < 3
    } else if (PyUnicode_Check(c)) {
        return (long)__Pyx_PyUnicode_AsPy_UCS4(c);
#endif
#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE))
    } else if (PyByteArray_Check(c)) {
        size = PyByteArray_GET_SIZE(c);
        if (likely(size == 1)) {
            return (unsigned char) PyByteArray_AS_STRING(c)[0];
        }
#endif
    } else {
        // FIXME: support character buffers - but CPython doesn't support them either
        PyErr_Format(PyExc_TypeError,
            "ord() expected string of length 1, but %.200s found", c->ob_type->tp_name);
        return (long)(Py_UCS4)-1;
    }
    PyErr_Format(PyExc_TypeError,
        "ord() expected a character, but string of length %zd found", size);
    return (long)(Py_UCS4)-1;
}
Exemplo n.º 4
0
static ssize_t python_pread(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n, off_t offset)
{
	struct pyfuncs *pf = handle->data;
	PyObject *pArgs, *pRet, *pValue;
	char *pydata;
	ssize_t s;

	if (!pf->pFuncPRead) {
		off_t original_pos;
		/*
		 * Simulate pread with lseek and read (like the default implementation
		 * does.
		 */
		if ((original_pos = python_lseek(handle, fsp, 0, SEEK_CUR)) == -1) return -1;
		if (python_lseek(handle, fsp, offset, SEEK_SET) == -1) return -1;
		s = python_vfs_read(handle, fsp, data, n);
		if (python_lseek(handle, fsp, original_pos, SEEK_SET) == -1) return -1;
		return s;
	}

	PY_TUPLE_NEW(3);
	PY_ADD_TO_TUPLE(fsp->fh->fd, PyInt_FromSsize_t, 0);
	PY_ADD_TO_TUPLE(n, PyInt_FromSize_t, 1);
	PY_ADD_TO_TUPLE(offset, PyInt_FromSize_t, 2);
	PY_CALL_WITH_ARGS(PRead);

	if (PyString_Check(pRet)) {
		pydata = PyString_AsString(pRet);
		if (pydata == NULL) {
			Py_DECREF(pRet);
			errno = E_INTERNAL;
			return -1;
		}
		s = PyString_Size(pRet);

	} else if (PyByteArray_Check(pRet)) {
		pydata = PyByteArray_AsString(pRet);
		if (pydata == NULL) {
			Py_DECREF(pRet);
			errno = E_INTERNAL;
			return -1;
		}
		s = PyByteArray_Size(pRet);

	} else {
		errno = PyInt_AsLong(pRet);
		Py_DECREF(pRet);
		return -1;
	}

	memcpy(data, pydata, s > n ? n : s);

	Py_DECREF(pRet);
	return s;
}
Exemplo n.º 5
0
static int
Transfer_setattr(twopence_Transfer *self, char *name, PyObject *v)
{
	if (!strcmp(name, "remotefile")) {
		char *s;

		if (!PyString_Check(v) || (s = PyString_AsString(v)) == NULL)
			goto bad_attr;
		assign_string(&self->remote_filename, s);
		return 0;
	}
	if (!strcmp(name, "localfile")) {
		char *s;

		if (!PyString_Check(v) || (s = PyString_AsString(v)) == NULL)
			goto bad_attr;
		assign_string(&self->local_filename, s);
		return 0;
	}
	if (!strcmp(name, "user")) {
		char *s;

		if (!PyString_Check(v) || (s = PyString_AsString(v)) == NULL)
			goto bad_attr;
		assign_string(&self->user, s);
		return 0;
	}
	if (!strcmp(name, "permissions")) {
		if (!PyInt_Check(v))
			goto bad_attr;
		self->permissions = PyInt_AsLong(v);
		return 0;
	}
	if (!strcmp(name, "timeout")) {
		if (!PyInt_Check(v))
			goto bad_attr;
		self->timeout = PyInt_AsLong(v);
		return 0;
	}
	if (!strcmp(name, "data")) {
		if (v != Py_None && !PyByteArray_Check(v))
			goto bad_attr;
		assign_object(&self->buffer, v);
		return 0;
	}

	(void) PyErr_Format(PyExc_AttributeError, "Unknown attribute: %s", name);
	return -1;

bad_attr:
	(void) PyErr_Format(PyExc_AttributeError, "Incompatible value for attribute: %s", name);
	return -1;

}
Exemplo n.º 6
0
char *get_bytes_or_bytearray_str(bp::object buf)
{
    PyObject *py_ba;
    py_ba = buf.ptr();
    if (PyByteArray_Check(py_ba))
        return PyByteArray_AsString(py_ba);
    else if (PyBytes_Check(py_ba))
        return PyBytes_AsString(py_ba);
    else
        throw_ba_exception();
    return NULL;
}
Exemplo n.º 7
0
int get_bytes_or_bytearray_ln(bp::object buf)
{
    PyObject *py_ba;
    py_ba = buf.ptr();
    if (PyByteArray_Check(py_ba))
        return PyByteArray_Size(py_ba);
    else if (PyBytes_Check(py_ba))
        return PyBytes_Size(py_ba);
    else
        throw_ba_exception();
    return 0;
}
Exemplo n.º 8
0
/**
 *******************************************************************************************************
 * This function will check whether operation can be performed
 * based on operation and value type.
 *
 * @param py_value              The value to perform operations.
 * @param op                    The operation to perform.
 *
 * Returns 0 if operation can be performed.
 *******************************************************************************************************
 */
int check_type(AerospikeClient * self, PyObject * py_value, int op, as_error *err)
{
	if ((!PyInt_Check(py_value) && !PyLong_Check(py_value) && strcmp(py_value->ob_type->tp_name, "aerospike.null")) && (op == AS_OPERATOR_TOUCH)) {
	    as_error_update(err, AEROSPIKE_ERR_PARAM, "Unsupported operand type(s) for touch : only int or long allowed");
		return 1;
	} else if ( (!PyInt_Check(py_value) && !PyLong_Check(py_value) && (!PyFloat_Check(py_value) || !aerospike_has_double(self->as)) && 
				strcmp(py_value->ob_type->tp_name, "aerospike.null")) && op == AS_OPERATOR_INCR){
	    as_error_update(err, AEROSPIKE_ERR_PARAM, "Unsupported operand type(s) for +: only 'int' allowed");
		return 1;
	} else if ((!PyString_Check(py_value) && !PyUnicode_Check(py_value) && !PyByteArray_Check(py_value) && strcmp(py_value->ob_type->tp_name, "aerospike.null")) && (op == AS_OPERATOR_APPEND || op == AS_OPERATOR_PREPEND)) {
	    as_error_update(err, AEROSPIKE_ERR_PARAM, "Cannot concatenate 'str' and 'non-str' objects");
		return 1;
	}
	return 0;
}
Exemplo n.º 9
0
// from Python/bltinmodule.c
static const char *
source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, PyObject **cmd_copy)
{
    const char *str;
    Py_ssize_t size;
    Py_buffer view;

    *cmd_copy = NULL;
    if (PyUnicode_Check(cmd)) {
        cf->cf_flags |= PyCF_IGNORE_COOKIE;
        str = PyUnicode_AsUTF8AndSize(cmd, &size);
        if (str == NULL)
            return NULL;
    }
    else if (PyBytes_Check(cmd)) {
        str = PyBytes_AS_STRING(cmd);
        size = PyBytes_GET_SIZE(cmd);
    }
    else if (PyByteArray_Check(cmd)) {
        str = PyByteArray_AS_STRING(cmd);
        size = PyByteArray_GET_SIZE(cmd);
    }
    else if (PyObject_GetBuffer(cmd, &view, PyBUF_SIMPLE) == 0) {
        /* Copy to NUL-terminated buffer. */
        *cmd_copy = PyBytes_FromStringAndSize(
            (const char *)view.buf, view.len);
        PyBuffer_Release(&view);
        if (*cmd_copy == NULL) {
            return NULL;
        }
        str = PyBytes_AS_STRING(*cmd_copy);
        size = PyBytes_GET_SIZE(*cmd_copy);
    }
    else {
        PyErr_Format(PyExc_TypeError,
          "%s() arg 1 must be a %s object",
          funcname, what);
        return NULL;
    }

    if (strlen(str) != (size_t)size) {
        PyErr_SetString(PyExc_ValueError,
                        "source code string cannot contain null bytes");
        Py_CLEAR(*cmd_copy);
        return NULL;
    }
    return str;
}
Exemplo n.º 10
0
// Helper for Map.__init__(), Map.set()
static int bad_mapbytes(PyObject * py_mapbytes, int size_pixels, const char * methodname)
{    
    if (!PyByteArray_Check(py_mapbytes))
    {
        return error_on_raise_argument_exception_with_details("Map", methodname, 
            "argument is not a byte array");        
    }
    
    if (PyByteArray_GET_SIZE(py_mapbytes) != (size_pixels * size_pixels))
    {        
        return error_on_raise_argument_exception_with_details("Map", methodname, 
            "mapbytes are wrong size");
    }

    return 0;
}
Exemplo n.º 11
0
static bool
Command_redirect_iostream(twopence_command_t *cmd, twopence_iofd_t dst, PyObject *object, twopence_buf_t **buf_ret)
{
	if (object == NULL || PyByteArray_Check(object)) {
		twopence_buf_t *buffer;

		if (dst == TWOPENCE_STDIN && object == NULL)
			return true;

		/* Capture command output in a buffer */
		buffer = twopence_command_alloc_buffer(cmd, dst, 65536);
		twopence_command_ostream_capture(cmd, dst, buffer);
		if (dst == TWOPENCE_STDIN) {
			unsigned int count = PyByteArray_Size(object);

			twopence_buf_ensure_tailroom(buffer, count);
			twopence_buf_append(buffer, PyByteArray_AsString(object), count);
		}
		if (buf_ret)
			*buf_ret = buffer;
	} else
	if (PyFile_Check(object)) {
		int fd = PyObject_AsFileDescriptor(object);

		if (fd < 0) {
			/* If this fails, we could also pull the content into a buffer and then send that */
			PyErr_SetString(PyExc_TypeError, "unable to obtain file handle from File object");
			return false;
		}

		/* We dup() the file descriptor so that we no longer have to worry
		 * about what python does with its File object */
		twopence_command_iostream_redirect(cmd, dst, dup(fd), true);
	} else
	if (object == Py_None) {
		/* Nothing */
	} else {
		/* FIXME: we could check for a string type, and in that case interpret that as
		 * the name of a file to write to. */
		PyErr_SetString(PyExc_TypeError, "invalid type in stdio attribute");
		return false;
	}

	return true;
}
Exemplo n.º 12
0
static PyObject *bip_ord(term_t t) {
  PyObject *pVal;
  Py_ssize_t size;

  if (!PL_get_arg(1, t, t))
    return NULL;
  pVal = term_to_python(t, true);
  if (PyUnicode_Check(pVal)) {
#if PY_MAJOR_VERSION < 3
    size = PyUnicode_GET_SIZE(pVal);
#else
    size = PyUnicode_GetLength(pVal);
#endif
    if (size == 1) {
#if PY_MAJOR_VERSION < 3
      long ord = (long)*PyUnicode_AS_UNICODE(pVal);
      return PyInt_FromLong(ord);
#else
      Py_UCS4 ord = PyUnicode_ReadChar(pVal, 0);
      return PyLong_FromLong(ord);
#endif
    }
    return NULL;
  } else if (PyByteArray_Check(pVal)) {
    char *s = PyByteArray_AsString(pVal);

    if (s[1])
      return NULL;
#if PY_MAJOR_VERSION < 3
    return PyInt_FromLong(s[0]);
  } else if (PyString_Check(pVal)) {
    char *s = PyString_AsString(pVal);

    if (s[1])
      return NULL;
    return PyInt_FromLong(s[0]);
#else
    return PyLong_FromLong(s[0]);
#endif
  } else
    return NULL;
}
Exemplo n.º 13
0
static ssize_t python_vfs_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
{
	struct pyfuncs *pf = handle->data;
	PyObject *pArgs, *pRet, *pValue;
	char *pydata;
	ssize_t s;

	PY_TUPLE_NEW(2);
	PY_ADD_TO_TUPLE(fsp->fh->fd, PyInt_FromSsize_t, 0);
	PY_ADD_TO_TUPLE(n, PyInt_FromSize_t, 1);
	PY_CALL_WITH_ARGS(Read);

	if (PyString_Check(pRet)) {
		pydata = PyString_AsString(pRet);
		if (pydata == NULL) {
			Py_DECREF(pRet);
			errno = E_INTERNAL;
			return -1;
		}
		s = PyString_Size(pRet);

	} else if (PyByteArray_Check(pRet)) {
		pydata = PyByteArray_AsString(pRet);
		if (pydata == NULL) {
			Py_DECREF(pRet);
			errno = E_INTERNAL;
			return -1;
		}
		s = PyByteArray_Size(pRet);

	} else {
		errno = PyInt_AsLong(pRet);
		Py_DECREF(pRet);
		return -1;
	}

	memcpy(data, pydata, s > n ? n : s);

	Py_DECREF(pRet);
	return s;
}
Exemplo n.º 14
0
PyObject *
pycbc_tc_determine_format(PyObject *value)
{
    if (PyUnicode_Check(value)) {
        return pycbc_helpers.fmt_utf8_flags;

    } else if (PyBytes_Check(value) || PyByteArray_Check(value)) {
        return pycbc_helpers.fmt_bytes_flags;

    } else if (PyList_Check(value) ||
            PyTuple_Check(value) ||
            PyDict_Check(value) ||
            value == Py_True ||
            value == Py_False ||
            value == Py_None) {
        return pycbc_helpers.fmt_json_flags;

    } else {
        return pycbc_helpers.fmt_pickle_flags;
    }
}
Exemplo n.º 15
0
static PyObject* _update_hash(void* hash_state, PyObject* arg_obj) {
    Py_ssize_t tuple_length;
    Py_ssize_t tuple_i;
    PyObject* tuple_obj, *partial_result;

#if PY_MAJOR_VERSION >= 3
    if (PyBytes_Check(arg_obj)) {
        XXH32_update(hash_state, PyBytes_AsString(arg_obj), PyBytes_Size(arg_obj));
    }
#else
    if (PyString_Check(arg_obj)) {
        XXH32_update(hash_state, PyString_AsString(arg_obj), PyString_Size(arg_obj));
    }
#endif
    else if (PyByteArray_Check(arg_obj)) {
        XXH32_update(hash_state, PyByteArray_AsString(arg_obj), PyByteArray_Size(arg_obj));
    }
    else if (PyTuple_Check(arg_obj)) {
        tuple_length = PyTuple_GET_SIZE(arg_obj);
        for(tuple_i = 0; tuple_i < tuple_length; tuple_i++) {
            tuple_obj = PyTuple_GetItem(arg_obj, tuple_i);
            partial_result = _update_hash(hash_state, tuple_obj);
            // Check exceptions
            if (partial_result == NULL) return NULL;
        }
    }
    else if (arg_obj == Py_None) {
        Py_RETURN_NONE;
    }
    else if (PyUnicode_Check(arg_obj)) {
        PyErr_SetString(PyExc_TypeError, "Found unicode string, you must convert to bytes/str before hashing.");
        return NULL;
    }
    else {
        PyErr_Format(PyExc_TypeError, "Tried to hash unsupported type: %S.", Py_TYPE(arg_obj));
        return NULL;
    }

    Py_RETURN_NONE;
}
Exemplo n.º 16
0
static PyObject *
c_set(void *ptr, PyObject *value, Py_ssize_t size)
{
    if (PyUnicode_Check(value)) {
        value = PyUnicode_AsEncodedString(value,
                                          _ctypes_conversion_encoding,
                                          _ctypes_conversion_errors);
        if (value == NULL)
            return NULL;
        if (PyBytes_GET_SIZE(value) != 1) {
            Py_DECREF(value);
            goto error;
        }
        *(char *)ptr = PyBytes_AS_STRING(value)[0];
        Py_DECREF(value);
        _RET(value);
    }
    if (PyBytes_Check(value) && PyBytes_GET_SIZE(value) == 1) {
        *(char *)ptr = PyBytes_AS_STRING(value)[0];
        _RET(value);
    }
    if (PyByteArray_Check(value) && PyByteArray_GET_SIZE(value) == 1) {
        *(char *)ptr = PyByteArray_AS_STRING(value)[0];
        _RET(value);
    }
    if (PyLong_Check(value))
    {
        long longval = PyLong_AS_LONG(value);
        if (longval < 0 || longval >= 256)
            goto error;
        *(char *)ptr = (char)longval;
        _RET(value);
    }
  error:
    PyErr_Format(PyExc_TypeError,
                 "one character string expected");
    return NULL;
}
Exemplo n.º 17
0
int
Transfer_build_send(twopence_Transfer *self, twopence_file_xfer_t *xfer)
{
	twopence_file_xfer_init(xfer);

	xfer->remote.name = self->remote_filename;
	xfer->remote.mode = self->permissions;
	xfer->user = self->user;
	/* xfer->timeout = self->timeout; */

	if (self->local_filename) {
		int rv;

		rv = twopence_iostream_open_file(self->local_filename, &xfer->local_stream);
		if (rv < 0)
			return -1;
	} else if (self->buffer != NULL && PyByteArray_Check(self->buffer)) {
		unsigned int count;

		twopence_buf_destroy(&self->databuf);

		count = PyByteArray_Size(self->buffer);
		twopence_buf_ensure_tailroom(&self->databuf, count);
		twopence_buf_append(&self->databuf, PyByteArray_AsString(self->buffer), count);
		if (twopence_iostream_wrap_buffer(&self->databuf, false, &xfer->local_stream) < 0) {
			PyErr_SetString(PyExc_TypeError, "Cannot convert xfer buffer");
			return -1;
		}
	} else {
		/* We don't know what to send */
		PyErr_SetString(PyExc_TypeError, "Transfer object specifies neither localfile nor buffer");
		return -1;
	}

	return 0;
}
Exemplo n.º 18
0
static PyObject *
c_set(void *ptr, PyObject *value, Py_ssize_t size)
{
    if (PyBytes_Check(value) && PyBytes_GET_SIZE(value) == 1) {
        *(char *)ptr = PyBytes_AS_STRING(value)[0];
        _RET(value);
    }
    if (PyByteArray_Check(value) && PyByteArray_GET_SIZE(value) == 1) {
        *(char *)ptr = PyByteArray_AS_STRING(value)[0];
        _RET(value);
    }
    if (PyLong_Check(value))
    {
        long longval = PyLong_AS_LONG(value);
        if (longval < 0 || longval >= 256)
            goto error;
        *(char *)ptr = (char)longval;
        _RET(value);
    }
  error:
    PyErr_Format(PyExc_TypeError,
                 "one character string expected");
    return NULL;
}
Exemplo n.º 19
0
/* Convert a Python object to a QVariant */
QVariant PyObject_AsQVariant(PyObject *obj)
{
    // Dict -> QVariantHash
    if (PyDict_Check(obj))
    {
        QVariantHash result;
        Py_ssize_t pos = 0;
        PyObject *pykey, *pyval;
        while (PyDict_Next(obj, &pos, &pykey, &pyval))
        {
            QString key = PyString_AsQString(pykey);
            result[key] = PyObject_AsQVariant(pyval);
        }
        return result;
    }
    // List -> QVariantList
    else if (PyList_Check(obj))
    {
        QVariantList result;
        Py_ssize_t len = PyList_Size(obj);
        for (Py_ssize_t i = 0; i < len; i++)
        {
            PyObject *item = PyList_GetItem(obj, i);
            result << PyObject_AsQVariant(item);
        }
        return result;
    }
    // Tuple -> QVariantList
    else if (PyTuple_Check(obj))
    {
        QVariantList result;
        Py_ssize_t len = PyTuple_Size(obj);
        for (Py_ssize_t i = 0; i < len; i++)
        {
            PyObject *item = PyTuple_GetItem(obj, i);
            result << PyObject_AsQVariant(item);
        }
        return result;
    }
    // Long
    else if (PyLong_Check(obj))
        return PyLong_AsLongLong(obj);

    // Int
#if PY_MAJOR_VERSION == 2
    else if (PyInt_Check(obj))
        return (long long) PyInt_AsLong(obj);
#endif

    // Float
    else if (PyFloat_Check(obj))
        return PyFloat_AsDouble(obj);

    // String
#if PY_MAJOR_VERSION >= 3
    else if (PyUnicode_Check(obj) || PyByteArray_Check(obj))
#else
    else if (PyUnicode_Check(obj) || PyString_Check(obj))
#endif
        return PyString_AsQString(obj);

    // Unknown
    else
    {
        qDebug("Error: convert an PyObject of unknown type to QVariant.");
        return QVariant();
    }
}
Exemplo n.º 20
0
/**
 *******************************************************************************************************
 * This function invokes csdk's API's.
 *
 * @param self                  AerospikeClient object
 * @param err                   The as_error to be populated by the function
 *                              with the encountered error if any.
 * @param key                   The C client's as_key that identifies the record.
 * @param py_list               The list containing op, bin and value.
 * @param py_meta               The metadata for the operation.
 * @param operate_policy_p      The value for operate policy.
 *******************************************************************************************************
 */
static
PyObject *  AerospikeClient_Operate_Invoke(
	AerospikeClient * self, as_error *err,
	as_key * key, PyObject * py_list, PyObject * py_meta,
	as_policy_operate * operate_policy_p)
{
	as_val* put_val = NULL;
	char* bin = NULL;
	char* val = NULL;
	long offset = 0;
	double double_offset = 0.0;
	uint32_t ttl = 0;
	long operation = 0;
	int i = 0;
	PyObject * py_rec = NULL;
	PyObject * py_ustr = NULL;
	PyObject * py_ustr1 = NULL;
	PyObject * py_bin = NULL;
	as_record * rec = NULL;

	as_static_pool static_pool;
	memset(&static_pool, 0, sizeof(static_pool));

	as_operations ops;
	Py_ssize_t size = PyList_Size(py_list);
	as_operations_inita(&ops, size);

	if (!self || !self->as) {
		as_error_update(err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object");
		goto CLEANUP;
	}

	if(py_meta) {
		AerospikeClient_CheckForMeta(py_meta, &ops, err);
	}

	if (err->code != AEROSPIKE_OK) {
		goto CLEANUP;
	}

	for ( i = 0; i < size; i++) {
		PyObject * py_val = PyList_GetItem(py_list, i);
		operation = -1;
		offset = 0;
		double_offset = 0.0;
		if ( PyDict_Check(py_val) ) {
			PyObject *key_op = NULL, *value = NULL;
			PyObject * py_value = NULL;
			Py_ssize_t pos = 0;
			while (PyDict_Next(py_val, &pos, &key_op, &value)) {
				if ( ! PyString_Check(key_op) ) {
					as_error_update(err, AEROSPIKE_ERR_CLIENT, "A operation key must be a string.");
					goto CLEANUP;
				} else {
					char * name = PyString_AsString(key_op);
					if(!strcmp(name,"op") && (PyInt_Check(value) || PyLong_Check(value))) {
						operation = PyInt_AsLong(value);
					} else if (!strcmp(name, "bin")) {
						py_bin = value;
					} else if(!strcmp(name, "val")) {
						py_value = value;
					} else {
						as_error_update(err, AEROSPIKE_ERR_PARAM, "operation can contain only op, bin and val keys");
						goto CLEANUP;
					}
				}
			}

			if (py_bin) {
				if (PyUnicode_Check(py_bin)) {
					py_ustr = PyUnicode_AsUTF8String(py_bin);
					bin = PyString_AsString(py_ustr);
				} else if (PyString_Check(py_bin)) {
					bin = PyString_AsString(py_bin);
				} else if (PyByteArray_Check(py_bin)) {
                    bin = PyByteArray_AsString(py_bin);
                } else {
                    as_error_update(err, AEROSPIKE_ERR_PARAM, "Bin name should be of type string");
					goto CLEANUP;
				}

				if (self->strict_types) {
					if (strlen(bin) > AS_BIN_NAME_MAX_LEN) {
						if (py_ustr) {
							Py_DECREF(py_ustr);
							py_ustr = NULL;
						}
						as_error_update(err, AEROSPIKE_ERR_BIN_NAME, "A bin name should not exceed 14 characters limit");
						goto CLEANUP;
					}
				}
			} else if (!py_bin && operation != AS_OPERATOR_TOUCH) {
				as_error_update(err, AEROSPIKE_ERR_PARAM, "Bin is not given");
				goto CLEANUP;
			}
			if (py_value) {
				if (self->strict_types) {
					if (check_type(self, py_value, operation, err)) {
						goto CLEANUP;
					}
				}
			} else if ((!py_value) && (operation != AS_OPERATOR_READ && operation != AS_OPERATOR_TOUCH)) {
				as_error_update(err, AEROSPIKE_ERR_PARAM, "Value should be given");
				goto CLEANUP;
			}

			switch(operation) {
				case AS_OPERATOR_APPEND:
					if (PyUnicode_Check(py_value)) {
						py_ustr1 = PyUnicode_AsUTF8String(py_value);
						val = PyString_AsString(py_ustr1);
						as_operations_add_append_str(&ops, bin, val);
					} else if (PyString_Check(py_value)) {
						val = PyString_AsString(py_value);
						as_operations_add_append_str(&ops, bin, val);
					} else if (PyByteArray_Check(py_value)) {
						as_bytes *bytes;
						GET_BYTES_POOL(bytes, &static_pool, err);
						serialize_based_on_serializer_policy(self, SERIALIZER_PYTHON, &bytes, py_value, err);
						as_operations_add_append_raw(&ops, bin, bytes->value, bytes->size);
					} else {
						if (!self->strict_types || !strcmp(py_value->ob_type->tp_name, "aerospike.null")) {
							as_operations *pointer_ops = &ops;
							as_binop *binop = &pointer_ops->binops.entries[pointer_ops->binops.size++];
							binop->op = AS_OPERATOR_APPEND;
							initialize_bin_for_strictypes(self, err, py_value, binop, bin, &static_pool);
						}
					}
					break;
				case AS_OPERATOR_PREPEND:
					if (PyUnicode_Check(py_value)) {
						py_ustr1 = PyUnicode_AsUTF8String(py_value);
						val = PyString_AsString(py_ustr1);
						as_operations_add_prepend_str(&ops, bin, val);
					} else if (PyString_Check(py_value)) {
						val = PyString_AsString(py_value);
						as_operations_add_prepend_str(&ops, bin, val);
					} else if (PyByteArray_Check(py_value)) {
						as_bytes *bytes;
						GET_BYTES_POOL(bytes, &static_pool, err);
						serialize_based_on_serializer_policy(self, SERIALIZER_PYTHON, &bytes, py_value, err);
						as_operations_add_prepend_raw(&ops, bin, bytes->value, bytes->size);
					} else {
						if (!self->strict_types || !strcmp(py_value->ob_type->tp_name, "aerospike.null")) {
							as_operations *pointer_ops = &ops;
							as_binop *binop = &pointer_ops->binops.entries[pointer_ops->binops.size++];
							binop->op = AS_OPERATOR_PREPEND;
							initialize_bin_for_strictypes(self, err, py_value, binop, bin, &static_pool);
						}
					}
					break;
				case AS_OPERATOR_INCR:
					if (PyInt_Check(py_value)) {
						offset = PyInt_AsLong(py_value);
						as_operations_add_incr(&ops, bin, offset);
					} else if ( PyLong_Check(py_value) ) {
						offset = PyLong_AsLong(py_value);
						if (offset == -1 && PyErr_Occurred()) {
							if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
								as_error_update(err, AEROSPIKE_ERR_PARAM, "integer value exceeds sys.maxsize");
								goto CLEANUP;
							}
						}
						as_operations_add_incr(&ops, bin, offset);
					} else if (PyFloat_Check(py_value)) {
						double_offset = PyFloat_AsDouble(py_value);
						as_operations_add_incr_double(&ops, bin, double_offset);
					} else {
						if (!self->strict_types || !strcmp(py_value->ob_type->tp_name, "aerospike.null")) {
							as_operations *pointer_ops = &ops;
							as_binop *binop = &pointer_ops->binops.entries[pointer_ops->binops.size++];
							binop->op = AS_OPERATOR_INCR;
							initialize_bin_for_strictypes(self, err, py_value, binop, bin, &static_pool);
						}
					}
					break;
				case AS_OPERATOR_TOUCH:
                    ops.ttl = 0;
					if (py_value && PyInt_Check(py_value)) {
                        ops.ttl = PyInt_AsLong(py_value);
                    } else if (py_value && PyLong_Check(py_value)) {
                        ttl = PyLong_AsLong(py_value);
                        if((uint32_t)-1 == ttl) {
                            as_error_update(err, AEROSPIKE_ERR_PARAM, "integer value for ttl exceeds sys.maxsize");
                            goto CLEANUP;
                        }
                        ops.ttl = ttl;
                    }
					as_operations_add_touch(&ops);
					break;
				case AS_OPERATOR_READ:
					as_operations_add_read(&ops, bin);
					break;
				case AS_OPERATOR_WRITE:
					pyobject_to_astype_write(self, err, bin, py_value, &put_val, &ops,
							&static_pool, SERIALIZER_PYTHON);
					if (err->code != AEROSPIKE_OK) {
						goto CLEANUP;
					}
					as_operations_add_write(&ops, bin, (as_bin_value *) put_val);
					break;
				default:
					if (self->strict_types) {
						as_error_update(err, AEROSPIKE_ERR_PARAM, "Invalid operation given");
						goto CLEANUP;
					}
			}
		}
	}

	// Initialize record
	as_record_init(rec, 0);

	Py_BEGIN_ALLOW_THREADS
	aerospike_key_operate(self->as, err, operate_policy_p, key, &ops, &rec);
	Py_END_ALLOW_THREADS

	if (err->code != AEROSPIKE_OK) {
		as_error_update(err, err->code, NULL);
		goto CLEANUP;
	}
	if(rec) {
		record_to_pyobject(self, err, rec, key, &py_rec);
	}

CLEANUP:
	if (py_ustr) {
		Py_DECREF(py_ustr);
	}
	if (py_ustr1) {
		Py_DECREF(py_ustr1);
	}
	if (rec) {
		as_record_destroy(rec);
	}
	if (key->valuep) {
		as_key_destroy(key);
	}
	if (put_val) {
		as_val_destroy(put_val);
	}

	if ( err->code != AEROSPIKE_OK ) {
		PyObject * py_err = NULL;
		error_to_pyobject(err, &py_err);
		PyObject *exception_type = raise_exception(err);
		PyErr_SetObject(exception_type, py_err);
		Py_DECREF(py_err);
		return NULL;
	}

	if (py_rec) {
		return py_rec;
	} else {
		return PyLong_FromLong(0);
	}
}
Exemplo n.º 21
0
/*
 *******************************************************************************************************
 * Checks serializer_policy.
 * Serializes Py_Object (value) into as_bytes using serialization logic
 * based on serializer_policy.
 *
 * @param serializer_policy         The serializer_policy to be used to handle
 *                                  the serialization.
 * @param bytes                     The as_bytes to be set.
 * @param value                     The value to be serialized.
 * @param error_p                   The as_error to be populated by the function
 *                                  with encountered error if any.
 *******************************************************************************************************
 */
extern PyObject * serialize_based_on_serializer_policy(AerospikeClient * self,
        int32_t serializer_policy,
		as_bytes **bytes,
		PyObject *value,
		as_error *error_p)
{
    uint8_t use_client_serializer = true;
	PyObject* initresult = NULL;

    if (self->is_client_put_serializer) {
        if (serializer_policy == SERIALIZER_USER) {
            if (!self->user_serializer_call_info.callback) {
                use_client_serializer = false;
            }
        }
    } else if (self->user_serializer_call_info.callback) {
        serializer_policy = SERIALIZER_USER;
    }

	switch(serializer_policy) {
		case SERIALIZER_NONE:
			as_error_update(error_p, AEROSPIKE_ERR_PARAM,
					"Cannot serialize: SERIALIZER_NONE selected");
			goto CLEANUP;
		case SERIALIZER_PYTHON:
			{
				/*
				 * Serialize bytearray as is and store them into database with
				 * type AS_BYTES_BLOB, unlike other values in case of 
				 * SERIALIZER_PYTHON.
				 * This is a special case.
				 * Refer: AER-3589 for more details.
				 */
				if (PyByteArray_Check(value)) {
					uint8_t *bytes_array = (uint8_t *) PyByteArray_AsString(value);
					uint32_t bytes_array_len  = (uint32_t)  PyByteArray_Size(value);

					set_as_bytes(bytes, bytes_array, bytes_array_len, AS_BYTES_BLOB, error_p);

				} else {

					/* get the sys.modules dictionary */
					PyObject* sysmodules = PyImport_GetModuleDict();
					PyObject* cpickle_module = NULL;
					if(PyMapping_HasKeyString(sysmodules, "cPickle")) {
						cpickle_module = PyMapping_GetItemString(sysmodules, "cPickle");
					} else {
						cpickle_module = PyImport_ImportModule("cPickle");
					}

					if(!cpickle_module) {
						/* insert error handling here! and exit this function */
						as_error_update(error_p, AEROSPIKE_ERR_CLIENT, "Unable to load cpickle module");
						goto CLEANUP;
					} else {
						PyObject * py_funcname = PyStr_FromString("dumps");

						Py_INCREF(cpickle_module);
						initresult = PyObject_CallMethodObjArgs(cpickle_module,
								py_funcname, value, NULL);
						Py_DECREF(cpickle_module);
						Py_DECREF(py_funcname);

						if(!initresult) {
							/* more error handling &c */
							as_error_update(error_p, AEROSPIKE_ERR_CLIENT, "Unable to call dumps function");
							goto CLEANUP;
						} else {
							Py_INCREF(initresult);
							char *return_value = PyStr_AsString(initresult);
							Py_ssize_t len = PyBytes_GET_SIZE(initresult);
                            set_as_bytes(bytes, (uint8_t *) return_value,
									len, AS_BYTES_PYTHON, error_p);
							Py_DECREF(initresult);
						}
					}
					Py_XDECREF(cpickle_module);
				}
			}
			break;
		case SERIALIZER_JSON:
			/*
			 *   TODO:
			 *     Handle JSON serialization after support for AS_BYTES_JSON
			 *     is added in aerospike-client-c
			 */
			as_error_update(error_p, AEROSPIKE_ERR,
					"Unable to serialize using standard json serializer");
			goto CLEANUP;

		case SERIALIZER_USER:
            if (use_client_serializer) {
                execute_user_callback(&self->user_serializer_call_info, bytes, &value, true, error_p);
				if (AEROSPIKE_OK != (error_p->code)) {
					goto CLEANUP;
				}
            } else {
			    if (is_user_serializer_registered) {
                    execute_user_callback(&user_serializer_call_info, bytes, &value, true, error_p);
				    if (AEROSPIKE_OK != (error_p->code)) {
					    goto CLEANUP;
				    }
			    } else if (self->user_serializer_call_info.callback) {
                    execute_user_callback(&self->user_serializer_call_info, bytes, &value, true, error_p);
				    if (AEROSPIKE_OK != (error_p->code)) {
					    goto CLEANUP;
				    }
                } else {
				    as_error_update(error_p, AEROSPIKE_ERR,
						"No serializer callback registered");
				    goto CLEANUP;
			    }
            }
		    break;
		default:
			as_error_update(error_p, AEROSPIKE_ERR,
					"Unsupported serializer");
			goto CLEANUP;
	}

CLEANUP:

	Py_XDECREF(initresult);
  	if ( error_p->code != AEROSPIKE_OK ) {
		PyObject * py_err = NULL;
		error_to_pyobject(error_p, &py_err);
		PyObject *exception_type = raise_exception(error_p);
		PyErr_SetObject(exception_type, py_err);
		Py_DECREF(py_err);
		return NULL;
	}

	return PyLong_FromLong(0);
}
Exemplo n.º 22
0
static bool GetParameterInfo(Cursor* cur, Py_ssize_t index, PyObject* param, ParamInfo& info)
{
    // Determines the type of SQL parameter that will be used for this parameter based on the Python data type.
    //
    // Populates `info`.

    // TODO: if the param is a SQLParameter object, then bind to the wrapped value and use the input/output type from that

    // Hold a reference to param until info is freed, because info will often be holding data borrowed from param.
    if (PyObject_TypeCheck(param, (PyTypeObject*)SQLParameter_type))
    {
        info.pParam = ((SQLParameter*)param)->value;
        info.InputOutputType = ((SQLParameter*)param)->type;
    }
    else
    {
        info.pParam = param;
        info.InputOutputType = SQL_PARAM_INPUT;
    }

    if (info.pParam == Py_None)
        return GetNullInfo(cur, index, info);

    if (info.pParam == null_binary)
        return GetNullBinaryInfo(cur, index, info);

    if (PyBytes_Check(info.pParam))
        return GetBytesInfo(cur, index, info.pParam, info);

    if (PyUnicode_Check(info.pParam))
        return GetUnicodeInfo(cur, index, info.pParam, info);

    if (PyBool_Check(info.pParam))
        return GetBooleanInfo(cur, index, info.pParam, info);

    if (PyDateTime_Check(info.pParam))
        return GetDateTimeInfo(cur, index, info.pParam, info);

    if (PyDate_Check(info.pParam))
        return GetDateInfo(cur, index, info.pParam, info);

    if (PyTime_Check(info.pParam))
        return GetTimeInfo(cur, index, info.pParam, info);

    if (PyLong_Check(info.pParam))
        return GetLongInfo(cur, index, info.pParam, info);

    if (PyFloat_Check(info.pParam))
        return GetFloatInfo(cur, index, info.pParam, info);

    if (PyDecimal_Check(info.pParam))
        return GetDecimalInfo(cur, index, info.pParam, info);

#if PY_VERSION_HEX >= 0x02060000
    if (PyByteArray_Check(info.pParam))
        return GetByteArrayInfo(cur, index, info.pParam, info);
#endif

#if PY_MAJOR_VERSION < 3
    if (PyInt_Check(info.pParam))
        return GetIntInfo(cur, index, info.pParam, info);

    if (PyBuffer_Check(info.pParam))
        return GetBufferInfo(cur, index, info.pParam, info);
#endif

    RaiseErrorV("HY105", ProgrammingError, "Invalid parameter type.  param-index=%zd param-type=%s", index, Py_TYPE(info.pParam)->tp_name);
    return false;
}
Exemplo n.º 23
0
void PythonTransform::transform(const QByteArray &input, QByteArray &output)
{
    if (input.isEmpty())
        return;

    PyGILState_STATE lgstate;
    lgstate = PyGILState_Ensure();
    if (loadModule()) {
        PyObject * pyInbound = Py_False; // needs reference count management

        if (twoWays)
            pyInbound = (wayValue == INBOUND ? Py_True : Py_False );
        Py_INCREF(pyInbound);

        if (PyModule_AddObject(pModule, PythonModules::INBOUND_ATTR_NAME, pyInbound) == -1) { // steal reference
            pythonmgm->checkPyError();
            logError(tr("T_T Could not set the direction value properly:\n%1").arg(pythonmgm->getLastError()),id);
            Py_XDECREF(pyInbound);
            PyGILState_Release(lgstate);
            return;
        }

        PyObject *paramsdict = PyDict_New(); // setting an empty dictionary
        // setting parameters in the python environment
        if (!parameters.isEmpty()) {
            if (!pythonmgm->checkPyError()) {
                logError(tr("T_T Error while creating the Python parameter dict:\n%1").arg(pythonmgm->getLastError()), id);
                Py_XDECREF(paramsdict);
                PyGILState_Release(lgstate);
                return;
            }
            // adding parameters to the python list
            QHashIterator<QByteArray, QByteArray> i(parameters);
            while (i.hasNext()) {
                i.next();
                PyObject* paramKey = PyUnicode_FromStringAndSize(i.key(),i.key().size());
                if (!pythonmgm->checkPyError()) {
                    logError(tr("T_T Error while creating Python parameter key:\n%1").arg(pythonmgm->getLastError()), id);
                    Py_XDECREF(paramsdict);
                    PyGILState_Release(lgstate);
                    return;
                }

                PyObject* paramValue = PyUnicode_FromStringAndSize(i.value(),i.value().size());
                if (!pythonmgm->checkPyError()) {
                    logError(tr("T_T Error while creating Python parameter value:\n%1").arg(pythonmgm->getLastError()), id);
                    Py_XDECREF(paramsdict);
                    Py_XDECREF(paramKey);
                    PyGILState_Release(lgstate);
                    return;
                }

                if (PyDict_SetItem(paramsdict,paramKey,paramValue) == -1) { // not stealing reference
                    pythonmgm->checkPyError(); // we already know there was an error
                    logError(tr("T_T Error while setting Python parameter pair:\n%1").arg(pythonmgm->getLastError()), id);
                    Py_XDECREF(paramsdict);
                    Py_XDECREF(paramKey);
                    Py_XDECREF(paramValue);
                    PyGILState_Release(lgstate);
                    return;
                }

                // Cleaning the values (references not stolen)

                Py_XDECREF(paramKey);
                Py_XDECREF(paramValue);
            }
        }

        // setting the dictionary in any case, even if it is empty
        if (PyModule_AddObject(pModule,PythonModules::PARAMS_ATTR_NAME , paramsdict) == -1) { // stolen paramsdict reference
            pythonmgm->checkPyError();
            logError(tr("T_T Could not set the Pip3line_params value properly:\n%1").arg(pythonmgm->getLastError()),id);
        }

        PyObject * pFunc = PyObject_GetAttrString(pModule, PythonModules::MAIN_FUNCTION_NAME);

        if (pythonmgm->checkPyError() && PyCallable_Check(pFunc)) {
            PyObject* pArgs = PyTuple_New(1);

            if (!pythonmgm->checkPyError()) {
                Q_EMIT error(tr("T_T Error while creating the Python argument tuple:\n%1").arg(pythonmgm->getLastError()), id);
                Py_XDECREF(pFunc);
                Py_XDECREF(pArgs);
                PyGILState_Release(lgstate);
                return;
            }

            PyObject* inputPy = PyByteArray_FromStringAndSize(input.data(),input.size());
            if (!pythonmgm->checkPyError()) {
                Q_EMIT error(tr("T_T Error while creating the Python byte array:\n%1").arg(pythonmgm->getLastError()), id);
                Py_XDECREF(pFunc);
                Py_XDECREF(pArgs);
                Py_XDECREF(inputPy);
                PyGILState_Release(lgstate);
                return;
            }

            if (PyTuple_SetItem(pArgs, 0, inputPy) != 0) {// stealing the reference of inputPy
                pythonmgm->checkPyError();
                Q_EMIT error(tr("T_T Error while creating the Python byte array:\n%1").arg(pythonmgm->getLastError()), id);
                Py_XDECREF(inputPy);
                Py_XDECREF(pFunc);
                Py_XDECREF(pArgs);
                PyGILState_Release(lgstate);
                return;
            }
            PyObject* returnValue = PyObject_CallObject(pFunc, pArgs); // new ref or NULL

            if (!pythonmgm->checkPyError()) {
                Q_EMIT error(tr("T_T Python error while executing the function:\n %1").arg(pythonmgm->getLastError()), id);
            } else {
                if (PyByteArray_Check(returnValue)) {

                    Py_ssize_t templength = PyByteArray_Size(returnValue);
                    if (templength > BLOCK_MAX_SIZE) {
                        templength = BLOCK_MAX_SIZE;
                        Q_EMIT warning(tr("Data block returned is too large, truncating."),id);
                    }

                    char * buffer = PyByteArray_AsString(returnValue); // never to be deleted
                    output.append(QByteArray(buffer,static_cast<int>(templength))); // safe cast as value was checked earlier
                } else {
                    Q_EMIT error(tr("The Python object returned is not a bytearray"), id);
                }
            }

            Py_XDECREF(returnValue);
            Py_XDECREF(pArgs);
          //  Py_DECREF(inputPy); // stolen reference, don't touch that
            Py_XDECREF(pFunc);

        } else {
            Q_EMIT error(tr("Python error while calling the function %1():\n%2").arg(PythonModules::MAIN_FUNCTION_NAME).arg(pythonmgm->getLastError()), id);
        }
    } else {
        qDebug() << "[Python transform] could not load the module";
    }

    PyGILState_Release(lgstate);
}
Exemplo n.º 24
0
NUITKA_MAY_BE_UNUSED static PyObject *TO_INT2( PyObject *value, PyObject *base )
{
    // TODO: Need to check if 3.4 is really the first version to do this.
#if PYTHON_VERSION < 340
    long base_int = PyInt_AsLong( base );
#else
    Py_ssize_t base_int = PyNumber_AsSsize_t( base, NULL );
#endif

    if (unlikely( base_int == -1 ))
    {
        PyObject *error = GET_ERROR_OCCURRED();

        if (likely( error ))
        {
#if PYTHON_VERSION >= 300
            if ( EXCEPTION_MATCH_BOOL_SINGLE( error, PyExc_OverflowError ) )
            {
                PyErr_Format(
                        PyExc_ValueError,
#if PYTHON_VERSION < 324
                        "int() arg 2 must be >= 2 and <= 36"
#else
                        "int() base must be >= 2 and <= 36"
#endif
                );
            }
#endif
            return NULL;
        }
    }

#if PYTHON_VERSION >= 300
    if (unlikely( ( base_int != 0 && base_int < 2 ) || base_int > 36 ))
    {
        PyErr_Format(
                PyExc_ValueError,
#if PYTHON_VERSION < 324
                "int() arg 2 must be >= 2 and <= 36"
#else
                "int() base must be >= 2 and <= 36"
#endif
        );

        return NULL;
    }
#endif

#if PYTHON_VERSION < 300
    if (unlikely( !Nuitka_String_Check( value ) && !PyUnicode_Check( value ) ))
    {
        PyErr_Format(
            PyExc_TypeError,
            "int() can't convert non-string with explicit base"
        );
        return NULL;
    }

    char *value_str = Nuitka_String_AsString( value );
    if (unlikely( value_str == NULL ))
    {
        return NULL;
    }

    PyObject *result = PyInt_FromString( value_str, NULL, base_int );
    if (unlikely( result == NULL ))
    {
        return NULL;
    }

    return result;
#else
    if ( PyUnicode_Check( value ) )
    {
#if PYTHON_VERSION < 330
        char *value_str = Nuitka_String_AsString( value );

        if (unlikely( value_str == NULL ))
        {
            return NULL;
        }

        PyObject *result = PyInt_FromString( value_str, NULL, base_int );

        if (unlikely( result == NULL ))
        {
            return NULL;
        }

        return result;
#else
        return PyLong_FromUnicodeObject( value, (int)base_int );
#endif
    }
    else if ( PyBytes_Check( value ) || PyByteArray_Check( value ) )
    {
        // Check for "NUL" as PyLong_FromString has no length parameter,
        Py_ssize_t size = Py_SIZE( value );
        char *value_str;

        if ( PyByteArray_Check( value ) )
        {
            value_str = PyByteArray_AS_STRING( value );
        }
        else
        {
            value_str = PyBytes_AS_STRING( value );
        }

        PyObject *result = NULL;

        if ( size != 0 && strlen( value_str ) == (size_t)size )
        {
            result = PyInt_FromString( value_str, NULL, (int)base_int );
        }

        if (unlikely( result == NULL ))
        {
            PyErr_Format(
                PyExc_ValueError,
                "invalid literal for int() with base %d: %R",
                base_int,
                value
            );

            return NULL;
        }

        return result;
    }
    else
    {
        PyErr_Format(
            PyExc_TypeError,
            "int() can't convert non-string with explicit base"
        );
        return NULL;
    }
#endif
}
Exemplo n.º 25
0
static PyObject *
pytrap_init(PyObject *self, PyObject *args, PyObject *keywds)
{
    char **argv = NULL;
    char *arg;
    PyObject *argvlist;
    PyObject *strObj;
    int argc = 0, i, ifcin = 1, ifcout = 0;

    static char *kwlist[] = {"argv", "ifcin", "ifcout", NULL};
    if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|ii", kwlist, &PyList_Type, &argvlist, &ifcin, &ifcout)) {
        return NULL;
    }

    argc = PyList_Size(argvlist);
    if (argc ==0) {
        PyErr_SetString(TrapError, "argv list must not be empty.");
        return NULL;
    }
    argv = calloc(argc, sizeof(char *));
    for (i=0; i<argc; i++) {
        strObj = PyList_GetItem(argvlist, i);
#if PY_MAJOR_VERSION >= 3
        if (!PyUnicode_Check(strObj)) {
#else
        if (!PyString_Check(strObj)) {
#endif
            PyErr_SetString(TrapError, "argv must contain string.");
            goto failure;
        }
#if PY_MAJOR_VERSION >= 3
        arg = PyUnicode_AsUTF8AndSize(strObj, NULL);
#else
        arg = PyString_AS_STRING(strObj);
#endif
        argv[i] = arg;
    }

    int ret = local_trap_init(argc, argv, module_info, ifcin, ifcout);
    if (ret != 0) {
        PyErr_SetString(TrapError, "Initialization failed");
        return NULL;
    }

    Py_RETURN_NONE;
failure:
    free(argv);
    return NULL;
}

static PyObject *
pytrap_send(PyObject *self, PyObject *args, PyObject *keywds)
{
    uint32_t ifcidx = 0;
    PyObject *dataObj;
    char *data;
    Py_ssize_t data_size;

    static char *kwlist[] = {"data", "ifcidx", NULL};
    if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|I", kwlist, &dataObj, &ifcidx)) {
        return NULL;
    }

    if (PyByteArray_Check(dataObj)) {
        data_size = PyByteArray_Size(dataObj);
        data = PyByteArray_AsString(dataObj);
    } else if (PyBytes_Check(dataObj)) {
        PyBytes_AsStringAndSize(dataObj, &data, &data_size);
    } else {
        PyErr_SetString(PyExc_TypeError, "Argument data must be of bytes or bytearray type.");
        return NULL;
    }

    if (data_size > 0xFFFF) {
        PyErr_SetString(TrapError, "Data length is out of range (0-65535)");
        return NULL;
    }

    int ret;
    Py_BEGIN_ALLOW_THREADS
    ret = trap_send(ifcidx, data, (uint16_t) data_size);
    Py_END_ALLOW_THREADS

    if (ret == TRAP_E_TIMEOUT) {
        PyErr_SetString(TimeoutError, "Timeout");
        return NULL;
    } else if (ret == TRAP_E_BAD_IFC_INDEX) {
        PyErr_SetString(TrapError, "Bad index of IFC.");
        return NULL;
    } else if (ret == TRAP_E_TERMINATED) {
        PyErr_SetString(TrapTerminated, "IFC was terminated.");
        return NULL;
    }

    Py_RETURN_NONE;
}
Exemplo n.º 26
0
static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
    if (
#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
            __Pyx_sys_getdefaultencoding_not_ascii && 
#endif
            PyUnicode_Check(o)) {
#if PY_VERSION_HEX < 0x03030000
        char* defenc_c;
        // borrowed, cached reference
        PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL);
        if (!defenc) return NULL;
        defenc_c = PyBytes_AS_STRING(defenc);
#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
        {
            char* end = defenc_c + PyBytes_GET_SIZE(defenc);
            char* c;
            for (c = defenc_c; c < end; c++) {
                if ((unsigned char) (*c) >= 128) {
                    // raise the error
                    PyUnicode_AsASCIIString(o);
                    return NULL;
                }
            }
        }
#endif /*__PYX_DEFAULT_STRING_ENCODING_IS_ASCII*/
        *length = PyBytes_GET_SIZE(defenc);
        return defenc_c;
#else /* PY_VERSION_HEX < 0x03030000 */
        if (PyUnicode_READY(o) == -1) return NULL;
#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
        if (PyUnicode_IS_ASCII(o)) {
            // cached for the lifetime of the object
            *length = PyUnicode_GET_DATA_SIZE(o);
            return PyUnicode_AsUTF8(o);
        } else {
            // raise the error
            PyUnicode_AsASCIIString(o);
            return NULL;
        }
#else /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */
        return PyUnicode_AsUTF8AndSize(o, length);
#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */
#endif /* PY_VERSION_HEX < 0x03030000 */
    } else
#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII  || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT */

#if PY_VERSION_HEX >= 0x02060000
    if (PyByteArray_Check(o)) {
        *length = PyByteArray_GET_SIZE(o);
        return PyByteArray_AS_STRING(o);
    } else
#endif
    {
        char* result;
        int r = PyBytes_AsStringAndSize(o, &result, length);
        if (unlikely(r < 0)) {
            return NULL;
        } else {
            return result;
        }
    }
}
Exemplo n.º 27
0
static int
encode_common(PyObject **o, void **buf, size_t *nbuf, lcb_uint32_t flags)
{
    PyObject *bytesobj;
    Py_ssize_t plen;
    int rv;

    if (flags == PYCBC_FMT_UTF8) {
#if PY_MAJOR_VERSION == 2
        if (PyString_Check(*o)) {
#else
        if (0) {
#endif
            bytesobj = *o;
            Py_INCREF(*o);
        } else {
            if (!PyUnicode_Check(*o)) {
                PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING,
                                   0, "Must be unicode or string", *o);
                return -1;
            }
            bytesobj = PyUnicode_AsUTF8String(*o);
        }

    } else if (flags == PYCBC_FMT_BYTES) {
        if (PyBytes_Check(*o) || PyByteArray_Check(*o)) {
            bytesobj = *o;
            Py_INCREF(*o);

        } else {
            PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0,
                               "Must be bytes or bytearray", *o);
            return -1;
        }

    } else {
        PyObject *args = NULL;
        PyObject *helper;

        if (flags == PYCBC_FMT_PICKLE) {
            helper = pycbc_helpers.pickle_encode;

        } else if (flags == PYCBC_FMT_JSON) {
            helper = pycbc_helpers.json_encode;

        } else {
            PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Unrecognized format");
            return -1;
        }

        args = PyTuple_Pack(1, *o);
        bytesobj = PyObject_CallObject(helper, args);
        Py_DECREF(args);

        if (!bytesobj) {
            PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING,
                               0, "Couldn't encode value", *o);
            return -1;
        }

        if (!PyBytes_Check(bytesobj)) {
            PyObject *old = bytesobj;
            bytesobj = convert_to_bytesobj(old);
            Py_DECREF(old);
            if (!bytesobj) {
                return -1;
            }
        }
    }

    if (PyByteArray_Check(bytesobj)) {
        *buf = PyByteArray_AS_STRING(bytesobj);
        plen = PyByteArray_GET_SIZE(bytesobj);
        rv = 0;
    } else {
        rv = PyBytes_AsStringAndSize(bytesobj, (char**)buf, &plen);
    }

    if (rv < 0) {
        Py_DECREF(bytesobj);
        PYCBC_EXC_WRAP(PYCBC_EXC_ENCODING, 0, "Couldn't encode value");
        return -1;
    }

    *nbuf = plen;
    *o = bytesobj;
    return 0;
}

static int
decode_common(PyObject **vp, const char *buf, size_t nbuf, lcb_uint32_t flags)
{
    PyObject *decoded = NULL;
    lcb_U32 c_flags, l_flags;

    c_flags = flags & PYCBC_FMT_COMMON_MASK;
    l_flags = flags & PYCBC_FMT_LEGACY_MASK;

    #define FMT_MATCHES(fmtbase) \
        (c_flags == PYCBC_FMT_COMMON_##fmtbase || l_flags == PYCBC_FMT_LEGACY_##fmtbase)

    if (FMT_MATCHES(UTF8)) {
        decoded = convert_to_string(buf, nbuf, CONVERT_MODE_UTF8_ONLY);
        if (!decoded) {
            return -1;
        }

    } else if (FMT_MATCHES(BYTES)) {
        GT_BYTES:
        decoded = convert_to_string(buf, nbuf, CONVERT_MODE_BYTES_ONLY);
        pycbc_assert(decoded);

    } else {
        PyObject *converter = NULL;
        PyObject *args = NULL;
        PyObject *first_arg = NULL;

        if (FMT_MATCHES(PICKLE)) {
            converter = pycbc_helpers.pickle_decode;
            first_arg = convert_to_string(buf, nbuf, CONVERT_MODE_BYTES_ONLY);
            pycbc_assert(first_arg);

        } else if (FMT_MATCHES(JSON)) {
            converter = pycbc_helpers.json_decode;
            first_arg = convert_to_string(buf, nbuf, CONVERT_MODE_UTF8_ONLY);

            if (!first_arg) {
                return -1;
            }

        } else {
            PyErr_Warn(PyExc_UserWarning, "Unrecognized flags. Forcing bytes");
            goto GT_BYTES;
        }

        pycbc_assert(first_arg);
        args = PyTuple_Pack(1, first_arg);
        decoded = PyObject_CallObject(converter, args);

        Py_DECREF(args);
        Py_DECREF(first_arg);
    }

    if (!decoded) {
        PyObject *bytes_tmp = PyBytes_FromStringAndSize(buf, nbuf);
        PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Failed to decode bytes",
                           bytes_tmp);
        Py_XDECREF(bytes_tmp);
        return -1;
    }

    *vp = decoded;
    return 0;

    #undef FMT_MATCHES
}
Exemplo n.º 28
0
static PyObject *
pyhashxx_hashxx(PyObject* self, PyObject *args, PyObject *kwds)
{
    unsigned int seed = 0;
    const char* err_msg = NULL;
    PyObject* err_obj = NULL;
    Py_ssize_t args_len = 0;
    unsigned int digest = 0;
    void* state = NULL;

    if (kwds != NULL) {
        Py_ssize_t kwds_size = PyDict_Size(kwds);
        PyObject* seed_obj = PyDict_GetItemString(kwds, "seed");

        if (kwds_size > 1) {
            err_msg = "Unexpected keyword arguments, only 'seed' is supported.";
            goto badarg;
        }

        if (kwds_size == 1) {
            if (seed_obj == NULL) {
                err_msg = "Unexpected keyword argument, only 'seed' is supported.";
                goto badarg;
            }
#if PY_MAJOR_VERSION < 3
            if (PyInt_Check(seed_obj))
                seed = PyInt_AsLong(seed_obj);
            else
#endif
                if (PyLong_Check(seed_obj))
                seed = PyLong_AsLong(seed_obj);
            else {
                err_msg = "Unexpected seed value type: %S";
                err_obj = seed_obj;
                goto badseed;
            }
        }
    }
    args_len = PyTuple_GET_SIZE(args);
    if (args_len == 0) {
        err_msg = "Received no arguments to be hashed.";
        goto badarg;
    }

    // If possible, use the shorter, faster version that elides
    // allocating the state variable because it knows there is only
    // one input.
    if (args_len == 1) {
        PyObject* hash_obj = PyTuple_GetItem(args, 0);
        int did_hash = 1;
#if PY_MAJOR_VERSION >= 3
        if (PyBytes_Check(hash_obj)) {
            digest = XXH32(PyBytes_AsString(hash_obj), PyBytes_Size(hash_obj), seed);
        }
#else
        if (PyString_Check(hash_obj)) {
            digest = XXH32(PyString_AsString(hash_obj), PyString_Size(hash_obj), seed);
        }
#endif
        else if (PyByteArray_Check(hash_obj)) {
            digest = XXH32(PyByteArray_AsString(hash_obj), PyByteArray_Size(hash_obj), seed);
        }
        else if (hash_obj == Py_None) {
            // Nothing to hash
            digest = XXH32("", 0, seed);
        }
        else {
            did_hash = 0;
        }

        if (did_hash)
            return Py_BuildValue("I", digest);
    }

    // Otherwise, do it the long, slower way
    state = XXH32_init(seed);
    if (_update_hash(state, args) == NULL) {
        XXH32_destroy(state);
        return NULL;
    }
    digest = XXH32_digest(state);
    XXH32_destroy(state);

    return Py_BuildValue("I", digest);

badarg:
    PyErr_SetString(PyExc_TypeError, err_msg);
    return NULL;
badseed:
    PyErr_Format(PyExc_TypeError, err_msg, Py_TYPE(err_obj));
    return NULL;
}
Exemplo n.º 29
0
static nxweb_result python_on_request(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) {
  nxb_buffer* nxb=req->nxb;
  nxweb_handler* handler=conn->handler;
  const char* request_uri=req->uri;
  char* query_string=strchr(request_uri, '?');
  int ulen=query_string? (query_string-request_uri) : strlen(request_uri);
  if (query_string) query_string++;
  int pfxlen=req->path_info? (req->path_info - req->uri) : 0;
  int plen=ulen-pfxlen;
  const char* path_info=request_uri+pfxlen;
  if (handler->uri && *handler->uri) {
    pfxlen=strlen(handler->uri);
    ulen=pfxlen+plen;
    char* u=nxb_alloc_obj(nxb, ulen+1);
    memcpy(u, handler->uri, pfxlen);
    memcpy(u+pfxlen, path_info, plen);
    u[ulen]='\0';
    request_uri=u;
    path_info=request_uri+pfxlen;
  }
  const char* host_port=req->host? strchr(req->host, ':') : 0;

  int content_fd=0;

  if (req->content_length) {
    nxd_fwbuffer* fwb=nxweb_get_request_data(req, PYTHON_HANDLER_KEY).ptr;

    if (fwb) {
      if (fwb->error || fwb->size > fwb->max_size) {
        nxweb_send_http_error(resp, 413, "Request Entity Too Large"); // most likely cause
        return NXWEB_ERROR;
      }
      else if (req->content_received!=fwb->size) {
        nxweb_log_error("content_received does not match upload stored size for %s", req->uri);
        nxweb_send_http_error(resp, 500, "Internal Server Error");
        return NXWEB_ERROR;
      }
      else {
        content_fd=fwb->fd;
        if (lseek(content_fd, 0, SEEK_SET)==-1) {
          nxweb_log_error("can't lseek() temp upload file for %s", req->uri);
          nxweb_send_http_error(resp, 500, "Internal Server Error");
          return NXWEB_ERROR;
        }
      }
    }
  }


  nxweb_log_debug("invoke python");

  PyGILState_STATE gstate=PyGILState_Ensure();

  PyObject* py_func_args=PyTuple_New(1);
  PyObject* py_environ=PyDict_New();
  assert(PyDict_Check(py_environ));

  dict_set(py_environ, "SERVER_NAME", PyString_FromStringAndSize(req->host, host_port? (host_port-req->host) : strlen(req->host)));
  dict_set(py_environ, "SERVER_PORT", PyString_FromString(host_port? host_port+1 : ""));
  dict_set(py_environ, "SERVER_PROTOCOL", PyString_FromString(req->http11? "HTTP/1.1" : "HTTP/1.0"));
  dict_set(py_environ, "SERVER_SOFTWARE", PyString_FromString(PACKAGE_STRING));
  dict_set(py_environ, "GATEWAY_INTERFACE", PyString_FromString("CGI/1.1"));
  dict_set(py_environ, "REQUEST_METHOD", PyString_FromString(req->method));
  dict_set(py_environ, "REQUEST_URI", PyString_FromStringAndSize(request_uri, ulen));
  dict_set(py_environ, "SCRIPT_NAME", PyString_FromStringAndSize(request_uri, pfxlen));
  dict_set(py_environ, "PATH_INFO", PyString_FromStringAndSize(path_info, plen));
  dict_set(py_environ, "QUERY_STRING", PyString_FromString(query_string? query_string : ""));
  dict_set(py_environ, "REMOTE_ADDR", PyString_FromString(conn->remote_addr));
  dict_set(py_environ, "CONTENT_TYPE", PyString_FromString(req->content_type? req->content_type : ""));
  dict_set(py_environ, "CONTENT_LENGTH", PyInt_FromLong(req->content_received));
  if (req->cookie) dict_set(py_environ, "HTTP_COOKIE", PyString_FromString(req->cookie));
  if (req->host) dict_set(py_environ, "HTTP_HOST", PyString_FromString(req->host));
  if (req->user_agent) dict_set(py_environ, "HTTP_USER_AGENT", PyString_FromString(req->user_agent));
  if (req->if_modified_since) {
    struct tm tm;
    gmtime_r(&req->if_modified_since, &tm);
    char ims[32];
    nxweb_format_http_time(ims, &tm);
    dict_set(py_environ, "HTTP_IF_MODIFIED_SINCE", PyString_FromString(ims));
  }

  if (req->headers) {
    // write added headers
    // encode http headers into CGI variables; see 4.1.18 in https://tools.ietf.org/html/rfc3875
    char hname[256];
    memcpy(hname, "HTTP_", 5);
    char* h=hname+5;
    nx_simple_map_entry* itr;
    for (itr=nx_simple_map_itr_begin(req->headers); itr; itr=nx_simple_map_itr_next(itr)) {
      nx_strtoupper(h, itr->name);
      char* p;
      for (p=h; *p; p++) {
        if (*p=='-') *p='_';
      }
      dict_set(py_environ, hname, PyString_FromString(itr->value));
    }
  }

  dict_set(py_environ, "wsgi.url_scheme", PyString_FromString(conn->secure? "https" : "http"));

  if (req->content_length) {
    if (content_fd) {
      dict_set(py_environ, "nxweb.req.content_fd", PyInt_FromLong(content_fd));
    }
    else {
      dict_set(py_environ, "nxweb.req.content", PyByteArray_FromStringAndSize(req->content? req->content : "", req->content_received));
    }
  }
  if (req->if_modified_since) dict_set(py_environ, "nxweb.req.if_modified_since", PyLong_FromLong(req->if_modified_since));
  dict_set(py_environ, "nxweb.req.uid", PyLong_FromLongLong(req->uid));
  if (req->parent_req) {
    nxweb_http_request* preq=req->parent_req;
    while (preq->parent_req) preq=preq->parent_req; // find root request
    if (preq->uid) {
      dict_set(py_environ, "nxweb.req.root_uid", PyLong_FromLongLong(preq->uid));
    }
  }

  // call python
  PyTuple_SetItem(py_func_args, 0, py_environ);
  PyObject* py_result=PyObject_CallObject(py_nxweb_on_request_func, py_func_args);
  Py_DECREF(py_func_args);
  if (py_result && PyTuple_Check(py_result) && PyTuple_Size(py_result)==3) {
    PyObject* py_status=PyTuple_GET_ITEM(py_result, 0);
    PyObject* py_headers=PyTuple_GET_ITEM(py_result, 1);
    PyObject* py_body=PyTuple_GET_ITEM(py_result, 2);

    if (py_status && PyString_Check(py_status)) {
      const char* status_string=PyString_AS_STRING(py_status);
      int status_code=0;
      const char* p=status_string;
      while (*p && *p>='0' && *p<='9') {
        status_code=status_code*10+(*p-'0');
        p++;
      }
      while (*p && *p==' ') p++;
      if (status_code>=200 && status_code<600 && *p) {
        resp->status_code=status_code;
        resp->status=nxb_copy_str(nxb, p);
      }
    }

    if (py_headers && PyList_Check(py_headers)) {
      const int size=PyList_Size(py_headers);
      int i;
      for (i=0; i<size; i++) {
        PyObject* py_header_tuple=PyList_GET_ITEM(py_headers, i);
        if (py_header_tuple && PyTuple_Check(py_header_tuple) && PyTuple_Size(py_header_tuple)==2) {
          PyObject* py_name=PyTuple_GET_ITEM(py_header_tuple, 0);
          PyObject* py_value=PyTuple_GET_ITEM(py_header_tuple, 1);
          if (py_name && PyString_Check(py_name) && py_value && PyString_Check(py_value)) {
            nxweb_add_response_header_safe(resp, PyString_AS_STRING(py_name), PyString_AS_STRING(py_value));
          }
        }
      }
    }

    if ((!resp->status_code || resp->status_code==200) && !resp->content_type) resp->content_type="text/html";

    char* rcontent=0;
    nxe_ssize_t rsize=0;
    if (PyByteArray_Check(py_body)) {
      rcontent=PyByteArray_AS_STRING(py_body);
      rsize=PyByteArray_Size(py_body);
    }
    else if (PyString_Check(py_body)) {
      rcontent=PyString_AS_STRING(py_body);
      rsize=PyString_Size(py_body);
    }
    if (rcontent && rsize>0) nxweb_response_append_data(resp, rcontent, rsize);
  }
  else if (py_result && PyString_Check(py_result)) {
    resp->status_code=500;
    resp->status="Internal Server Error";
    resp->content_type="text/html";
    nxweb_log_error("python call failed: %s", PyString_AS_STRING(py_result));
    nxweb_response_printf(resp, "python call failed: %H", PyString_AS_STRING(py_result));
  }
  else {
    PyErr_Print();
    nxweb_log_error("python call failed");
    nxweb_response_printf(resp, "python call failed");
  }
  Py_XDECREF(py_result);

  // Release the thread. No Python API allowed beyond this point.
  PyGILState_Release(gstate);

  nxweb_log_debug("invoke python complete");

  return NXWEB_OK;
}
Exemplo n.º 30
0
QImage
QPythonImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    QImage img;

    // Image data (and metadata) returned from Python
    PyObject *pixels = NULL;
    int width = 0, height = 0;
    int format = 0;

    // For counting the number of required bytes
    int bitsPerPixel = 0;
    size_t requiredBytes = 0;
    size_t actualBytes = 0;

    QPythonPriv *priv = QPythonPriv::instance();
    if (!priv) {
        qWarning() << "Python component not instantiated yet";
        return QImage();
    }

    if (!priv->image_provider) {
        qWarning() << "No image provider set in Python code";
        return QImage();
    }

    QByteArray id_utf8 = id.toUtf8();

    // Image provider implementation in Python:
    //
    // import pyotherside
    //
    // def image_provider(image_id, requested_size):
    //     if requested_size == (-1, -1):
    //         requested_size = 100, 200 # some sane default size
    //     width, height = requested_size
    //     pixels = ...
    //     format = pyotherside.format_argb32 # or some other format
    //     return (bytearray(pixels), (width, height), format)
    //
    // pyotherside.set_image_provider(image_provider)

    ENSURE_GIL_STATE;

    PyObjectRef args(Py_BuildValue("(N(ii))",
            PyUnicode_FromString(id_utf8.constData()),
            requestedSize.width(), requestedSize.height()), true);
    PyObjectRef result(PyObject_Call(priv->image_provider.borrow(), args.borrow(), NULL), true);

    if (!result) {
        qDebug() << "Error while calling the image provider";
        PyErr_Print();
        goto cleanup;
    }

    if (!PyArg_ParseTuple(result.borrow(), "O(ii)i", &pixels, &width, &height, &format)) {
        PyErr_Clear();
        qDebug() << "Image provider must return (pixels, (width, height), format)";
        goto cleanup;
    }

    if (!PyByteArray_Check(pixels)) {
        qDebug() << "Image data must be a Python bytearray()";
        goto cleanup;
    }

    switch (format) {
        case PYOTHERSIDE_IMAGE_FORMAT_ENCODED: /* pyotherside.format_data */
            break;
        case PYOTHERSIDE_IMAGE_FORMAT_SVG: /* pyotherside.format_svg_data */
            break;
        case QImage::Format_Mono:
        case QImage::Format_MonoLSB:
            bitsPerPixel = 1;
            break;
        case QImage::Format_RGB32:
        case QImage::Format_ARGB32:
            bitsPerPixel = 32;
            break;
        case QImage::Format_RGB16:
        case QImage::Format_RGB555:
        case QImage::Format_RGB444:
            bitsPerPixel = 16;
            break;
        case QImage::Format_RGB666:
        case QImage::Format_RGB888:
            bitsPerPixel = 24;
            break;
        default:
            qDebug() << "Invalid format:" << format;
            goto cleanup;
    }

    requiredBytes = (bitsPerPixel * width * height + 7) / 8;
    actualBytes = PyByteArray_Size(pixels);

    // QImage requires scanlines to be 32-bit aligned. Scanlines from Python
    // are considered to be tightly packed, we have to check for alignment.
    // While we could re-pack the data to be aligned, we don't want to do that
    // for performance reasons.
    // If we're using 32-bit data (e.g. ARGB32), it will always be aligned.
    if (format >= 0 && bitsPerPixel != 32) {
        if ((bitsPerPixel * width) % 32 != 0) {
            // If actualBytes > requiredBytes, we can check if there are enough
            // bytes to consider the data 32-bit aligned (from Python) and avoid
            // the error (scanlines must be padded to multiples of 4 bytes)
            if ((unsigned int)(((width * bitsPerPixel / 8 + 3) / 4) * 4 * height) == actualBytes) {
                qDebug() << "Assuming 32-bit aligned scanlines from Python";
            } else {
                qDebug() << "Each scanline of data must be 32-bit aligned";
                goto cleanup;
            }
        }
    }

    if (format >= 0 && requiredBytes > actualBytes) {
        qDebug() << "Format" << (enum QImage::Format)format <<
            "at size" << QSize(width, height) <<
            "requires at least" << requiredBytes <<
            "bytes of image data, got only" << actualBytes << "bytes";
        goto cleanup;
    }

    if (format < 0) {
        switch (format) {
        case PYOTHERSIDE_IMAGE_FORMAT_ENCODED: {
            // Pixel data is actually encoded image data that we need to decode
            img.loadFromData((const unsigned char*)PyByteArray_AsString(pixels), PyByteArray_Size(pixels));
            break;
        }
        case PYOTHERSIDE_IMAGE_FORMAT_SVG: {
            // Convert the Python byte array to a QByteArray
            QByteArray svgDataArray(PyByteArray_AsString(pixels), PyByteArray_Size(pixels));

            // Load the SVG data to the SVG renderer
            QSvgRenderer renderer(svgDataArray);

            // Handle width, height or both not being set
            QSize defaultSize = renderer.defaultSize();
            int defaultWidth = defaultSize.width();
            int defaultHeight = defaultSize.height();

            if (width < 0 && height < 0) {
                // Both Width and Height have not been set - use the defaults from the SVG data
                // (each SVG image has a default size)
                // NOTE: we get a -1,-1 requestedSize only if sourceSize is not set at all,
                //       if either width or height is set then the other one is 0, not -1
                width = defaultWidth;
                height = defaultHeight;
            } else { // At least width or height is valid
                if (width <= 0) {
                    // Width is not set, use default width scaled according to height to keep
                    // aspect ratio
                    if (defaultHeight != 0) {  // Protect from division by zero
                        width = (float)defaultWidth*((float)height/(float)defaultHeight);
                    }
                }

                if (height <= 0) {
                    // Height is not set, use default height scaled according to width to keep
                    // aspect ratio
                    if (defaultWidth != 0) {  // Protect from division by zero
                        height = (float)defaultHeight*((float)width/(float)defaultWidth);
                    }
                }
            }

            // The pixel data is actually SVG image data that we need to render at correct size
            //
            // Note: according to the QImage and QPainter documentation the optimal QImage
            // format for drawing is Format_ARGB32_Premultiplied
            img = QImage(width, height, QImage::Format_ARGB32_Premultiplied);

            // According to the documentation an empty QImage needs to be "flushed" before
            // being used with QPainter to prevent rendering artifacts from showing up
            img.fill(Qt::transparent);

            // Paints the rendered SVG to the QImage instance
            QPainter painter(&img);
            renderer.render(&painter);
            break;
        }
        default:
            qWarning() << "Unknown format" << format <<
                "has been specified and will not be handled.";
            break;
        }
    } else {
        // Need to keep a reference to the byte array object, as it contains
        // the backing store data for the QImage.
        // Will be decref'd by cleanup_python_qimage once the QImage is gone.
        Py_INCREF(pixels);

        img = QImage((const unsigned char *)PyByteArray_AsString(pixels),
                width, height, (enum QImage::Format)format,
                cleanup_python_qimage, pixels);
    }

cleanup:

    *size = img.size();
    return img;
}