(ctx: &'static Context, class: &'static Py<PyType>)
| 132 | const TP_FLAGS: PyTypeFlags = PyTypeFlags::DEFAULT; |
| 133 | |
| 134 | fn extend_class(ctx: &'static Context, class: &'static Py<PyType>) |
| 135 | where |
| 136 | Self: Sized, |
| 137 | { |
| 138 | #[cfg(debug_assertions)] |
| 139 | { |
| 140 | assert!(class.slots.flags.is_created_with_flags()); |
| 141 | } |
| 142 | |
| 143 | let _ = ctx.intern_str(Self::NAME); // intern type name |
| 144 | |
| 145 | if Self::TP_FLAGS.has_feature(PyTypeFlags::HAS_DICT) { |
| 146 | let __dict__ = identifier!(ctx, __dict__); |
| 147 | class.set_attr( |
| 148 | __dict__, |
| 149 | ctx.new_static_getset( |
| 150 | "__dict__", |
| 151 | class, |
| 152 | crate::builtins::object::object_get_dict, |
| 153 | crate::builtins::object::object_set_dict, |
| 154 | ) |
| 155 | .into(), |
| 156 | ); |
| 157 | } |
| 158 | Self::impl_extend_class(ctx, class); |
| 159 | if let Some(doc) = Self::DOC { |
| 160 | // Only set __doc__ if it doesn't already exist (e.g., as a member descriptor) |
| 161 | // This matches CPython's behavior in type_dict_set_doc |
| 162 | let doc_attr_name = identifier!(ctx, __doc__); |
| 163 | if class.attributes.read().get(doc_attr_name).is_none() { |
| 164 | class.set_attr(doc_attr_name, ctx.new_str(doc).into()); |
| 165 | } |
| 166 | } |
| 167 | if let Some(module_name) = Self::MODULE_NAME { |
| 168 | let module_key = identifier!(ctx, __module__); |
| 169 | // Don't overwrite a getset descriptor for __module__ (e.g. TypeAliasType |
| 170 | // has an instance-level __module__ getset that should not be replaced) |
| 171 | let has_getset = class |
| 172 | .attributes |
| 173 | .read() |
| 174 | .get(module_key) |
| 175 | .is_some_and(|v| v.downcastable::<crate::builtins::PyGetSet>()); |
| 176 | if !has_getset { |
| 177 | class.set_attr(module_key, ctx.new_str(module_name).into()); |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | // Don't add __new__ attribute if slot_new is inherited from object |
| 182 | // (Python doesn't add __new__ to __dict__ for inherited slots) |
| 183 | // Exception: object itself should have __new__ in its dict |
| 184 | if let Some(slot_new) = class.slots.new.load() { |
| 185 | let object_new = ctx.types.object_type.slots.new.load(); |
| 186 | let is_object_itself = core::ptr::eq(class, ctx.types.object_type); |
| 187 | let is_inherited_from_object = !is_object_itself |
| 188 | && object_new.is_some_and(|obj_new| slot_new as usize == obj_new as usize); |
| 189 | |
| 190 | if !is_inherited_from_object { |
| 191 | let bound_new = |
nothing calls this directly
no test coverage detected