Changeset View
Changeset View
Standalone View
Standalone View
source/blender/python/intern/bpy_rna.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
| Show First 20 Lines • Show All 2,217 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| PointerRNA newptr; | PointerRNA newptr; | ||||
| Py_ssize_t keynum_abs = keynum; | Py_ssize_t keynum_abs = keynum; | ||||
| PYRNA_PROP_CHECK_OBJ(self); | PYRNA_PROP_CHECK_OBJ(self); | ||||
| PYRNA_PROP_COLLECTION_ABS_INDEX(NULL); | PYRNA_PROP_COLLECTION_ABS_INDEX(NULL); | ||||
| if (RNA_property_collection_lookup_int_has_fn(self->prop)) { | |||||
| if (RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) { | if (RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) { | ||||
| return pyrna_struct_CreatePyObject(&newptr); | return pyrna_struct_CreatePyObject(&newptr); | ||||
| } | } | ||||
| } | |||||
| else { | |||||
| /* No callback defined, just iterate and find the nth item. */ | |||||
| const int key = (int)keynum; | |||||
| PyObject *result = NULL; | |||||
| bool found = false; | |||||
| CollectionPropertyIterator iter; | |||||
| RNA_property_collection_begin(&self->ptr, self->prop, &iter); | |||||
| for (int i = 0; iter.valid; RNA_property_collection_next(&iter), i++) { | |||||
| if (i == key) { | |||||
| result = pyrna_struct_CreatePyObject(&iter.ptr); | |||||
| found = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* It's important to end the iterator after `result` has been created | |||||
| * so iterators may optionally invalidate items that were iterated over, see: T100286. */ | |||||
| RNA_property_collection_end(&iter); | |||||
| if (found) { | |||||
| return result; | |||||
| } | |||||
| } | |||||
mont29: Would add a comment here about why this is needed, and the fact that this may return an… | |||||
| const int len = RNA_property_collection_length(&self->ptr, self->prop); | const int len = RNA_property_collection_length(&self->ptr, self->prop); | ||||
| if (keynum_abs >= len) { | if (keynum_abs >= len) { | ||||
| PyErr_Format(PyExc_IndexError, | PyErr_Format(PyExc_IndexError, | ||||
| "bpy_prop_collection[index]: " | "bpy_prop_collection[index]: " | ||||
| "index %d out of range, size %d", | "index %d out of range, size %d", | ||||
| keynum, | keynum, | ||||
| len); | len); | ||||
| ▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, const char *keyname) | static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, const char *keyname) | ||||
| { | { | ||||
| PointerRNA newptr; | PointerRNA newptr; | ||||
| PYRNA_PROP_CHECK_OBJ(self); | PYRNA_PROP_CHECK_OBJ(self); | ||||
| if (RNA_property_collection_lookup_string_has_fn(self->prop)) { | |||||
| if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { | if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { | ||||
| return pyrna_struct_CreatePyObject(&newptr); | return pyrna_struct_CreatePyObject(&newptr); | ||||
| } | } | ||||
| } | |||||
| else { | |||||
| /* No callback defined, just iterate and find the nth item. */ | |||||
| const int keylen = strlen(keyname); | |||||
| char name[256]; | |||||
| int namelen; | |||||
| PyObject *result = NULL; | |||||
| bool found = false; | |||||
| CollectionPropertyIterator iter; | |||||
| RNA_property_collection_begin(&self->ptr, self->prop, &iter); | |||||
| for (int i = 0; iter.valid; RNA_property_collection_next(&iter), i++) { | |||||
| PropertyRNA *nameprop = RNA_struct_name_property(iter.ptr.type); | |||||
| char *nameptr = RNA_property_string_get_alloc( | |||||
| &iter.ptr, nameprop, name, sizeof(name), &namelen); | |||||
| if ((keylen == namelen) && STREQ(nameptr, keyname)) { | |||||
| found = true; | |||||
| } | |||||
| if ((char *)&name != nameptr) { | |||||
| MEM_freeN(nameptr); | |||||
| } | |||||
| if (found) { | |||||
| result = pyrna_struct_CreatePyObject(&iter.ptr); | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* It's important to end the iterator after `result` has been created | |||||
| * so iterators may optionally invalidate items that were iterated over, see: T100286. */ | |||||
| RNA_property_collection_end(&iter); | |||||
| if (found) { | |||||
| return result; | |||||
| } | |||||
| } | |||||
| PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname); | PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| // static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) | // static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) | ||||
Not Done Inline ActionsThis could be de-duplicated with the same code above maybe? E.g. in a pyrna_prop_collection_subscript_end ? mont29: This could be de-duplicated with the same code above maybe? E.g. in a… | |||||
Done Inline ActionsAgree with the goal of de-duplicating boiler plate. if (found) {
if (result && (pyrna_prop_collection_subscript_is_valid_or_error(result) == -1)) {
Py_DECREF(result);
result = NULL; /* The exception has been set. */
}
return result;
}Could be replaced with: if (found) {
pyrna_prop_collection_subscript_is_valid_or_error_and_clear(&result);
return result;
}campbellbarton: Agree with the goal of de-duplicating boiler plate.
An issue with this is it moves `Py_DECREF`… | |||||
Not Done Inline ActionsFair enough, can keep it like for now. mont29: Fair enough, can keep it like for now. | |||||
| /** | /** | ||||
| * Special case: `bpy.data.objects["some_id_name", "//some_lib_name.blend"]` | * Special case: `bpy.data.objects["some_id_name", "//some_lib_name.blend"]` | ||||
| * also for: `bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback)` | * also for: `bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback)` | ||||
| * | * | ||||
| * \note | * \note | ||||
| * error codes since this is not to be called directly from Python, | * error codes since this is not to be called directly from Python, | ||||
| * this matches Python's `__contains__` values C-API. | * this matches Python's `__contains__` values C-API. | ||||
| * - -1: exception set | * - -1: exception set | ||||
| ▲ Show 20 Lines • Show All 6,903 Lines • Show Last 20 Lines | |||||
Would add a comment here about why this is needed, and the fact that this may return an 'invalidated' PyObject in case the actual data memory is freed by the call to RNA_property_collection_end (with link back to the deg instance objects iterator code) ?
Same with the string subscript function below.