- o->id = g_strdup(key);
- py_str_as_str(py_desc, &o->desc);
- if (PyUnicode_Check(py_default)) {
- /* UTF-8 string */
- py_str_as_str(py_default, &def_str);
- o->def = g_variant_new_string(def_str);
- g_free(def_str);
- } else {
- /* Long */
- def_long = PyLong_AsLongAndOverflow(py_default, &overflow);
- if (overflow) {
- /* Value is < LONG_MIN or > LONG_MAX */
- PyErr_Clear();
- srd_err("Protocol decoder %s option '%s' has "
- "invalid default value.", d->name, key);
- goto err_out;
+
+ if ((py_val = PyDict_GetItemString(py_opt, "values"))) {
+ /* A default is required if a list of values is
+ * given, since it's used to verify their type. */
+ if (!o->def) {
+ srd_err("No default for option '%s'", o->id);
+ return SRD_ERR_PYTHON;
+ }
+ if (!PyTuple_Check(py_val)) {
+ srd_err("Option '%s' values should be a tuple.", o->id);
+ return SRD_ERR_PYTHON;
+ }
+ for (i = 0; i < PyTuple_Size(py_val); i++) {
+ py_item = PyTuple_GetItem(py_val, i);
+ if (Py_TYPE(py_default) != Py_TYPE(py_item)) {
+ srd_err("All values for option '%s' must be "
+ "of the same type as the default.",
+ o->id);
+ return SRD_ERR_PYTHON;
+ }
+ if (PyUnicode_Check(py_item)) {
+ /* UTF-8 string */
+ py_str_as_str(py_item, &sval);
+ gvar = g_variant_new_string(sval);
+ g_variant_ref_sink(gvar);
+ g_free(sval);
+ o->values = g_slist_append(o->values, gvar);
+ } else if (PyLong_Check(py_item)) {
+ /* Long */
+ lval = PyLong_AsLongAndOverflow(py_item, &overflow);
+ if (overflow) {
+ /* Value is < LONG_MIN or > LONG_MAX */
+ PyErr_Clear();
+ srd_err("Protocol decoder %s option 'values' "
+ "has invalid value.", d->name);
+ return SRD_ERR_PYTHON;
+ }
+ gvar = g_variant_new_int64(lval);
+ g_variant_ref_sink(gvar);
+ o->values = g_slist_append(o->values, gvar);
+ } else if (PyFloat_Check(py_item)) {
+ /* Float */
+ if ((dval = PyFloat_AsDouble(py_item)) == -1.0) {
+ PyErr_Clear();
+ srd_err("Protocol decoder %s option 'default' has "
+ "invalid default value.", d->name);
+ return SRD_ERR_PYTHON;
+ }
+ gvar = g_variant_new_double(dval);
+ g_variant_ref_sink(gvar);
+ o->values = g_slist_append(o->values, gvar);
+ }