Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9fbd66a

Browse files
authored
GH-133912: FixPyObject_GenericSetDict to handle inline values (GH-134725)
1 parentf6324bc commit9fbd66a

File tree

6 files changed

+95
-53
lines changed

6 files changed

+95
-53
lines changed

‎Include/internal/pycore_object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,8 @@ enum _PyAnnotateFormat {
10101010
_Py_ANNOTATE_FORMAT_STRING=4,
10111011
};
10121012

1013+
int_PyObject_SetDict(PyObject*obj,PyObject*value);
1014+
10131015
#ifdef__cplusplus
10141016
}
10151017
#endif

‎Lib/test/test_capi/test_type.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,13 @@ def test_manual_heap_type(self):
264264
ManualHeapType=_testcapi.ManualHeapType
265265
foriinrange(100):
266266
self.assertIsInstance(ManualHeapType(),ManualHeapType)
267+
268+
deftest_extension_managed_dict_type(self):
269+
ManagedDictType=_testcapi.ManagedDictType
270+
obj=ManagedDictType()
271+
obj.foo=42
272+
self.assertEqual(obj.foo,42)
273+
self.assertEqual(obj.__dict__, {'foo':42})
274+
obj.__dict__= {'bar':3}
275+
self.assertEqual(obj.__dict__, {'bar':3})
276+
self.assertEqual(obj.bar,3)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix the C API function ``PyObject_GenericSetDict`` to handle extension
2+
classes with inline values.

‎Modules/_testcapimodule.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3175,6 +3175,48 @@ create_manual_heap_type(void)
31753175
return (PyObject*)type;
31763176
}
31773177

3178+
typedefstruct {
3179+
PyObject_VAR_HEAD
3180+
}ManagedDictObject;
3181+
3182+
intManagedDict_traverse(PyObject*self,visitprocvisit,void*arg) {
3183+
PyObject_VisitManagedDict(self,visit,arg);
3184+
Py_VISIT(Py_TYPE(self));
3185+
return0;
3186+
}
3187+
3188+
intManagedDict_clear(PyObject*self) {
3189+
PyObject_ClearManagedDict(self);
3190+
return0;
3191+
}
3192+
3193+
staticPyGetSetDefManagedDict_getset[]= {
3194+
{"__dict__",PyObject_GenericGetDict,PyObject_GenericSetDict,NULL,NULL},
3195+
{NULL,NULL,NULL,NULL,NULL},
3196+
};
3197+
3198+
staticPyType_SlotManagedDict_slots[]= {
3199+
{Py_tp_new, (void*)PyType_GenericNew},
3200+
{Py_tp_getset, (void*)ManagedDict_getset},
3201+
{Py_tp_traverse, (void*)ManagedDict_traverse},
3202+
{Py_tp_clear, (void*)ManagedDict_clear},
3203+
{0}
3204+
};
3205+
3206+
staticPyType_SpecManagedDict_spec= {
3207+
"_testcapi.ManagedDictType",
3208+
sizeof(ManagedDictObject),
3209+
0,// itemsize
3210+
Py_TPFLAGS_DEFAULT |Py_TPFLAGS_BASETYPE |Py_TPFLAGS_MANAGED_DICT |Py_TPFLAGS_HEAPTYPE |Py_TPFLAGS_HAVE_GC,
3211+
ManagedDict_slots
3212+
};
3213+
3214+
staticPyObject*
3215+
create_managed_dict_type(void)
3216+
{
3217+
returnPyType_FromSpec(&ManagedDict_spec);
3218+
}
3219+
31783220
staticstructPyModuleDef_testcapimodule= {
31793221
PyModuleDef_HEAD_INIT,
31803222
.m_name="_testcapi",
@@ -3315,6 +3357,13 @@ PyInit__testcapi(void)
33153357
returnNULL;
33163358
}
33173359

3360+
PyObject*managed_dict_type=create_managed_dict_type();
3361+
if (managed_dict_type==NULL) {
3362+
returnNULL;
3363+
}
3364+
if (PyModule_Add(m,"ManagedDictType",managed_dict_type)<0) {
3365+
returnNULL;
3366+
}
33183367

