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; }
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; }
/* 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; }
/* {{{ 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; }
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; }
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; }
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; }
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; }
} } 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);
/** * \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; }
static PyObject * proxy_keys(proxyobject *pp) { return PyMapping_Keys(pp->dict); }
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; }
/* 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; }
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; }
/**************************** * 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)) {
PyObject *glue_PyMapping_Keys(PyObject *o) { return PyMapping_Keys(o); }
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; }
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; }