mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30: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_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_Dtor dtor; // destructor for this type, NULL if no dtor
|
||||
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
|
||||
typedef struct py_TValue {
|
||||
int64_t _[2];
|
||||
py_Type type;
|
||||
bool is_ptr;
|
||||
int extra;
|
||||
int64_t _i64;
|
||||
} py_TValue;
|
||||
#endif
|
||||
|
||||
@ -355,6 +358,12 @@ PK_API const char* py_tpname(py_Type type);
|
||||
/// 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;
|
||||
|
||||
/// 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.
|
||||
/// Raise `TypeError` if the check fails.
|
||||
PK_API bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
||||
@ -760,11 +769,11 @@ enum py_PredefinedType {
|
||||
tp_bool,
|
||||
tp_str,
|
||||
tp_str_iterator,
|
||||
tp_list, // c11_vector
|
||||
tp_tuple, // N slots
|
||||
tp_list, // c11_vector
|
||||
tp_tuple, // N slots
|
||||
tp_list_iterator, // 1 slot
|
||||
tp_tuple_iterator, // 1 slot
|
||||
tp_slice, // 3 slots (start, stop, step)
|
||||
tp_slice, // 3 slots (start, stop, step)
|
||||
tp_range,
|
||||
tp_range_iterator,
|
||||
tp_module,
|
||||
|
@ -81,6 +81,10 @@ static void py_TypeInfo__common_init(py_Name name,
|
||||
self->is_python = is_python;
|
||||
self->is_sealed = is_sealed;
|
||||
|
||||
self->getattribute = NULL;
|
||||
self->setattribute = NULL;
|
||||
self->delattribute = NULL;
|
||||
|
||||
self->annotations = *py_NIL();
|
||||
self->dtor = dtor;
|
||||
self->on_end_subclass = NULL;
|
||||
@ -150,4 +154,15 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo
|
||||
py_Type type = pk_newtype(name, base, module, dtor, false, false);
|
||||
if(module) py_setdict(module, py_name(name), py_tpobject(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) {
|
||||
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
|
||||
py_TypeInfo* ti = pk_typeinfo(self->type);
|
||||
if(ti->getattribute) return ti->getattribute(self, name);
|
||||
|
||||
py_Ref cls_var = pk_tpfindname(ti, name);
|
||||
if(cls_var) {
|
||||
// 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) {
|
||||
py_Type type = self->type;
|
||||
py_Ref cls_var = py_tpfindname(type, name);
|
||||
py_TypeInfo* ti = pk_typeinfo(self->type);
|
||||
if(ti->setattribute) return ti->setattribute(self, name, val);
|
||||
|
||||
py_Ref cls_var = pk_tpfindname(ti, name);
|
||||
if(cls_var) {
|
||||
// handle descriptor
|
||||
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) {
|
||||
py_TypeInfo* ti = pk_typeinfo(self->type);
|
||||
if(ti->delattribute) return ti->delattribute(self, name);
|
||||
|
||||
if(self->is_ptr && self->_obj->slots == -1) {
|
||||
if(py_deldict(self, name)) return true;
|
||||
return AttributeError(self, name);
|
||||
|
Loading…
x
Reference in New Issue
Block a user