add __module__ for types and fix pickle bugs

This commit is contained in:
blueloveTH 2023-09-10 03:22:01 +08:00
parent 7a7ded5735
commit aaa6d60404
5 changed files with 27 additions and 12 deletions

View File

@ -51,6 +51,7 @@ typedef PyObject* (*BinaryFuncC)(VM*, PyObject*, PyObject*);
struct PyTypeInfo{ struct PyTypeInfo{
PyObject* obj; PyObject* obj;
Type base; Type base;
PyObject* mod;
Str name; Str name;
bool subclass_enabled; bool subclass_enabled;

View File

@ -2,15 +2,13 @@ import json
import builtins import builtins
_BASIC_TYPES = [int, float, str, bool, type(None)] _BASIC_TYPES = [int, float, str, bool, type(None)]
_MOD_T_SEP = "@"
def _find_class(path: str): def _find_class(path: str):
if "." not in path: if _MOD_T_SEP not in path:
g = globals()
if path in g:
return g[path]
return builtins.__dict__[path] return builtins.__dict__[path]
modname, name = path.split(".") modpath, name = path.split(_MOD_T_SEP)
return __import__(modname).__dict__[name] return __import__(modpath).__dict__[name]
def _find__new__(cls): def _find__new__(cls):
while cls is not None: while cls is not None:
@ -26,11 +24,19 @@ class _Pickler:
self.raw_memo = {} # id -> int self.raw_memo = {} # id -> int
self.memo = [] # int -> object self.memo = [] # int -> object
def _type_id(self, o: type):
assert type(o) is type
name = o.__name__
mod = o.__module__
if mod is not None:
name = mod.__path__ + _MOD_T_SEP + name
return name
def wrap(self, o): def wrap(self, o):
if type(o) in _BASIC_TYPES: if type(o) in _BASIC_TYPES:
return o return o
if type(o) is type: if type(o) is type:
return ["type", o.__name__] return ["type", self._type_id(o)]
index = self.raw_memo.get(id(o), None) index = self.raw_memo.get(id(o), None)
if index is not None: if index is not None:
@ -59,7 +65,7 @@ class _Pickler:
ret.append([[self.wrap(k), self.wrap(v)] for k,v in o.items()]) ret.append([[self.wrap(k), self.wrap(v)] for k,v in o.items()])
return [index] return [index]
_0 = o.__class__.__name__ _0 = self._type_id(type(o))
if hasattr(o, "__getnewargs__"): if hasattr(o, "__getnewargs__"):
_1 = o.__getnewargs__() # an iterable _1 = o.__getnewargs__() # an iterable

View File

@ -1540,6 +1540,11 @@ void VM::post_init(){
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])]; const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
return VAR(info.name); return VAR(info.name);
}); });
bind_property(_t(tp_type), "__module__", [](VM* vm, ArgsView args){
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
if(info.mod == nullptr) return vm->None;
return info.mod;
});
bind_property(_t(tp_bound_method), "__self__", [](VM* vm, ArgsView args){ bind_property(_t(tp_bound_method), "__self__", [](VM* vm, ArgsView args){
return CAST(BoundMethod&, args[0]).self; return CAST(BoundMethod&, args[0]).self;
}); });

View File

@ -131,7 +131,8 @@ namespace pkpy{
PyTypeInfo info{ PyTypeInfo info{
obj, obj,
base, base,
(mod!=nullptr && mod!=builtins) ? Str(OBJ_NAME(mod)+"."+name.sv()): name.sv(), mod,
name.sv(),
subclass_enabled, subclass_enabled,
}; };
if(mod != nullptr) mod->attr().set(name, obj); if(mod != nullptr) mod->attr().set(name, obj);
@ -636,8 +637,8 @@ void VM::_log_s_data(const char* title) {
#endif #endif
void VM::init_builtin_types(){ void VM::init_builtin_types(){
_all_types.push_back({heap._new<Type>(Type(1), Type(0)), -1, "object", true}); _all_types.push_back({heap._new<Type>(Type(1), Type(0)), -1, nullptr, "object", true});
_all_types.push_back({heap._new<Type>(Type(1), Type(1)), 0, "type", false}); _all_types.push_back({heap._new<Type>(Type(1), Type(1)), 0, nullptr, "type", false});
tp_object = 0; tp_type = 1; tp_object = 0; tp_type = 1;
tp_int = _new_type_object("int"); tp_int = _new_type_object("int");

View File

@ -1,7 +1,9 @@
from pickle import dumps, loads, _wrap, _unwrap from pickle import dumps, loads, _wrap, _unwrap
def test(x): def test(x):
ok = x == loads(dumps(x)) y = dumps(x)
# print(y.decode())
ok = x == loads(y)
if not ok: if not ok:
_0 = _wrap(x) _0 = _wrap(x)
_1 = _unwrap(_0) _1 = _unwrap(_0)