Index: src/org/python/core/PyGetSetDescr.java =================================================================== --- src/org/python/core/PyGetSetDescr.java (revision 3001) +++ src/org/python/core/PyGetSetDescr.java (working copy) @@ -10,6 +10,8 @@ private Method set_meth; + private Method del_meth; + private Class getset_type; public PyGetSetDescr(PyType dtype, @@ -17,6 +19,18 @@ Class c, String get, String set) { + this(dtype, name, c, get, set, null); + } + public PyGetSetDescr(String name, Class c, String get, String set) { + this(PyType.fromClass(c), name, c, get, set, null); + } + + public PyGetSetDescr(PyType dtype, + String name, + Class c, + String get, + String set, + String del) { this.name = name; this.dtype = dtype; try { @@ -36,10 +50,19 @@ if(Modifier.isStatic(set_meth.getModifiers())) throw Py.SystemError("static getset not supported"); } - } + if(del != null) { + try { + del_meth = c.getMethod(del, new Class[] {}); + } catch(NoSuchMethodException e) { + throw Py.SystemError("bogus getset spec"); + } + if(Modifier.isStatic(del_meth.getModifiers())) + throw Py.SystemError("static getset not supported"); + } + } - public PyGetSetDescr(String name, Class c, String get, String set) { - this(PyType.fromClass(c), name, c, get, set); + public PyGetSetDescr(String name, Class c, String get, String set, String del) { + this(PyType.fromClass(c), name, c, get, set, del); } public String toString() { @@ -97,6 +120,23 @@ } } + public void __delete__(PyObject obj) { + try { + if(obj != null) { + PyType objtype = obj.getType(); + if(objtype != dtype && !objtype.isSubType(dtype)) + throw get_wrongtype(objtype); + del_meth.invoke(obj, new Object[0]); + } + } catch(IllegalArgumentException e) { + throw Py.JavaError(e); + } catch(IllegalAccessException e) { + throw Py.JavaError(e); // unexpected + } catch(InvocationTargetException e) { + throw Py.JavaError(e); + } + } + /** * @see org.python.core.PyObject#implementsDescrSet() */ @@ -104,10 +144,15 @@ return set_meth != null; } + public boolean implementsDescrDelete() { + return del_meth != null; + } + /** * @see org.python.core.PyObject#isDataDescr() */ public boolean isDataDescr() { return true; } + } Index: src/org/python/core/PyObject.java =================================================================== --- src/org/python/core/PyObject.java (revision 3001) +++ src/org/python/core/PyObject.java (working copy) @@ -2791,7 +2791,16 @@ return null; } + public void setDict(PyObject newDict) { + // fallback if setDict not implemented in subclass + throw Py.TypeError("can't set attribute '__dict__' of instance of " + getType().safeRepr()); + } + public void delDict() { + // fallback to error + throw Py.TypeError("can't delete attribute '__dict__' of instance of '" + getType().safeRepr()+ "'"); + } + public boolean implementsDescrSet() { return objtype.has_set; } Index: src/org/python/core/PyType.java =================================================================== --- src/org/python/core/PyType.java (revision 3001) +++ src/org/python/core/PyType.java (working copy) @@ -21,7 +21,7 @@ public static final String exposed_name="type"; public static void typeSetup(PyObject dict,PyType.Newstyle marker) { - dict.__setitem__("__dict__",new PyGetSetDescr("__dict__",PyType.class,"getDict",null)); + dict.__setitem__("__dict__",new PyGetSetDescr("__dict__",PyType.class,"getDict","setDict","delDict")); dict.__setitem__("__name__",new PyGetSetDescr("__name__",PyType.class,"fastGetName",null)); dict.__setitem__("__base__",new PyGetSetDescr("__base__",PyType.class,"getBase",null)); dict.__setitem__("__bases__",new PyGetSetDescr("__bases__",PyType.class,"getBases",null)); @@ -732,7 +732,7 @@ // __dict__ descriptor if (newtype.needs_userdict && newtype.lookup("__dict__")==null) { - dict.__setitem__("__dict__",new PyGetSetDescr(newtype,"__dict__",PyObject.class,"getDict",null)); + dict.__setitem__("__dict__",new PyGetSetDescr(newtype,"__dict__",PyObject.class,"getDict","setDict","delDict")); } newtype.has_set = newtype.lookup("__set__") != null; @@ -1296,7 +1296,15 @@ public PyObject getDict() { // xxx return dict-proxy return dict; } + + public void setDict(PyObject newDict) { + throw Py.TypeError("can't set attribute '__dict__' of type '" + name + "'"); + } + public void delDict() { + throw Py.TypeError("can't delete attribute '__dict__' of type '" + name + "'"); + } + public Object __tojava__(Class c) { if (underlying_class!= null &&( c == Object.class || c == Class.class || c == Serializable.class)) { Index: src/templates/gderived-defs =================================================================== --- src/templates/gderived-defs (revision 3000) +++ src/templates/gderived-defs (working copy) @@ -70,6 +70,19 @@ return dict; } + public void setDict(PyObject newDict) { + if (newDict instanceof PyStringMap || newDict instanceof PyDictionary ) { + dict = newDict; + } + else { + throw Py.TypeError("__dict__ must be set to a Dictionary " + newDict.getClass().getName()); + } + } + + public void delDict() { + dict = new PyStringMap(); + } + define: (ClassBodyDeclarations)ctr public `concat`(`base,Derived)(PyType subtype,`extraargs) { super(subtype,`extra);