From: Samuele P. <ped...@st...> - 2006-06-12 20:37:09
|
Frank Wierzbicki wrote: > Hmmm. I had a feeling I was under-implementing this. I'll back it > out and try again. > I fear that there's not much text around explaning the exact semantics of __slots__, the PyPy code in http://codespeak.net/svn/pypy/dist/pypy/objspace/std/typeobject.py, especially the __init__ (typedefs in PyPy correspond a bit to the role of underlying java classes in Jython) and in http://codespeak.net/svn/pypy/dist/pypy/interpreter/typedef.py _buildusercls which is in some sense a version of what gderived does, although it doesn't need to produce delegation code for the __xxx__ methods because that's handled more uniformly in PyPy. are probably your best bet. > -Frank > > On 6/12/06, Samuele Pedroni <ped...@st...> wrote: > >> fwi...@us... wrote: >> > Revision: 2816 >> > Author: fwierzbicki >> > Date: 2006-06-12 12:31:11 -0700 (Mon, 12 Jun 2006) >> > ViewCVS: http://svn.sourceforge.net/jython/?rev=2816&view=rev >> > >> > Log Message: >> > ----------- >> > A very simple-minded implementation of slots. It may have bugs >> since I have >> > written it to pass the "slots" test in test_descr. It does not do >> anything about >> > __weakref__ yet, since __weakref__ needs some work yet. >> > >> >> I don't understand the need for changes in PyObject, >> __dict__ and slots should really be reflected by the presence absence >> of descriptors in the type dict, is not an implementation detail, >> taking a slot descriptor and using it directly is quite common! >> >> > Modified Paths: >> > -------------- >> > trunk/jython/src/org/python/core/PyObject.java >> > trunk/jython/src/org/python/core/PyType.java >> > Modified: trunk/jython/src/org/python/core/PyObject.java >> > =================================================================== >> > --- trunk/jython/src/org/python/core/PyObject.java 2006-06-12 >> 01:47:39 UTC (rev 2815) >> > +++ trunk/jython/src/org/python/core/PyObject.java 2006-06-12 >> 19:31:11 UTC (rev 2816) >> > @@ -2,6 +2,7 @@ >> > package org.python.core; >> > >> > import java.text.MessageFormat; >> > +import java.util.List; >> > >> > /** >> > * All objects known to the Jython runtime system are represented >> > @@ -2820,14 +2821,25 @@ >> > throw Py.AttributeError("object internal __delete__ impl is >> abstract"); >> > } >> > >> > + private void slotscheck(String name) { >> > + List slotnames = objtype.getSlotnames(); >> > + if (slotnames != null) { >> > + if (!slotnames.contains(name) && >> !slotnames.contains("__dict__")) { >> > + noAttributeError(name); >> > + } >> > + } >> > + } >> > + >> > // name must be interned >> > final PyObject object___findattr__(String name) { >> > - >> > PyObject descr = objtype.lookup(name); >> > PyObject res; >> > >> > if (descr != null) { >> > if (descr.isDataDescr()) { >> > + if (objtype.hide_dict && name.equals("__dict__")) { >> > + noAttributeError(name); >> > + } >> > res = descr.__get__(this, objtype); >> > if (res != null) >> > return res; >> > @@ -2856,6 +2868,7 @@ >> > if (descr != null) { >> > set = descr.implementsDescrSet(); >> > if (set && descr.isDataDescr()) { >> > + //slotscheck(name); >> > descr.__set__(this, value); >> > return; >> > } >> > @@ -2863,16 +2876,19 @@ >> > >> > PyObject obj_dict = fastGetDict(); >> > if (obj_dict != null) { >> > + slotscheck(name); >> > obj_dict.__setitem__(name, value); >> > return; >> > } >> > >> > if (set) { >> > + //XXX: need slotscheck here? >> > descr.__set__(this, value); >> > } >> > >> > - if (descr != null) >> > + if (descr != null) { >> > readonlyAttributeError(name); >> > + } >> > >> > noAttributeError(name); >> > } >> > >> > Modified: trunk/jython/src/org/python/core/PyType.java >> > =================================================================== >> > --- trunk/jython/src/org/python/core/PyType.java 2006-06-12 >> 01:47:39 UTC (rev 2815) >> > +++ trunk/jython/src/org/python/core/PyType.java 2006-06-12 >> 19:31:11 UTC (rev 2816) >> > @@ -8,6 +8,7 @@ >> > import java.util.ArrayList; >> > import java.util.HashMap; >> > import java.util.Iterator; >> > +import java.util.List; >> > >> > /** >> > * first-class Python type. >> > @@ -61,7 +62,7 @@ >> > } >> > >> > } >> > - dict.__setitem__("mro", new PyClassMethod(new >> PyMethodDescr("mro",PyType.class,0,1,new exposed_mro(null,null)))); >> > + dict.__setitem__("mro",new PyClassMethod(new >> PyMethodDescr("mro",PyType.class,0,1,new exposed_mro(null,null)))); >> > class exposed___getattribute__ extends >> PyBuiltinFunctionNarrow { >> > >> > private PyType self; >> > @@ -381,16 +382,22 @@ >> > return null; >> > } >> > >> > + public List getSlotnames() { >> > + return slotnames; >> > + } >> > + >> > + >> > private String name; >> > private PyType base; >> > private PyObject[] bases; >> > private PyObject dict; >> > private PyObject[] mro; >> > private Class underlying_class; >> > + private List slotnames; >> > >> > private boolean non_instantiable = false; >> > >> > - boolean has_set, has_delete; >> > + boolean has_set, has_delete, hide_dict; >> > >> > private boolean needs_finalizer; >> > >> > @@ -701,7 +708,32 @@ >> > } >> > >> > // xxx also __doc__ __module__ >> > - // xxx __slots__! >> > + List slotnames = null; >> > + boolean hide_dict = false; >> > + >> > + PyObject slots = dict.__finditem__("__slots__"); >> > + if (slots != null) { >> > + hide_dict = true; >> > + if (base.nuserslots > 0) { >> > + nuserslots = base.nuserslots; >> > + slotnames = new ArrayList(base.getSlotnames()); >> > + } >> > + else { >> > + slotnames = new ArrayList(); >> > + } >> > + PyObject iter = slots.__iter__(); >> > + PyObject slotname; >> > + for (; (slotname = iter.__iternext__())!= null; ) { >> > + confirmIdentifier(slotname); >> > + String slotstring = slotname.toString(); >> > + if (slotstring.equals("__dict__")) { >> > + hide_dict = false; >> > + } >> > + slotnames.add(mangleName(name, slotstring)); >> > + nuserslots += 1; >> > + } >> > + } >> > + >> > PyType newtype; >> > if (new_.for_type == metatype) { >> > newtype = new PyType(); // xxx set metatype >> > @@ -715,9 +747,12 @@ >> > >> > newtype.needs_userdict = needs_userdict; >> > newtype.nuserslots = nuserslots; >> > + newtype.hide_dict = hide_dict; >> > >> > newtype.dict = dict; >> > >> > + newtype.slotnames = slotnames; >> > + >> > // special case __new__, if function => static method >> > PyObject tmp = dict.__finditem__("__new__"); >> > if (tmp != null && tmp instanceof PyFunction) { // xxx java >> functions? >> > @@ -1442,5 +1477,41 @@ >> > >> > return invoke_new_(new_,this,true,args,keywords); >> > } >> > + //XXX: consider pulling this out into a generally accessible place >> > + // I bet this is duplicated more or less in other places. >> > + private static void confirmIdentifier(PyObject o) { >> > + String msg = "__slots__ must be identifiers"; >> > + if (o == Py.None) { >> > + throw Py.TypeError(msg); >> > + } >> > + String identifier = o.toString(); >> > + if (identifier == null || >> > + identifier.length() < 1 || >> > + (!Character.isLetter(identifier.charAt(0)) && >> identifier.charAt(0) != '_') >> > + ) { >> > + throw Py.TypeError(msg); >> > + } >> > + char[] chars = identifier.toCharArray(); >> > + for(int i = 0; i < chars.length; i++) { >> > + if (!Character.isLetterOrDigit(chars[i]) && chars[i] != >> '_') { >> > + throw Py.TypeError(msg); >> > + } >> > + } >> > + } >> > >> > + //XXX: copied from CodeCompiler.java and changed variable names. >> > + // Maybe this should go someplace for all classes to use. >> > + private static String mangleName(String classname, String >> methodname) { >> > + if (classname != null && methodname.startsWith("__") && >> > + !methodname.endsWith("__")) >> > + { >> > + //remove leading '_' from classname >> > + int i = 0; >> > + while (classname.charAt(i) == '_') >> > + i++; >> > + return "_"+classname.substring(i)+methodname; >> > + } >> > + return methodname; >> > + } >> > + >> > } >> > >> > >> > This was sent by the SourceForge.net collaborative development >> platform, the world's largest Open Source development site. >> > >> > >> > >> > _______________________________________________ >> > Jython-checkins mailing list >> > Jyt...@li... >> > https://lists.sourceforge.net/lists/listinfo/jython-checkins >> >> >> >> >> _______________________________________________ >> Jython-checkins mailing list >> Jyt...@li... >> https://lists.sourceforge.net/lists/listinfo/jython-checkins >> |