mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
add py_tphookattributes
This commit is contained in:
parent
2f296994ae
commit
b6cefdeedc
@ -16,6 +16,10 @@ typedef struct py_TypeInfo {
|
|||||||
bool is_python; // is it a python class? (not derived from c object)
|
bool is_python; // is it a python class? (not derived from c object)
|
||||||
bool is_sealed; // can it be subclassed?
|
bool is_sealed; // can it be subclassed?
|
||||||
|
|
||||||
|
bool (*getattribute)(py_Ref self, py_Name name);
|
||||||
|
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val);
|
||||||
|
bool (*delattribute)(py_Ref self, py_Name name);
|
||||||
|
|
||||||
py_TValue annotations;
|
py_TValue annotations;
|
||||||
py_Dtor dtor; // destructor for this type, NULL if no dtor
|
py_Dtor dtor; // destructor for this type, NULL if no dtor
|
||||||
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
|
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
|
||||||
|
@ -30,7 +30,10 @@ typedef void (*py_Dtor)(void*);
|
|||||||
|
|
||||||
#ifdef PK_IS_PUBLIC_INCLUDE
|
#ifdef PK_IS_PUBLIC_INCLUDE
|
||||||
typedef struct py_TValue {
|
typedef struct py_TValue {
|
||||||
int64_t _[2];
|
py_Type type;
|
||||||
|
bool is_ptr;
|
||||||
|
int extra;
|
||||||
|
int64_t _i64;
|
||||||
} py_TValue;
|
} py_TValue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -355,6 +358,12 @@ PK_API const char* py_tpname(py_Type type);
|
|||||||
/// Call a type to create a new instance.
|
/// Call a type to create a new instance.
|
||||||
PK_API bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
PK_API bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
||||||
|
|
||||||
|
/// Set attribute hooks for the given type.
|
||||||
|
PK_API void py_tphookattributes(py_Type type,
|
||||||
|
bool (*getattribute)(py_Ref self, py_Name name),
|
||||||
|
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val),
|
||||||
|
bool (*delattribute)(py_Ref self, py_Name name));
|
||||||
|
|
||||||
/// Check if the object is an instance of the given type exactly.
|
/// Check if the object is an instance of the given type exactly.
|
||||||
/// Raise `TypeError` if the check fails.
|
/// Raise `TypeError` if the check fails.
|
||||||
PK_API bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
PK_API bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
||||||
|
@ -81,6 +81,10 @@ static void py_TypeInfo__common_init(py_Name name,
|
|||||||
self->is_python = is_python;
|
self->is_python = is_python;
|
||||||
self->is_sealed = is_sealed;
|
self->is_sealed = is_sealed;
|
||||||
|
|
||||||
|
self->getattribute = NULL;
|
||||||
|
self->setattribute = NULL;
|
||||||
|
self->delattribute = NULL;
|
||||||
|
|
||||||
self->annotations = *py_NIL();
|
self->annotations = *py_NIL();
|
||||||
self->dtor = dtor;
|
self->dtor = dtor;
|
||||||
self->on_end_subclass = NULL;
|
self->on_end_subclass = NULL;
|
||||||
@ -151,3 +155,14 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo
|
|||||||
if(module) py_setdict(module, py_name(name), py_tpobject(type));
|
if(module) py_setdict(module, py_name(name), py_tpobject(type));
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void py_tphookattributes(py_Type type,
|
||||||
|
bool (*getattribute)(py_Ref self, py_Name name),
|
||||||
|
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val),
|
||||||
|
bool (*delattribute)(py_Ref self, py_Name name)) {
|
||||||
|
assert(type);
|
||||||
|
py_TypeInfo* ti = pk_typeinfo(type);
|
||||||
|
ti->getattribute = getattribute;
|
||||||
|
ti->setattribute = setattribute;
|
||||||
|
ti->delattribute = delattribute;
|
||||||
|
}
|
||||||
|
@ -122,6 +122,8 @@ int py_next(py_Ref val) {
|
|||||||
bool py_getattr(py_Ref self, py_Name name) {
|
bool py_getattr(py_Ref self, py_Name name) {
|
||||||
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
|
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
|
||||||
py_TypeInfo* ti = pk_typeinfo(self->type);
|
py_TypeInfo* ti = pk_typeinfo(self->type);
|
||||||
|
if(ti->getattribute) return ti->getattribute(self, name);
|
||||||
|
|
||||||
py_Ref cls_var = pk_tpfindname(ti, name);
|
py_Ref cls_var = pk_tpfindname(ti, name);
|
||||||
if(cls_var) {
|
if(cls_var) {
|
||||||
// handle descriptor
|
// handle descriptor
|
||||||
@ -212,8 +214,10 @@ bool py_getattr(py_Ref self, py_Name name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
|
bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
|
||||||
py_Type type = self->type;
|
py_TypeInfo* ti = pk_typeinfo(self->type);
|
||||||
py_Ref cls_var = py_tpfindname(type, name);
|
if(ti->setattribute) return ti->setattribute(self, name, val);
|
||||||
|
|
||||||
|
py_Ref cls_var = pk_tpfindname(ti, name);
|
||||||
if(cls_var) {
|
if(cls_var) {
|
||||||
// handle descriptor
|
// handle descriptor
|
||||||
if(py_istype(cls_var, tp_property)) {
|
if(py_istype(cls_var, tp_property)) {
|
||||||
@ -239,6 +243,9 @@ bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool py_delattr(py_Ref self, py_Name name) {
|
bool py_delattr(py_Ref self, py_Name name) {
|
||||||
|
py_TypeInfo* ti = pk_typeinfo(self->type);
|
||||||
|
if(ti->delattribute) return ti->delattribute(self, name);
|
||||||
|
|
||||||
if(self->is_ptr && self->_obj->slots == -1) {
|
if(self->is_ptr && self->_obj->slots == -1) {
|
||||||
if(py_deldict(self, name)) return true;
|
if(py_deldict(self, name)) return true;
|
||||||
return AttributeError(self, name);
|
return AttributeError(self, name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user