33193368
/* Include tests from the _testcapi/ directory */
33203369
if (_PyTestCapi_Init_Vectorcall(m)<0) {

‎Objects/object.c

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,40 +2016,11 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
20162016
int
20172017
PyObject_GenericSetDict(PyObject*obj,PyObject*value,void*context)
20182018
{
2019-
PyObject**dictptr=_PyObject_GetDictPtr(obj);
2020-
if (dictptr==NULL) {
2021-
if (_PyType_HasFeature(Py_TYPE(obj),Py_TPFLAGS_INLINE_VALUES)&&
2022-
_PyObject_GetManagedDict(obj)==NULL
2023-
) {
2024-
/* Was unable to convert to dict */
2025-
PyErr_NoMemory();
2026-
}
2027-
else {
2028-
PyErr_SetString(PyExc_AttributeError,
2029-
"This object has no __dict__");
2030-
}
2031-
return-1;
2032-
}
20332019
if (value==NULL) {
20342020
PyErr_SetString(PyExc_TypeError,"cannot delete __dict__");
20352021
return-1;
20362022
}
2037-
if (!PyDict_Check(value)) {
2038-
PyErr_Format(PyExc_TypeError,
2039-
"__dict__ must be set to a dictionary, "
2040-
"not a '%.200s'",Py_TYPE(value)->tp_name);
2041-
return-1;
2042-
}
2043-
Py_BEGIN_CRITICAL_SECTION(obj);
2044-
PyObject*olddict=*dictptr;
2045-
FT_ATOMIC_STORE_PTR_RELEASE(*dictptr,Py_NewRef(value));
2046-
#ifdefPy_GIL_DISABLED
2047-
_PyObject_XDecRefDelayed(olddict);
2048-
#else
2049-
Py_XDECREF(olddict);
2050-
#endif
2051-
Py_END_CRITICAL_SECTION();
2052-
return0;
2023+
return_PyObject_SetDict(obj,value);
20532024
}
20542025

20552026

‎Objects/typeobject.c

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3948,10 +3948,39 @@ subtype_dict(PyObject *obj, void *context)
39483948
returnPyObject_GenericGetDict(obj,context);
39493949
}
39503950

3951+
int
3952+
_PyObject_SetDict(PyObject*obj,PyObject*value)
3953+
{
3954+
if (value!=NULL&& !PyDict_Check(value)) {
3955+
PyErr_Format(PyExc_TypeError,
3956+
"__dict__ must be set to a dictionary, "
3957+
"not a '%.200s'",Py_TYPE(value)->tp_name);
3958+
return-1;
3959+
}
3960+
if (Py_TYPE(obj)->tp_flags&Py_TPFLAGS_MANAGED_DICT) {
3961+
return_PyObject_SetManagedDict(obj,value);
3962+
}
3963+
PyObject**dictptr=_PyObject_ComputedDictPointer(obj);
3964+
if (dictptr==NULL) {
3965+
PyErr_SetString(PyExc_AttributeError,
3966+
"This object has no __dict__");
3967+
return-1;
3968+
}
3969+
Py_BEGIN_CRITICAL_SECTION(obj);
3970+
PyObject*olddict=*dictptr;
3971+
FT_ATOMIC_STORE_PTR_RELEASE(*dictptr,Py_NewRef(value));
3972+
#ifdefPy_GIL_DISABLED
3973+
_PyObject_XDecRefDelayed(olddict);
3974+
#else
3975+
Py_XDECREF(olddict);
3976+
#endif
3977+
Py_END_CRITICAL_SECTION();
3978+
return0;
3979+
}
3980+
39513981
staticint
39523982
subtype_setdict(PyObject*obj,PyObject*value,void*context)
39533983
{
3954-
PyObject**dictptr;
39553984
PyTypeObject*base;
39563985

39573986
base=get_builtin_base_with_dict(Py_TYPE(obj));
@@ -3969,28 +3998,7 @@ subtype_setdict(PyObject *obj, PyObject *value, void *context)
39693998
}
39703999
returnfunc(descr,obj,value);
39714000
}
3972-
/* Almost like PyObject_GenericSetDict, but allow __dict__ to be deleted. */
3973-
if (value!=NULL&& !PyDict_Check(value)) {
3974-
PyErr_Format(PyExc_TypeError,
3975-
"__dict__ must be set to a dictionary, "
3976-
"not a '%.200s'",Py_TYPE(value)->tp_name);
3977-
return-1;
3978-
}
3979-
3980-
if (Py_TYPE(obj)->tp_flags&Py_TPFLAGS_MANAGED_DICT) {
3981-
return_PyObject_SetManagedDict(obj,value);
3982-
}
3983-
else {
3984-
dictptr=_PyObject_ComputedDictPointer(obj);
3985-
if (dictptr==NULL) {
3986-
PyErr_SetString(PyExc_AttributeError,
3987-
"This object has no __dict__");
3988-
return-1;
3989-
}
3990-
Py_CLEAR(*dictptr);
3991-
*dictptr=Py_XNewRef(value);
3992-
}
3993-
return0;
4001+
return_PyObject_SetDict(obj,value);
39944002
}
39954003

39964004
staticPyObject*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp