Example #1
0
static int
python_to_map(ConvertInfo *info, PyObject *pyobj, avro_value_t *dest)
{
    int rval = 0;
    size_t i;
    size_t element_count;
    PyObject *keys;
    PyObject *vals;

    element_count = PyMapping_Length(pyobj);

    keys = PyMapping_Keys(pyobj);
    vals = PyMapping_Values(pyobj);

    for (i = 0; !rval && i < element_count; i++) {
        PyObject *key = PySequence_GetItem(keys, i);
        PyObject *val = PySequence_GetItem(vals, i);
        avro_value_t child;

        rval = avro_value_add(dest, PyString_AsString(key), &child, NULL, NULL);
        if (!rval) {
            rval = python_to_avro(info, val, &child);
        }

        Py_DECREF(key);
        Py_DECREF(val);
    }

    Py_DECREF(keys);
    Py_DECREF(vals);

    return rval;
}
Example #2
0
static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob)
{
	IDProperty *prop;
	IDPropertyTemplate val = {0};

	PyObject *keys, *vals, *key, *pval;
	int i, len;
	/* yay! we get into recursive stuff now! */
	keys = PyMapping_Keys(ob);
	vals = PyMapping_Values(ob);

	/* we allocate the group first; if we hit any invalid data,
	 * we can delete it easily enough.*/
	prop = IDP_New(IDP_GROUP, &val, name);
	len = PyMapping_Length(ob);
	for (i = 0; i < len; i++) {
		key = PySequence_GetItem(keys, i);
		pval = PySequence_GetItem(vals, i);
		if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) {
			IDP_FreeProperty(prop);
			MEM_freeN(prop);
			Py_XDECREF(keys);
			Py_XDECREF(vals);
			Py_XDECREF(key);
			Py_XDECREF(pval);
			/* error is already set */
			return NULL;
		}
		Py_XDECREF(key);
		Py_XDECREF(pval);
	}
	Py_XDECREF(keys);
	Py_XDECREF(vals);
	return prop;
}
Example #3
0
/*	Update LDAPEntry form dict. Based on the PyDict_Merge function. */
int
LDAPEntry_UpdateFromDict(LDAPEntry *self, PyObject *dict) {
	int rc;
	PyObject *keys = PyMapping_Keys(dict);
	PyObject *iter;
	PyObject *key, *value;
	if (keys == NULL) return -1;

	iter = PyObject_GetIter(keys);
	Py_DECREF(keys);
	if (iter == NULL) return -1;

	/*Iterate over the dict keys, and get the values. */
	for (key = PyIter_Next(iter); key != NULL; key = PyIter_Next(iter)) {
		/* Return value: New reference. */
		value = PyObject_GetItem(dict, key);
		if (value == NULL) {
			Py_DECREF(iter);
			Py_DECREF(key);
			return -1;
		}
		/* Set the new key-value. */
		rc = LDAPEntry_SetItem(self, key, value);
		Py_DECREF(key);
		Py_DECREF(value);
		if (rc < 0) {
			Py_DECREF(iter);
			return -1;
		}
	}
	Py_DECREF(iter);
	if (PyErr_Occurred()) return -1;
    return 0;
}
Example #4
0
/* {{{ pip_mapping_to_hash(PyObject *map)
   Convert a Python mapping to a PHP hash */
