Convert unicode objects to utf-8 encoded G_STRINGs

This commit is contained in:
Thomas Vander Stichele 2009-06-01 19:08:47 +02:00
parent eb3701dfe5
commit 88f3323bfe
3 changed files with 127 additions and 82 deletions

View file

@ -38,7 +38,7 @@ static PyObject *gstfractionrange_class = NULL;
* Returns 1 if none other found. * Returns 1 if none other found.
* This is Euclid's algorithm. */ * This is Euclid's algorithm. */
static long static long
my_gcd(long num, long denom) my_gcd (long num, long denom)
{ {
while (denom != 0) { while (denom != 0) {
long temp = num; long temp = num;
@ -61,73 +61,81 @@ my_gcd(long num, long denom)
* Returns: a PyObject representing the value. * Returns: a PyObject representing the value.
*/ */
PyObject * PyObject *
pygst_value_as_pyobject(const GValue *value, gboolean copy_boxed) pygst_value_as_pyobject (const GValue * value, gboolean copy_boxed)
{ {
PyObject *ret = pyg_value_as_pyobject(value, copy_boxed); PyObject *ret = pyg_value_as_pyobject (value, copy_boxed);
if (!ret) { if (!ret) {
PyErr_Clear(); PyErr_Clear ();
if (GST_VALUE_HOLDS_FOURCC (value)) { if (GST_VALUE_HOLDS_FOURCC (value)) {
gchar str[5]; gchar str[5];
g_snprintf (str, 5, "%"GST_FOURCC_FORMAT, g_snprintf (str, 5, "%" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (gst_value_get_fourcc (value))); GST_FOURCC_ARGS (gst_value_get_fourcc (value)));
ret = PyObject_Call (gstfourcc_class, Py_BuildValue ("(s)", str), NULL); ret = PyObject_Call (gstfourcc_class, Py_BuildValue ("(s)", str), NULL);
} else if (GST_VALUE_HOLDS_INT_RANGE (value)) { } else if (GST_VALUE_HOLDS_INT_RANGE (value)) {
ret = PyObject_Call ret = PyObject_Call
(gstintrange_class, (gstintrange_class,
Py_BuildValue ("ii", Py_BuildValue ("ii",
gst_value_get_int_range_min (value), gst_value_get_int_range_min (value),
gst_value_get_int_range_max (value)), gst_value_get_int_range_max (value)), NULL);
NULL);
} else if (GST_VALUE_HOLDS_DOUBLE_RANGE (value)) { } else if (GST_VALUE_HOLDS_DOUBLE_RANGE (value)) {
ret = PyObject_Call ret = PyObject_Call
(gstdoublerange_class, (gstdoublerange_class,
Py_BuildValue ("dd", Py_BuildValue ("dd",
gst_value_get_double_range_min (value), gst_value_get_double_range_min (value),
gst_value_get_double_range_max (value)), gst_value_get_double_range_max (value)), NULL);
NULL);
} else if (GST_VALUE_HOLDS_LIST (value)) { } else if (GST_VALUE_HOLDS_LIST (value)) {
int i, len; int i, len;
len = gst_value_list_get_size (value); len = gst_value_list_get_size (value);
ret = PyList_New (len); ret = PyList_New (len);
for (i=0; i<len; i++) { for (i = 0; i < len; i++) {
PyList_SetItem (ret, i, PyList_SetItem (ret, i,
pygst_value_as_pyobject pygst_value_as_pyobject
(gst_value_list_get_value (value, i), copy_boxed)); (gst_value_list_get_value (value, i), copy_boxed));
} }
} else if (GST_VALUE_HOLDS_ARRAY (value)) { } else if (GST_VALUE_HOLDS_ARRAY (value)) {
int i, len; int i, len;
len = gst_value_array_get_size (value); len = gst_value_array_get_size (value);
ret = PyTuple_New (len); ret = PyTuple_New (len);
for (i=0; i<len; i++) { for (i = 0; i < len; i++) {
PyTuple_SetItem (ret, i, PyTuple_SetItem (ret, i,
pygst_value_as_pyobject pygst_value_as_pyobject
(gst_value_array_get_value (value, i), copy_boxed)); (gst_value_array_get_value (value, i), copy_boxed));
} }
} else if (GST_VALUE_HOLDS_FRACTION (value)) { } else if (GST_VALUE_HOLDS_FRACTION (value)) {
ret = PyObject_Call ret = PyObject_Call
(gstfraction_class, (gstfraction_class,
Py_BuildValue ("ii", Py_BuildValue ("ii",
gst_value_get_fraction_numerator (value), gst_value_get_fraction_numerator (value),
gst_value_get_fraction_denominator (value)), gst_value_get_fraction_denominator (value)), NULL);
NULL);
} else if (GST_VALUE_HOLDS_FRACTION_RANGE (value)) { } else if (GST_VALUE_HOLDS_FRACTION_RANGE (value)) {
const GValue *min, *max; const GValue *min, *max;
min = gst_value_get_fraction_range_min (value); min = gst_value_get_fraction_range_min (value);
max = gst_value_get_fraction_range_max (value); max = gst_value_get_fraction_range_max (value);
ret = PyObject_Call ret = PyObject_Call
(gstfractionrange_class, (gstfractionrange_class,
Py_BuildValue ("OO", Py_BuildValue ("OO",
pygst_value_as_pyobject (min, copy_boxed), pygst_value_as_pyobject (min, copy_boxed),
pygst_value_as_pyobject (max, copy_boxed)), pygst_value_as_pyobject (max, copy_boxed)), NULL);
NULL);
} else if (GST_VALUE_HOLDS_BUFFER (value)) { } else if (GST_VALUE_HOLDS_BUFFER (value)) {
return pygstminiobject_new (gst_value_get_mini_object (value)); return pygstminiobject_new (gst_value_get_mini_object (value));
} else { } else {
gchar buf[256]; gchar buf[256];
g_snprintf (buf, 256, "unknown type: %s", g_type_name (G_VALUE_TYPE (value))); g_snprintf (buf, 256, "unknown type: %s",
PyErr_SetString(PyExc_TypeError, buf); g_type_name (G_VALUE_TYPE (value)));
PyErr_SetString (PyExc_TypeError, buf);
} }
} }
if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
PyObject *u = NULL;
/* FIXME: docs are not clear on whether this sets a python
exception when it fails */
u = PyUnicode_FromEncodedObject (ret, "utf-8", NULL);
Py_DECREF (ret);
ret = u;
}
return ret; return ret;
} }
@ -142,11 +150,11 @@ if (!G_VALUE_HOLDS (v, t)) {\
}}G_STMT_END }}G_STMT_END
gboolean gboolean
pygst_value_init_for_pyobject (GValue *value, PyObject *obj) pygst_value_init_for_pyobject (GValue * value, PyObject * obj)
{ {
GType t; GType t;
if (!(t = pyg_type_from_object ((PyObject*)obj->ob_type))) { if (!(t = pyg_type_from_object ((PyObject *) obj->ob_type))) {
if (PyObject_IsInstance (obj, gstvalue_class)) { if (PyObject_IsInstance (obj, gstvalue_class)) {
PyErr_Clear (); PyErr_Clear ();
if (PyObject_IsInstance (obj, gstfourcc_class)) if (PyObject_IsInstance (obj, gstfourcc_class))
@ -158,12 +166,12 @@ pygst_value_init_for_pyobject (GValue *value, PyObject *obj)
else if (PyObject_IsInstance (obj, gstfraction_class)) else if (PyObject_IsInstance (obj, gstfraction_class))
t = GST_TYPE_FRACTION; t = GST_TYPE_FRACTION;
else if (PyObject_IsInstance (obj, gstfractionrange_class)) else if (PyObject_IsInstance (obj, gstfractionrange_class))
t = GST_TYPE_FRACTION_RANGE; t = GST_TYPE_FRACTION_RANGE;
else { else {
PyErr_SetString(PyExc_TypeError, "Unexpected gst.Value instance"); PyErr_SetString (PyExc_TypeError, "Unexpected gst.Value instance");
return FALSE; return FALSE;
} }
} else if (PyObject_IsInstance (obj, (PyObject *)&PyGstMiniObject_Type)) { } else if (PyObject_IsInstance (obj, (PyObject *) & PyGstMiniObject_Type)) {
PyErr_Clear (); PyErr_Clear ();
t = GST_TYPE_MINI_OBJECT; t = GST_TYPE_MINI_OBJECT;
} else if (PyTuple_Check (obj)) { } else if (PyTuple_Check (obj)) {
@ -172,6 +180,10 @@ pygst_value_init_for_pyobject (GValue *value, PyObject *obj)
} else if (PyList_Check (obj)) { } else if (PyList_Check (obj)) {
PyErr_Clear (); PyErr_Clear ();
t = GST_TYPE_LIST; t = GST_TYPE_LIST;
} else if (PyUnicode_Check (obj)) {
/* unicode strings should be converted to UTF-8 */
PyErr_Clear ();
t = G_TYPE_STRING;
} else { } else {
/* pyg_type_from_object already set the error */ /* pyg_type_from_object already set the error */
return FALSE; return FALSE;
@ -194,10 +206,19 @@ pygst_value_init_for_pyobject (GValue *value, PyObject *obj)
* Returns: 0 on success, -1 on error. * Returns: 0 on success, -1 on error.
*/ */
int int
pygst_value_from_pyobject (GValue *value, PyObject *obj) pygst_value_from_pyobject (GValue * value, PyObject * obj)
{ {
GType f = g_type_fundamental (G_VALUE_TYPE (value)); GType f = g_type_fundamental (G_VALUE_TYPE (value));
/* Unicode objects should be converted to utf-8 strings */
if (PyObject_TypeCheck (obj, &PyUnicode_Type)) {
PyObject *v;
v = PyUnicode_AsUTF8String (obj);
Py_DECREF (obj);
obj = v;
}
/* work around a bug in pygtk whereby pyg_value_from_pyobject claims success /* work around a bug in pygtk whereby pyg_value_from_pyobject claims success
for unknown fundamental types without actually doing anything */ for unknown fundamental types without actually doing anything */
if (f < G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST) if (f < G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST)
@ -228,7 +249,7 @@ pygst_value_from_pyobject (GValue *value, PyObject *obj)
return -1; return -1;
high = PyInt_AsLong (pyval); high = PyInt_AsLong (pyval);
g_assert (G_MININT <= high && high <= G_MAXINT); g_assert (G_MININT <= high && high <= G_MAXINT);
gst_value_set_int_range (value, (int)low, (int)high); gst_value_set_int_range (value, (int) low, (int) high);
} else if (PyObject_IsInstance (obj, gstdoublerange_class)) { } else if (PyObject_IsInstance (obj, gstdoublerange_class)) {
PyObject *pyval; PyObject *pyval;
double low, high; double low, high;
@ -248,53 +269,53 @@ pygst_value_from_pyobject (GValue *value, PyObject *obj)
if (!(pyval = PyObject_GetAttrString (obj, "num"))) if (!(pyval = PyObject_GetAttrString (obj, "num")))
return -1; return -1;
num = PyInt_AsLong (pyval); num = PyInt_AsLong (pyval);
if ((num == -1) && PyErr_Occurred()) if ((num == -1) && PyErr_Occurred ())
return -1; return -1;
g_assert (G_MININT <= num && num <= G_MAXINT); g_assert (G_MININT <= num && num <= G_MAXINT);
if (!(pyval = PyObject_GetAttrString (obj, "denom"))) if (!(pyval = PyObject_GetAttrString (obj, "denom")))
return -1; return -1;
denom = PyInt_AsLong (pyval); denom = PyInt_AsLong (pyval);
if ((denom == -1) && PyErr_Occurred()) if ((denom == -1) && PyErr_Occurred ())
return -1; return -1;
/* we need to reduce the values to be smaller than MAXINT */ /* we need to reduce the values to be smaller than MAXINT */
if ((gcd = my_gcd(num, denom))) { if ((gcd = my_gcd (num, denom))) {
num /= gcd; num /= gcd;
denom /= gcd; denom /= gcd;
} }
g_assert (G_MININT <= denom && denom <= G_MAXINT); g_assert (G_MININT <= denom && denom <= G_MAXINT);
gst_value_set_fraction (value, (int)num, (int)denom); gst_value_set_fraction (value, (int) num, (int) denom);
} else if (PyObject_IsInstance (obj, gstfractionrange_class)) { } else if (PyObject_IsInstance (obj, gstfractionrange_class)) {
GValue low = {0, }; GValue low = { 0, };
GValue high = {0, }; GValue high = { 0, };
PyObject *pylow, *pyhigh; PyObject *pylow, *pyhigh;
VALUE_TYPE_CHECK (value, GST_TYPE_FRACTION_RANGE); VALUE_TYPE_CHECK (value, GST_TYPE_FRACTION_RANGE);
if (!(pylow = PyObject_GetAttrString (obj, "low"))) if (!(pylow = PyObject_GetAttrString (obj, "low")))
return -1; return -1;
if (!pygst_value_init_for_pyobject (&low, pylow)) if (!pygst_value_init_for_pyobject (&low, pylow))
return -1; return -1;
if (pygst_value_from_pyobject (&low, pylow) != 0) if (pygst_value_from_pyobject (&low, pylow) != 0)
return -1; return -1;
if (!(pyhigh = PyObject_GetAttrString (obj, "high"))) if (!(pyhigh = PyObject_GetAttrString (obj, "high")))
return -1; return -1;
if (!pygst_value_init_for_pyobject (&high, pyhigh)) if (!pygst_value_init_for_pyobject (&high, pyhigh))
return -1; return -1;
if (pygst_value_from_pyobject (&high, pyhigh) != 0) if (pygst_value_from_pyobject (&high, pyhigh) != 0)
return -1; return -1;
gst_value_set_fraction_range (value, &low, &high); gst_value_set_fraction_range (value, &low, &high);
} else { } else {
gchar buf[256]; gchar buf[256];
gchar *str = PyString_AsString (PyObject_Repr(obj)); gchar *str = PyString_AsString (PyObject_Repr (obj));
g_snprintf(buf, 256, "Unknown gst.Value type: %s", str); g_snprintf (buf, 256, "Unknown gst.Value type: %s", str);
PyErr_SetString(PyExc_TypeError, buf); PyErr_SetString (PyExc_TypeError, buf);
return -1; return -1;
} }
return 0; return 0;
} else if (PyObject_IsInstance (obj, (PyObject *)&PyGstMiniObject_Type)) { } else if (PyObject_IsInstance (obj, (PyObject *) & PyGstMiniObject_Type)) {
VALUE_TYPE_CHECK (value, GST_TYPE_MINI_OBJECT); VALUE_TYPE_CHECK (value, GST_TYPE_MINI_OBJECT);
gst_value_set_mini_object (value, pygstminiobject_get(obj)); gst_value_set_mini_object (value, pygstminiobject_get (obj));
return 0; return 0;
} else if (PyTuple_Check (obj)) { } else if (PyTuple_Check (obj)) {
gint i, len; gint i, len;
@ -303,7 +324,7 @@ pygst_value_from_pyobject (GValue *value, PyObject *obj)
len = PyTuple_Size (obj); len = PyTuple_Size (obj);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
PyObject *o; PyObject *o;
GValue new = {0,}; GValue new = { 0, };
o = PyTuple_GetItem (obj, i); o = PyTuple_GetItem (obj, i);
if (!pygst_value_init_for_pyobject (&new, o)) if (!pygst_value_init_for_pyobject (&new, o))
return -1; return -1;
@ -322,7 +343,7 @@ pygst_value_from_pyobject (GValue *value, PyObject *obj)
len = PyList_Size (obj); len = PyList_Size (obj);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
PyObject *o; PyObject *o;
GValue new = {0,}; GValue new = { 0, };
o = PyList_GetItem (obj, i); o = PyList_GetItem (obj, i);
if (!pygst_value_init_for_pyobject (&new, o)) if (!pygst_value_init_for_pyobject (&new, o))
return -1; return -1;
@ -342,31 +363,33 @@ pygst_value_from_pyobject (GValue *value, PyObject *obj)
#define NULL_CHECK(o) if (!o) goto err #define NULL_CHECK(o) if (!o) goto err
gboolean gboolean
pygst_value_init(void) pygst_value_init (void)
{ {
PyObject *module, *dict; PyObject *module, *dict;
if ((module = PyImport_ImportModule("gst")) == NULL) if ((module = PyImport_ImportModule ("gst")) == NULL)
return FALSE; return FALSE;
dict = PyModule_GetDict (module); dict = PyModule_GetDict (module);
gstvalue_class = (PyObject*)PyDict_GetItemString (dict, "Value"); gstvalue_class = (PyObject *) PyDict_GetItemString (dict, "Value");
NULL_CHECK (gstvalue_class); NULL_CHECK (gstvalue_class);
gstfourcc_class = (PyObject*)PyDict_GetItemString (dict, "Fourcc"); gstfourcc_class = (PyObject *) PyDict_GetItemString (dict, "Fourcc");
NULL_CHECK (gstfourcc_class); NULL_CHECK (gstfourcc_class);
gstintrange_class = (PyObject*)PyDict_GetItemString (dict, "IntRange"); gstintrange_class = (PyObject *) PyDict_GetItemString (dict, "IntRange");
NULL_CHECK (gstintrange_class); NULL_CHECK (gstintrange_class);
gstdoublerange_class = (PyObject*)PyDict_GetItemString (dict, "DoubleRange"); gstdoublerange_class =
(PyObject *) PyDict_GetItemString (dict, "DoubleRange");
NULL_CHECK (gstdoublerange_class); NULL_CHECK (gstdoublerange_class);
gstfraction_class = (PyObject*)PyDict_GetItemString (dict, "Fraction"); gstfraction_class = (PyObject *) PyDict_GetItemString (dict, "Fraction");
NULL_CHECK (gstfraction_class); NULL_CHECK (gstfraction_class);
gstfractionrange_class = (PyObject*)PyDict_GetItemString (dict, "FractionRange"); gstfractionrange_class =
(PyObject *) PyDict_GetItemString (dict, "FractionRange");
NULL_CHECK (gstfractionrange_class); NULL_CHECK (gstfractionrange_class);
return TRUE; return TRUE;
err: err:
PyErr_SetString (PyExc_ImportError, PyErr_SetString (PyExc_ImportError,
"Failed to get GstValue classes from gst module"); "Failed to get GstValue classes from gst module");
return FALSE; return FALSE;
} }

View file

@ -44,11 +44,11 @@ class StructureTest(TestCase):
def testString(self): def testString(self):
assert self.struct.has_key('foo') assert self.struct.has_key('foo')
assert isinstance(self.struct['foo'], str) assert isinstance(self.struct['foo'], unicode)
assert self.struct['foo'] == 'bar', self.struct['foo'] assert self.struct['foo'] == 'bar', self.struct['foo']
self.struct['foo'] = 'baz' self.struct['foo'] = 'baz'
assert self.struct.has_key('foo') assert self.struct.has_key('foo')
assert isinstance(self.struct['foo'], str) assert isinstance(self.struct['foo'], unicode)
assert self.struct['foo'] == 'baz', self.struct['foo'] assert self.struct['foo'] == 'baz', self.struct['foo']
def testBoolean(self): def testBoolean(self):

View file

@ -43,3 +43,25 @@ class TestTagList(TestCase):
keys = taglist.keys() keys = taglist.keys()
keys.sort() keys.sort()
self.assertEqual(keys, ['key1', 'key2']) self.assertEqual(keys, ['key1', 'key2'])
def testUnicode(self):
taglist = gst.TagList()
# normal ASCII text
taglist[gst.TAG_ARTIST] = 'Artist'
self.failUnless(isinstance(taglist[gst.TAG_ARTIST], unicode))
self.assertEquals(taglist[gst.TAG_ARTIST], u'Artist')
self.assertEquals(taglist[gst.TAG_ARTIST], 'Artist')
# normal ASCII text as unicode
taglist[gst.TAG_ARTIST] = u'Artist'
self.failUnless(isinstance(taglist[gst.TAG_ARTIST], unicode))
self.assertEquals(taglist[gst.TAG_ARTIST], u'Artist')
self.assertEquals(taglist[gst.TAG_ARTIST], 'Artist')
# real unicode
taglist[gst.TAG_ARTIST] = u'S\xc3\xadgur R\xc3\xb3s'
self.failUnless(isinstance(taglist[gst.TAG_ARTIST], unicode))
self.assertEquals(taglist[gst.TAG_ARTIST], u'S\xc3\xadgur R\xc3\xb3s')