zval *
pip_mapping_to_hash(PyObject *map)
{
	zval *hash, *val;
	PyObject *keys, *key, *item;
	char *key_name;
	int i, key_len;

	if (!PyMapping_Check(map)) {
		return NULL;
	}

	/* Initialize our PHP array */
	MAKE_STD_ZVAL(hash);
	if (array_init(hash) != SUCCESS) {
		return NULL;
	}

	/* Retrieve the list of keys for this mapping */
	keys = PyMapping_Keys(map);
	if (keys == NULL) {
		return hash;
	}

	/* Iterate over the list of keys */
	for (i = 0; i < PySequence_Size(keys); i++) {
		key = PySequence_GetItem(keys, i);
		if (key) {
			/* Get the string representation of the key */
			if (pip_str(key, &key_name, &key_len) != -1) {
				/* Extract the item for this key */
				item = PyMapping_GetItemString(map, key_name);
				if (item) {
					val = pip_pyobject_to_zval(item);

					/* Add the new item to the associative array */
					if (zend_hash_update(HASH_OF(hash), key_name, key_len,
										 (void *)&val, sizeof(zval *),
										 NULL) == FAILURE) {
						php_error(E_ERROR, "Python: Array conversion error");
					}
					Py_DECREF(item);
				} else {
					php_error(E_ERROR, "Python: Could not get item for key");
				}
			} else {
				php_error(E_ERROR, "Python: Mapping key conversion error");
			}
			Py_DECREF(key);
		}
	}
	Py_DECREF(keys);

	return hash;
}
Example #5
0
static PyObject *Scopeable__getattr__(PyObject *self, PyObject *args) {
  char *attrname;
  PyObject *val=NULL, *inDict, *masher;
  if (!PyArg_ParseTuple(args, "Os", &self, &attrname)) {
    return NULL;
  }

  inDict=((PyInstanceObject *)self)->in_dict;
  masher=PyMapping_GetItemString(inDict, MASH);

  if (PyObject_IsTrue(masher) 
      && PyMapping_HasKeyString(masher, attrname)) {
    val=PyMapping_GetItemString(masher, attrname);
  } 
  else {
    PyObject *dictList;
    int len, i;

    dictList=PyMapping_GetItemString(inDict, DICTLIST);    
    len=PyList_Size(dictList);

    for (i=0;i<len;i++) {
      PyObject *d=PyList_GetItem(dictList, i);
      if (PyMapping_HasKeyString(d, attrname)) {
	val=PyMapping_GetItemString(d, attrname);
	break;
      }
    }
    Py_DECREF(dictList);
  }  

  if (val==NULL) {
    /* check for special attribute "__all__" */
    char *allattr="__all__";
    if (!strncmp(attrname, allattr, strlen(allattr))) {
      PyObject *mashed, *keys, *newargs;
      newargs=PyTuple_New(1);

      PyTuple_SetItem(newargs, 0, self);

      REFCNT("self", self);
      mashed=Scopeable_mash(NULL, newargs);
      keys=PyMapping_Keys(mashed);
      REFCNT("keys", keys);
      Py_DECREF(mashed);
      val=keys;
    } else {
      PyErr_SetString(PyExc_AttributeError, attrname);
    }
  }

  Py_DECREF(masher);
  return val;
}
Example #6
0
PyObject *ObjectRow_PyObject__keys(ObjectRow_PyObject *self, PyObject *args, PyObject *kwargs)
{
    PyObject *key, *value, *parent_type, *parent_id;
    Py_ssize_t pos = 0;

    if (!self->query_info && !self->keys)
        // No query_info means we work just from pickle dict.
        self->keys = PyMapping_Keys(self->pickle);

    if (self->keys) {
        Py_INCREF(self->keys);
        return self->keys;
    }

    self->keys = PyList_New(0);
    key = PyString_FromString("type");
    PyList_Append(self->keys, key);
    Py_DECREF(key);

    while (PyDict_Next(self->query_info->idxmap, &pos, &key, &value)) {
        ObjectAttribute *attr = (ObjectAttribute *)PyCObject_AsVoidPtr(value);
        if (attr->index >= 0 || (attr->pickled && self->query_info->pickle_idx >= 0)) {
            if (PyStr_Compare(key, "pickle") != 0)
                PyList_Append(self->keys, key);
        }
    }

    parent_type = PyString_FromString("parent_type");
    parent_id = PyString_FromString("parent_id");
    if (PySequence_Contains(self->keys, parent_type) && PySequence_Contains(self->keys, parent_id)) {
        key = PyString_FromString("parent");
        PyList_Append(self->keys, key);
        Py_DECREF(key);
    }
    Py_DECREF(parent_type);
    Py_DECREF(parent_id);

    Py_INCREF(self->keys);
    return self->keys;
}
Example #7
0
static PyObject *
LDAPEntry_delete(LDAPEntry *self, PyObject *args, PyObject *kwds) {
	char *dnstr;
	PyObject *keys = PyMapping_Keys((PyObject *)self);
	PyObject *iter, *key;
	PyObject *tmp;
	LDAPValueList *value;

	/* Client must be set. */
	if (self->client == NULL) {
		PyErr_SetString(PyExc_AttributeError, "LDAPClient is not set.");
		return NULL;
	}

	/* Get DN string. */
	tmp = PyObject_Str(self->dn);
	dnstr = PyObject2char(tmp);
	Py_DECREF(tmp);
	if (dnstr == NULL) return NULL;
	if (LDAPClient_DelEntryStringDN(self->client, dnstr) != 0) return NULL;

	if (keys == NULL) return NULL;

	iter = PyObject_GetIter(keys);
	Py_DECREF(keys);
	if (iter == NULL) return NULL;

	for (key = PyIter_Next(iter); key != NULL; key = PyIter_Next(iter)) {
		/* Return value: New reference. */
		value = (LDAPValueList *)LDAPEntry_GetItem(self, key);
		if (value == NULL) {
			Py_DECREF(iter);
			Py_DECREF(key);
			return NULL;
		}
		value->status = 2;
	}
	return Py_None;
}
Example #8
0
static PyObject *
attr_dir_merge(PyObject *_self, PyObject *map)
{
	PyObject *keys, *iter;
	PyObject *key, *value;
	int status;

	keys = PyMapping_Keys(map);
	if (!keys)
	    return NULL;
	iter = PyObject_GetIter(keys);
	Py_DECREF(keys);
	if (!iter)
	    return NULL;

	for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
		value = PyObject_GetItem(map, key);
		if (!value)
			goto err;

		status = attr_dir_ass_subscript(_self, key, value);
		Py_DECREF(value);
		if (status < 0)
			goto err;
		Py_DECREF(key);
	}
	Py_DECREF(iter);
	if (PyErr_Occurred())
		return NULL;

	return Py_None;

 err:
	Py_DECREF(iter);
	Py_DECREF(key);
	return NULL;
}
Example #9
0
        }
    }
    return v;
}

/**
 ** table_merge
 **
 *  Since tables can only store strings, key/vals from
 *  mapping object b will be str()ingized.
 */

static int table_merge(tableobject *a, PyObject *b, int override)
{
    /* Do it the generic, slower way */
    PyObject *keys = PyMapping_Keys(b);
    PyObject *iter;
    PyObject *key, *value, *skey, *svalue;
    int status;

    if (keys == NULL)
        return -1;

    iter = PyObject_GetIter(keys);
    Py_DECREF(keys);
    if (iter == NULL)
        return -1;
    
    for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {

        skey = PyObject_Str(key);
Example #10
0
/**
 * \note group can be a pointer array or a group.
 * assume we already checked key is a string.
 *
 * \return success.
 */
bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob)
{
    IDProperty *prop = NULL;
    IDPropertyTemplate val = {0};

    const char *name;

    if (name_obj) {
        Py_ssize_t name_size;
        name = _PyUnicode_AsStringAndSize(name_obj, &name_size);

        if (name == NULL) {
            PyErr_Format(PyExc_KeyError,
                         "invalid id-property key, expected a string, not a %.200s",
                         Py_TYPE(name_obj)->tp_name);
            return false;
        }

        if (name_size > MAX_IDPROP_NAME) {
            PyErr_SetString(PyExc_KeyError, "the length of IDProperty names is limited to 63 characters");
            return false;
        }
    }
    else {
        name = "";
    }

    if (PyFloat_Check(ob)) {
        val.d = PyFloat_AsDouble(ob);
        prop = IDP_New(IDP_DOUBLE, &val, name);
    }
    else if (PyLong_Check(ob)) {
        val.i = _PyLong_AsInt(ob);
        if (val.i == -1 && PyErr_Occurred()) {
            return false;
        }
        prop = IDP_New(IDP_INT, &val, name);
    }
    else if (PyUnicode_Check(ob)) {
#ifdef USE_STRING_COERCE
        PyObject *value_coerce = NULL;
        val.string.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce);
        val.string.subtype = IDP_STRING_SUB_UTF8;
        prop = IDP_New(IDP_STRING, &val, name);
        Py_XDECREF(value_coerce);
#else
        val.str = _PyUnicode_AsString(ob);
        prop = IDP_New(IDP_STRING, val, name);
#endif
    }
    else if (PyBytes_Check(ob)) {
        val.string.str = PyBytes_AS_STRING(ob);
        val.string.len = PyBytes_GET_SIZE(ob);
        val.string.subtype = IDP_STRING_SUB_BYTE;

        prop = IDP_New(IDP_STRING, &val, name);
        //prop = IDP_NewString(PyBytes_AS_STRING(ob), name, PyBytes_GET_SIZE(ob));
        //prop->subtype = IDP_STRING_SUB_BYTE;
    }
    else if (PySequence_Check(ob)) {
        PyObject *ob_seq_fast = PySequence_Fast(ob, "py -> idprop");
        PyObject *item;
        int i;

        if (ob_seq_fast == NULL) {
            return false;
        }

        if ((val.array.type = idp_sequence_type(ob_seq_fast)) == -1) {
            Py_DECREF(ob_seq_fast);
            PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays");
            return false;
        }

        /* validate sequence and derive type.
         * we assume IDP_INT unless we hit a float
         * number; then we assume it's */

        val.array.len = PySequence_Fast_GET_SIZE(ob_seq_fast);

        switch (val.array.type) {
        case IDP_DOUBLE:
        {
            double *prop_data;

            prop = IDP_New(IDP_ARRAY, &val, name);
            prop_data = IDP_Array(prop);
            for (i = 0; i < val.array.len; i++) {
                item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);
                if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) {
                    Py_DECREF(ob_seq_fast);
                    return false;
                }
            }
            break;
        }
        case IDP_INT:
        {
            int *prop_data;
            prop = IDP_New(IDP_ARRAY, &val, name);
            prop_data = IDP_Array(prop);
            for (i = 0; i < val.array.len; i++) {
                item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);
                if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) {
                    Py_DECREF(ob_seq_fast);
                    return false;
                }
            }
            break;
        }
        case IDP_IDPARRAY:
        {
            prop = IDP_NewIDPArray(name);
            for (i = 0; i < val.array.len; i++) {
                item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);

                if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) {
                    Py_DECREF(ob_seq_fast);
                    return false;
                }
            }
            break;
        }
        default:
            /* should never happen */
            Py_DECREF(ob_seq_fast);
            PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type");
            return false;
        }

        Py_DECREF(ob_seq_fast);
    }
    else if (PyMapping_Check(ob)) {
        PyObject *keys, *vals, *key, *pval;
        int i, len;
        /*yay! we get into recursive stuff now!*/
        keys = PyMapping_Keys(ob);
        vals = PyMapping_Values(ob);

        /* we allocate the group first; if we hit any invalid data,
         * we can delete it easily enough.*/
        prop = IDP_New(IDP_GROUP, &val, name);
        len = PyMapping_Length(ob);
        for (i = 0; i < len; i++) {
            key = PySequence_GetItem(keys, i);
            pval = PySequence_GetItem(vals, i);
            if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) {
                IDP_FreeProperty(prop);
                MEM_freeN(prop);
                Py_XDECREF(keys);
                Py_XDECREF(vals);
                Py_XDECREF(key);
                Py_XDECREF(pval);
                /* error is already set */
                return false;
            }
            Py_XDECREF(key);
            Py_XDECREF(pval);
        }
        Py_XDECREF(keys);
        Py_XDECREF(vals);
    }
    else {
        PyErr_Format(PyExc_TypeError,
                     "invalid id-property type %.200s not supported",
                     Py_TYPE(ob)->tp_name);
        return false;
    }

    if (group->type == IDP_IDPARRAY) {
        IDP_AppendArray(group, prop);
        // IDP_FreeProperty(item);  /* IDP_AppendArray does a shallow copy (memcpy), only free memory */
        MEM_freeN(prop);
    }
    else {
        IDP_ReplaceInGroup(group, prop);
    }

    return true;
}
Example #11
0
static PyObject *
proxy_keys(proxyobject *pp)
{
	return PyMapping_Keys(pp->dict);
}
Example #12
0
static PyObject*
getenvironment(PyObject* environment)
{
	int i, envsize;
	PyObject* out = NULL;
	PyObject* keys;
	PyObject* values;
	char* p;

	/* convert environment dictionary to windows enviroment string */
	if (! PyMapping_Check(environment)) {
		PyErr_SetString(
		    PyExc_TypeError, "environment must be dictionary or None");
		return NULL;
	}

	envsize = PyMapping_Length(environment);

	keys = PyMapping_Keys(environment);
	values = PyMapping_Values(environment);
	if (!keys || !values)
		goto error;

	out = PyString_FromStringAndSize(NULL, 2048);
	if (! out)
		goto error;

	p = PyString_AS_STRING(out);

	for (i = 0; i < envsize; i++) {
		int ksize, vsize, totalsize;
		PyObject* key = PyList_GET_ITEM(keys, i);
		PyObject* value = PyList_GET_ITEM(values, i);

		if (! PyString_Check(key) || ! PyString_Check(value)) {
			PyErr_SetString(PyExc_TypeError,
				"environment can only contain strings");
			goto error;
		}
		ksize = PyString_GET_SIZE(key);
		vsize = PyString_GET_SIZE(value);
		totalsize = (p - PyString_AS_STRING(out)) + ksize + 1 +
							     vsize + 1 + 1;
		if (totalsize > PyString_GET_SIZE(out)) {
			int offset = p - PyString_AS_STRING(out);
			_PyString_Resize(&out, totalsize + 1024);
			p = PyString_AS_STRING(out) + offset;
		}
		memcpy(p, PyString_AS_STRING(key), ksize);
		p += ksize;
		*p++ = '=';
		memcpy(p, PyString_AS_STRING(value), vsize);
		p += vsize;
		*p++ = '\0';
	}

	/* add trailing null byte */
	*p++ = '\0';
	_PyString_Resize(&out, p - PyString_AS_STRING(out));

	/* PyObject_Print(out, stdout, 0); */

	Py_XDECREF(keys);
	Py_XDECREF(values);

	return out;

 error:
	Py_XDECREF(out);
	Py_XDECREF(keys);
	Py_XDECREF(values);
	return NULL;
}
Example #13
0
/* note: group can be a pointer array or a group */
const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *group, PyObject *ob)
{
    IDProperty *prop = NULL;
    IDPropertyTemplate val = {0};

    if(strlen(name) >= sizeof(group->name))
        return "the length of IDProperty names is limited to 31 characters";

    if (PyFloat_Check(ob)) {
        val.d = PyFloat_AsDouble(ob);
        prop = IDP_New(IDP_DOUBLE, val, name);
    } else if (PyLong_Check(ob)) {
        val.i = (int) PyLong_AsSsize_t(ob);
        prop = IDP_New(IDP_INT, val, name);
    } else if (PyUnicode_Check(ob)) {
#ifdef USE_STRING_COERCE
        PyObject *value_coerce= NULL;
        val.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce);
        prop = IDP_New(IDP_STRING, val, name);
        Py_XDECREF(value_coerce);
#else
        val.str = _PyUnicode_AsString(ob);
        prop = IDP_New(IDP_STRING, val, name);
#endif
    } else if (PySequence_Check(ob)) {
        PyObject *item;
        int i;

        if((val.array.type= idp_sequence_type(ob)) == -1)
            return "only floats, ints and dicts are allowed in ID property arrays";

        /*validate sequence and derive type.
        we assume IDP_INT unless we hit a float
        number; then we assume it's */

        val.array.len = PySequence_Size(ob);

        switch(val.array.type) {
        case IDP_DOUBLE:
            prop = IDP_New(IDP_ARRAY, val, name);
            for (i=0; i<val.array.len; i++) {
                item = PySequence_GetItem(ob, i);
                ((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
                Py_DECREF(item);
            }
            break;
        case IDP_INT:
            prop = IDP_New(IDP_ARRAY, val, name);
            for (i=0; i<val.array.len; i++) {
                item = PySequence_GetItem(ob, i);
                ((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item);
                Py_DECREF(item);
            }
            break;
        case IDP_IDPARRAY:
            prop= IDP_NewIDPArray(name);
            for (i=0; i<val.array.len; i++) {
                const char *error;
                item = PySequence_GetItem(ob, i);
                error= BPy_IDProperty_Map_ValidateAndCreate("", prop, item);
                Py_DECREF(item);

                if(error)
                    return error;
            }
            break;
        }
    } else if (PyMapping_Check(ob)) {
        PyObject *keys, *vals, *key, *pval;
        int i, len;
        /*yay! we get into recursive stuff now!*/
        keys = PyMapping_Keys(ob);
        vals = PyMapping_Values(ob);

        /*we allocate the group first; if we hit any invalid data,
          we can delete it easily enough.*/
        prop = IDP_New(IDP_GROUP, val, name);
        len = PyMapping_Length(ob);
        for (i=0; i<len; i++) {
            key = PySequence_GetItem(keys, i);
            pval = PySequence_GetItem(vals, i);
            if (!PyUnicode_Check(key)) {
                IDP_FreeProperty(prop);
                MEM_freeN(prop);
                Py_XDECREF(keys);
                Py_XDECREF(vals);
                Py_XDECREF(key);
                Py_XDECREF(pval);
                return "invalid element in subgroup dict template!";
            }
            if (BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, pval)) {
                IDP_FreeProperty(prop);
                MEM_freeN(prop);
                Py_XDECREF(keys);
                Py_XDECREF(vals);
                Py_XDECREF(key);
                Py_XDECREF(pval);
                return "invalid element in subgroup dict template!";
            }
            Py_XDECREF(key);
            Py_XDECREF(pval);
        }
        Py_XDECREF(keys);
        Py_XDECREF(vals);
    } else return "invalid property value";

    if(group->type==IDP_IDPARRAY) {
        IDP_AppendArray(group, prop);
        // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory
        MEM_freeN(prop);
    } else {
        IDP_ReplaceInGroup(group, prop);
    }

    return NULL;
}
Example #14
0
int SortedDict_iterNext(JSOBJ obj, JSONTypeContext *tc)
{
  PyObject *items = NULL, *item = NULL, *key = NULL, *value = NULL;
  Py_ssize_t i, nitems;
#if PY_MAJOR_VERSION >= 3
  PyObject* keyTmp;
#endif

  // Upon first call, obtain a list of the keys and sort them. This follows the same logic as the
  // stanard library's _json.c sort_keys handler.
  if (GET_TC(tc)->newObj == NULL)
  {
    // Obtain the list of keys from the dictionary.
    items = PyMapping_Keys(GET_TC(tc)->dictObj);
    if (items == NULL)
    {
      goto error;
    }
    else if (!PyList_Check(items))
    {
      PyErr_SetString(PyExc_ValueError, "keys must return list");
      goto error;
    }

    // Sort the list.
    if (PyList_Sort(items) < 0)
    {
      goto error;
    }

    // Obtain the value for each key, and pack a list of (key, value) 2-tuples.
    nitems = PyList_GET_SIZE(items);
    for (i = 0; i < nitems; i++)
    {
      key = PyList_GET_ITEM(items, i);
      value = PyDict_GetItem(GET_TC(tc)->dictObj, key);

      // Subject the key to the same type restrictions and conversions as in Dict_iterGetValue.
      if (PyUnicode_Check(key))
      {
        key = PyUnicode_AsUTF8String(key);
      }
      else if (!PyString_Check(key))
      {
        key = PyObject_Str(key);
#if PY_MAJOR_VERSION >= 3
        keyTmp = key;
        key = PyUnicode_AsUTF8String(key);
        Py_DECREF(keyTmp);
#endif
      }
      else
      {
        Py_INCREF(key);
      }

      item = PyTuple_Pack(2, key, value);
      if (item == NULL)
      {
        goto error;
      }
      PyList_SET_ITEM(items, i, item);
      Py_DECREF(key);
    }

    // Store the sorted list of tuples in the newObj slot.
    GET_TC(tc)->newObj = items;
    GET_TC(tc)->size = nitems;
  }

  if (GET_TC(tc)->index >= GET_TC(tc)->size)
  {
    PRINTMARK();
    return 0;
  }

  item = PyList_GET_ITEM(GET_TC(tc)->newObj, GET_TC(tc)->index);
  GET_TC(tc)->itemName = PyTuple_GET_ITEM(item, 0);
  GET_TC(tc)->itemValue = PyTuple_GET_ITEM(item, 1);
  GET_TC(tc)->index++;
  return 1;

error:
  Py_XDECREF(item);
  Py_XDECREF(key);
  Py_XDECREF(value);
  Py_XDECREF(items);
  return -1;
}
Example #15
0
/****************************
 * SV* Py2Pl(PyObject *obj)
 *
 * Converts arbitrary Python data structures to Perl data structures
 * Note on references: does not Py_DECREF(obj).
 *
 * Modifications by Eric Wilhelm 2004-07-11 marked as elw
 *
 ****************************/
SV *Py2Pl(PyObject * const obj) {
    /* elw: see what python says things are */
#if PY_MAJOR_VERSION >= 3
    int const is_string = PyBytes_Check(obj) || PyUnicode_Check(obj);
#else
    int const is_string = PyString_Check(obj) || PyUnicode_Check(obj);
#endif
#ifdef I_PY_DEBUG
    PyObject *this_type = PyObject_Type(obj); /* new reference */
    PyObject *t_string = PyObject_Str(this_type); /* new reference */
#if PY_MAJOR_VERSION >= 3
    PyObject *type_str_bytes = PyUnicode_AsUTF8String(t_string); /* new reference */
    char *type_str = PyBytes_AsString(type_str_bytes);
#else
    char *type_str = PyString_AsString(t_string);
#endif
    Printf(("type is %s\n", type_str));
    printf("Py2Pl object:\n\t");
    PyObject_Print(obj, stdout, Py_PRINT_RAW);
    printf("\ntype:\n\t");
    PyObject_Print(this_type, stdout, Py_PRINT_RAW);
    printf("\n");
    Printf(("String check:   %i\n", is_string));
    Printf(("Number check:   %i\n", PyNumber_Check(obj)));
    Printf(("Int check:      %i\n", PyInt_Check(obj)));
    Printf(("Long check:     %i\n", PyLong_Check(obj)));
    Printf(("Float check:    %i\n", PyFloat_Check(obj)));
    Printf(("Type check:     %i\n", PyType_Check(obj)));
#if PY_MAJOR_VERSION < 3
    Printf(("Class check:    %i\n", PyClass_Check(obj)));
    Printf(("Instance check: %i\n", PyInstance_Check(obj)));
#endif
    Printf(("Dict check:     %i\n", PyDict_Check(obj)));
    Printf(("Mapping check:  %i\n", PyMapping_Check(obj)));
    Printf(("Sequence check: %i\n", PySequence_Check(obj)));
    Printf(("Iter check:     %i\n", PyIter_Check(obj)));
    Printf(("Function check: %i\n", PyFunction_Check(obj)));
    Printf(("Module check:   %i\n", PyModule_Check(obj)));
    Printf(("Method check:   %i\n", PyMethod_Check(obj)));
#if PY_MAJOR_VERSION < 3
    if ((obj->ob_type->tp_flags & Py_TPFLAGS_HEAPTYPE))
        printf("heaptype true\n");
    if ((obj->ob_type->tp_flags & Py_TPFLAGS_HAVE_CLASS))
        printf("has class\n");
#else
    Py_DECREF(type_str_bytes);
#endif
    Py_DECREF(t_string);
    Py_DECREF(this_type);
#endif
    /* elw: this needs to be early */
    /* None (like undef) */
    if (!obj || obj == Py_None) {
        Printf(("Py2Pl: Py_None\n"));
        return &PL_sv_undef;
    }
    else

#ifdef EXPOSE_PERL
    /* unwrap Perl objects */
    if (PerlObjObject_Check(obj)) {
        Printf(("Py2Pl: Obj_object\n"));
        return ((PerlObj_object *) obj)->obj;
    }

    /* unwrap Perl code refs */
    else if (PerlSubObject_Check(obj)) {
        Printf(("Py2Pl: Sub_object\n"));
        SV * ref = ((PerlSub_object *) obj)->ref;
        if (! ref) { /* probably an inherited method */
            if (! ((PerlSub_object *) obj)->obj)
                croak("Error: could not find a code reference or object method for PerlSub");
            SV * const sub_obj = (SV*)SvRV(((PerlSub_object *) obj)->obj);
            HV * const pkg = SvSTASH(sub_obj);
#if PY_MAJOR_VERSION >= 3
            char * const sub = PyBytes_AsString(((PerlSub_object *) obj)->sub);
#else
            PyObject *obj_sub_str = PyObject_Str(((PerlSub_object *) obj)->sub); /* new ref. */
            char * const sub = PyString_AsString(obj_sub_str);
#endif
            GV * const gv = Perl_gv_fetchmethod_autoload(aTHX_ pkg, sub, TRUE);
            if (gv && isGV(gv)) {
                ref = (SV *)GvCV(gv);
            }
#if PY_MAJOR_VERSION < 3
            Py_DECREF(obj_sub_str);
#endif
        }
        return newRV_inc((SV *) ref);
    }

    else
#endif

    /* wrap an instance of a Python class */
    /* elw: here we need to make these look like instances: */
    if ((obj->ob_type->tp_flags & Py_TPFLAGS_HEAPTYPE)
#if PY_MAJOR_VERSION < 3
        || PyInstance_Check(obj)
#endif
    ) {

        /* This is a Python class instance -- bless it into an
         * Inline::Python::Object. If we're being called from an
         * Inline::Python class, it will be re-blessed into whatever
         * class that is.
         */
        SV * const inst_ptr = newSViv(0);
        SV * const inst = newSVrv(inst_ptr, "Inline::Python::Object");;
        _inline_magic priv;

        /* set up magic */
        priv.key = INLINE_MAGIC_KEY;
        sv_magic(inst, inst, PERL_MAGIC_ext, (char *) &priv, sizeof(priv));
        MAGIC * const mg = mg_find(inst, PERL_MAGIC_ext);
        mg->mg_virtual = &inline_mg_vtbl;

        sv_setiv(inst, (IV) obj);
        /*SvREADONLY_on(inst); */ /* to uncomment this means I can't
            re-bless it */
        Py_INCREF(obj);
        Printf(("Py2Pl: Instance. Obj: %p, inst_ptr: %p\n", obj, inst_ptr));

        sv_2mortal(inst_ptr);
        return inst_ptr;
    }

    /* a tuple or a list */
    else if (PySequence_Check(obj) && !is_string) {
        AV * const retval = newAV();
        int i;
        int const sz = PySequence_Length(obj);

        Printf(("sequence (%i)\n", sz));

        for (i = 0; i < sz; i++) {
            PyObject * const tmp = PySequence_GetItem(obj, i);    /* new reference */
            SV * const next = Py2Pl(tmp);
            av_push(retval, next);
            if (sv_isobject(next)) // needed because objects get mortalized in Py2Pl
                SvREFCNT_inc(next);
            Py_DECREF(tmp);
        }

        if (PyTuple_Check(obj)) {
            _inline_magic priv;
            priv.key = TUPLE_MAGIC_KEY;

            sv_magic((SV * const)retval, (SV * const)NULL, PERL_MAGIC_ext, (char *) &priv, sizeof(priv));
        }

        return newRV_noinc((SV *) retval);
    }

    /* a dictionary or fake Mapping object */
    /* elw: PyMapping_Check() now returns true for strings */
    else if (! is_string && PyMapping_Check(obj)) {
        HV * const retval = newHV();
        int i;
        int const sz = PyMapping_Length(obj);
        PyObject * const keys = PyMapping_Keys(obj);   /* new reference */
        PyObject * const vals = PyMapping_Values(obj); /* new reference */

        Printf(("Py2Pl: dict/map\n"));
        Printf(("mapping (%i)\n", sz));

        for (i = 0; i < sz; i++) {
            PyObject * const key = PySequence_GetItem(keys, i), /* new reference */
                                 * const val = PySequence_GetItem(vals, i); /* new reference */
            SV       * const sv_val = Py2Pl(val);
            char     *       key_val;

            if (PyUnicode_Check(key)) {
                PyObject * const utf8_string = PyUnicode_AsUTF8String(key); /* new reference */
#if PY_MAJOR_VERSION >= 3
                key_val = PyBytes_AsString(utf8_string);
                SV * const utf8_key = newSVpv(key_val, PyBytes_Size(utf8_string));
#else
                key_val = PyString_AsString(utf8_string);
                SV * const utf8_key = newSVpv(key_val, PyString_Size(utf8_string));
#endif
                SvUTF8_on(utf8_key);

                hv_store_ent(retval, utf8_key, sv_val, 0);
                Py_DECREF(utf8_string);
            }
            else {
                PyObject * s = NULL;
#if PY_MAJOR_VERSION >= 3
                PyObject * s_bytes = NULL;
                if (PyBytes_Check(key)) {
                    key_val = PyBytes_AsString(key);
#else
                if (PyString_Check(key)) {
                    key_val = PyString_AsString(key);
#endif
                }
                else {
                    /* Warning -- encountered a non-string key value while converting a
                     * Python dictionary into a Perl hash. Perl can only use strings as
                     * key values. Using Python's string representation of the key as
                     * Perl's key value.
                     */
                    s = PyObject_Str(key); /* new reference */
#if PY_MAJOR_VERSION >= 3
                    s_bytes = PyUnicode_AsUTF8String(s); /* new reference */
                    key_val = PyBytes_AsString(s_bytes);
#else
                    key_val = PyString_AsString(s);
#endif
                    Py_DECREF(s);
                    if (PL_dowarn)
                        warn("Stringifying non-string hash key value: '%s'",
                             key_val);
                }

                if (!key_val) {
                    croak("Invalid key on key %i of mapping\n", i);
                }

                hv_store(retval, key_val, strlen(key_val), sv_val, 0);
#if PY_MAJOR_VERSION >= 3
                Py_XDECREF(s_bytes);
#endif
                Py_XDECREF(s);
            }
            if (sv_isobject(sv_val)) // needed because objects get mortalized in Py2Pl
                SvREFCNT_inc(sv_val);
            Py_DECREF(key);
            Py_DECREF(val);
        }
        Py_DECREF(keys);
        Py_DECREF(vals);
        return newRV_noinc((SV *) retval);
    }

    /* a boolean */
    else if (PyBool_Check(obj)) {
Example #16
0
PyObject *glue_PyMapping_Keys(PyObject *o) {
  return PyMapping_Keys(o);
}
Example #17
0
GIArgument
_pygi_argument_from_object (PyObject   *object,
                            GITypeInfo *type_info,
                            GITransfer  transfer)
{
    GIArgument arg;
    GITypeTag type_tag;
    gpointer cleanup_data = NULL;

    memset(&arg, 0, sizeof(GIArgument));
    type_tag = g_type_info_get_tag (type_info);

    /* Ignores cleanup data for now. */
    if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer, &cleanup_data) ||
            PyErr_Occurred()) {
        return arg;
    }

    switch (type_tag) {
        case GI_TYPE_TAG_ARRAY:
        {
            Py_ssize_t length;
            gboolean is_zero_terminated;
            GITypeInfo *item_type_info;
            gsize item_size;
            GArray *array;
            GITransfer item_transfer;
            Py_ssize_t i;

            if (object == Py_None) {
                arg.v_pointer = NULL;
                break;
            }

            /* Note, strings are sequences, but we cannot accept them here */
            if (!PySequence_Check (object) || 
#if PY_VERSION_HEX < 0x03000000
                PyString_Check (object) || 
#endif
                PyUnicode_Check (object)) {
                PyErr_SetString (PyExc_TypeError, "expected sequence");
                break;
            }

            length = PySequence_Length (object);
            if (length < 0) {
                break;
            }

            is_zero_terminated = g_type_info_is_zero_terminated (type_info);
            item_type_info = g_type_info_get_param_type (type_info, 0);

            /* we handle arrays that are really strings specially, see below */
            if (g_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8)
               item_size = 1;
            else
               item_size = sizeof (GIArgument);

            array = g_array_sized_new (is_zero_terminated, FALSE, item_size, length);
            if (array == NULL) {
                g_base_info_unref ( (GIBaseInfo *) item_type_info);
                PyErr_NoMemory();
                break;
            }

            if (g_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8 &&
                PYGLIB_PyBytes_Check(object)) {

                memcpy(array->data, PYGLIB_PyBytes_AsString(object), length);
                array->len = length;
                goto array_success;
            }


            item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;

            for (i = 0; i < length; i++) {
                PyObject *py_item;
                GIArgument item;

                py_item = PySequence_GetItem (object, i);
                if (py_item == NULL) {
                    goto array_item_error;
                }

                item = _pygi_argument_from_object (py_item, item_type_info, item_transfer);

                Py_DECREF (py_item);

                if (PyErr_Occurred()) {
                    goto array_item_error;
                }

                g_array_insert_val (array, i, item);
                continue;

array_item_error:
                /* Free everything we have converted so far. */
                _pygi_argument_release ( (GIArgument *) &array, type_info,
                                         GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
                array = NULL;

                _PyGI_ERROR_PREFIX ("Item %zd: ", i);
                break;
            }

array_success:
            arg.v_pointer = array;

            g_base_info_unref ( (GIBaseInfo *) item_type_info);
            break;
        }
        case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *info;
            GIInfoType info_type;

            info = g_type_info_get_interface (type_info);
            info_type = g_base_info_get_type (info);

            switch (info_type) {
                case GI_INFO_TYPE_CALLBACK:
                    /* This should be handled in invoke() */
                    g_assert_not_reached();
                    break;
                case GI_INFO_TYPE_BOXED:
                case GI_INFO_TYPE_STRUCT:
                case GI_INFO_TYPE_UNION:
                {
                    GType g_type;
                    PyObject *py_type;
                    gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) &&
                                          (g_struct_info_is_foreign ((GIStructInfo *) info));

                    g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
                    py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info);

                    /* Note for G_TYPE_VALUE g_type:
                     * This will currently leak the GValue that is allocated and
                     * stashed in arg.v_pointer. Out argument marshaling for caller
                     * allocated GValues already pass in memory for the GValue.
                     * Further re-factoring is needed to fix this leak.
                     * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405
                     */
                    pygi_arg_struct_from_py_marshal (object,
                                                     &arg,
                                                     NULL, /*arg_name*/
                                                     info, /*interface_info*/
                                                     g_type,
                                                     py_type,
                                                     transfer,
                                                     FALSE, /*copy_reference*/
                                                     is_foreign,
                                                     g_type_info_is_pointer (type_info));

                    Py_DECREF (py_type);
                    break;
                }
                case GI_INFO_TYPE_ENUM:
                case GI_INFO_TYPE_FLAGS:
                {
                    PyObject *int_;

                    int_ = PYGLIB_PyNumber_Long (object);
                    if (int_ == NULL) {
                        break;
                    }

                    arg.v_int = PYGLIB_PyLong_AsLong (int_);

                    Py_DECREF (int_);

                    break;
                }
                case GI_INFO_TYPE_INTERFACE:
                case GI_INFO_TYPE_OBJECT:
                    /* An error within this call will result in a NULL arg */
                    pygi_arg_gobject_out_arg_from_py (object, &arg, transfer);
                    break;

                default:
                    g_assert_not_reached();
            }
            g_base_info_unref (info);
            break;
        }
        case GI_TYPE_TAG_GLIST:
        case GI_TYPE_TAG_GSLIST:
        {
            Py_ssize_t length;
            GITypeInfo *item_type_info;
            GSList *list = NULL;
            GITransfer item_transfer;
            Py_ssize_t i;

            if (object == Py_None) {
                arg.v_pointer = NULL;
                break;
            }

            length = PySequence_Length (object);
            if (length < 0) {
                break;
            }

            item_type_info = g_type_info_get_param_type (type_info, 0);
            g_assert (item_type_info != NULL);

            item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;

            for (i = length - 1; i >= 0; i--) {
                PyObject *py_item;
                GIArgument item;

                py_item = PySequence_GetItem (object, i);
                if (py_item == NULL) {
                    goto list_item_error;
                }

                item = _pygi_argument_from_object (py_item, item_type_info, item_transfer);

                Py_DECREF (py_item);

                if (PyErr_Occurred()) {
                    goto list_item_error;
                }

                if (type_tag == GI_TYPE_TAG_GLIST) {
                    list = (GSList *) g_list_prepend ( (GList *) list, item.v_pointer);
                } else {
                    list = g_slist_prepend (list, item.v_pointer);
                }

                continue;

list_item_error:
                /* Free everything we have converted so far. */
                _pygi_argument_release ( (GIArgument *) &list, type_info,
                                         GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
                list = NULL;

                _PyGI_ERROR_PREFIX ("Item %zd: ", i);
                break;
            }

            arg.v_pointer = list;

            g_base_info_unref ( (GIBaseInfo *) item_type_info);

            break;
        }
        case GI_TYPE_TAG_GHASH:
        {
            Py_ssize_t length;
            PyObject *keys;
            PyObject *values;
            GITypeInfo *key_type_info;
            GITypeInfo *value_type_info;
            GITypeTag key_type_tag;
            GHashFunc hash_func;
            GEqualFunc equal_func;
            GHashTable *hash_table;
            GITransfer item_transfer;
            Py_ssize_t i;


            if (object == Py_None) {
                arg.v_pointer = NULL;
                break;
            }

            length = PyMapping_Length (object);
            if (length < 0) {
                break;
            }

            keys = PyMapping_Keys (object);
            if (keys == NULL) {
                break;
            }

            values = PyMapping_Values (object);
            if (values == NULL) {
                Py_DECREF (keys);
                break;
            }

            key_type_info = g_type_info_get_param_type (type_info, 0);
            g_assert (key_type_info != NULL);

            value_type_info = g_type_info_get_param_type (type_info, 1);
            g_assert (value_type_info != NULL);

            key_type_tag = g_type_info_get_tag (key_type_info);

            switch (key_type_tag) {
                case GI_TYPE_TAG_UTF8:
                case GI_TYPE_TAG_FILENAME:
                    hash_func = g_str_hash;
                    equal_func = g_str_equal;
                    break;
                default:
                    hash_func = NULL;
                    equal_func = NULL;
            }

            hash_table = g_hash_table_new (hash_func, equal_func);
            if (hash_table == NULL) {
                PyErr_NoMemory();
                goto hash_table_release;
            }

            item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;

            for (i = 0; i < length; i++) {
                PyObject *py_key;
                PyObject *py_value;
                GIArgument key;
                GIArgument value;

                py_key = PyList_GET_ITEM (keys, i);
                py_value = PyList_GET_ITEM (values, i);

                key = _pygi_argument_from_object (py_key, key_type_info, item_transfer);
                if (PyErr_Occurred()) {
                    goto hash_table_item_error;
                }

                value = _pygi_argument_from_object (py_value, value_type_info, item_transfer);
                if (PyErr_Occurred()) {
                    _pygi_argument_release (&key, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
                    goto hash_table_item_error;
                }

                g_hash_table_insert (hash_table, key.v_pointer,
                                     _pygi_arg_to_hash_pointer (&value, g_type_info_get_tag (value_type_info)));
                continue;

hash_table_item_error:
                /* Free everything we have converted so far. */
                _pygi_argument_release ( (GIArgument *) &hash_table, type_info,
                                         GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
                hash_table = NULL;

                _PyGI_ERROR_PREFIX ("Item %zd: ", i);
                break;
            }

            arg.v_pointer = hash_table;

hash_table_release:
            g_base_info_unref ( (GIBaseInfo *) key_type_info);
            g_base_info_unref ( (GIBaseInfo *) value_type_info);
            Py_DECREF (keys);
            Py_DECREF (values);
            break;
        }
        case GI_TYPE_TAG_ERROR:
            PyErr_SetString (PyExc_NotImplementedError, "error marshalling is not supported yet");
            /* TODO */
            break;
        default:
            g_assert_not_reached ();
    }

    return arg;
}
Example #18
0
PyObject *
PyObject_Dir(PyObject *arg)
{
	/* Set exactly one of these non-NULL before the end. */
	PyObject *result = NULL;	/* result list */
	PyObject *masterdict = NULL;	/* result is masterdict.keys() */

	/* If NULL arg, return the locals. */
	if (arg == NULL) {
		PyObject *locals = PyEval_GetLocals();
		if (locals == NULL)
			goto error;
		result = PyMapping_Keys(locals);
		if (result == NULL)
			goto error;
	}

	/* Elif this is some form of module, we only want its dict. */
	else if (PyModule_Check(arg)) {
		masterdict = PyObject_GetAttrString(arg, "__dict__");
		if (masterdict == NULL)
			goto error;
		if (!PyDict_Check(masterdict)) {
			PyErr_SetString(PyExc_TypeError,
					"module.__dict__ is not a dictionary");
			goto error;
		}
	}

	/* Elif some form of type or class, grab its dict and its bases.
	   We deliberately don't suck up its __class__, as methods belonging
	   to the metaclass would probably be more confusing than helpful. */
	else if (PyType_Check(arg) || PyClass_Check(arg)) {
		masterdict = PyDict_New();
		if (masterdict == NULL)
			goto error;
		if (merge_class_dict(masterdict, arg) < 0)
			goto error;
	}

	/* Else look at its dict, and the attrs reachable from its class. */
	else {
		PyObject *itsclass;
		/* Create a dict to start with.  CAUTION:  Not everything
		   responding to __dict__ returns a dict! */
		masterdict = PyObject_GetAttrString(arg, "__dict__");
		if (masterdict == NULL) {
			PyErr_Clear();
			masterdict = PyDict_New();
		}
		else if (!PyDict_Check(masterdict)) {
			Py_DECREF(masterdict);
			masterdict = PyDict_New();
		}
		else {
			/* The object may have returned a reference to its
			   dict, so copy it to avoid mutating it. */
			PyObject *temp = PyDict_Copy(masterdict);
			Py_DECREF(masterdict);
			masterdict = temp;
		}
		if (masterdict == NULL)
			goto error;

		/* Merge in __members__ and __methods__ (if any).
		   XXX Would like this to go away someday; for now, it's
		   XXX needed to get at im_self etc of method objects. */
		if (merge_list_attr(masterdict, arg, "__members__") < 0)
			goto error;
		if (merge_list_attr(masterdict, arg, "__methods__") < 0)
			goto error;

		/* Merge in attrs reachable from its class.
		   CAUTION:  Not all objects have a __class__ attr. */
		itsclass = PyObject_GetAttrString(arg, "__class__");
		if (itsclass == NULL)
			PyErr_Clear();
		else {
			int status = merge_class_dict(masterdict, itsclass);
			Py_DECREF(itsclass);
			if (status < 0)
				goto error;
		}
	}

	assert((result == NULL) ^ (masterdict == NULL));
	if (masterdict != NULL) {
		/* The result comes from its keys. */
		assert(result == NULL);
		result = PyDict_Keys(masterdict);
		if (result == NULL)
			goto error;
	}

	assert(result);
	if (!PyList_Check(result)) {
		PyErr_Format(PyExc_TypeError,
			"Expected keys() to be a list, not '%.200s'",
			result->ob_type->tp_name);
		goto error;
	}
	if (PyList_Sort(result) != 0)
		goto error;
	else
		goto normal_return;

  error:
	Py_XDECREF(result);
	result = NULL;
	/* fall through */
  normal_return:
  	Py_XDECREF(masterdict);
	return result;
}