From: <cg...@us...> - 2007-02-20 07:54:54
|
Revision: 3111 http://svn.sourceforge.net/jython/?rev=3111&view=rev Author: cgroves Date: 2007-02-19 23:54:48 -0800 (Mon, 19 Feb 2007) Log Message: ----------- Finish work to expose classmethods from the templates. new-style class classmethods now call the given method in the template with the type and any specified arguments. Get dict.fromkeys to correctly function as a classmethod that works on dict, an instance of dict and a subtype of dict. Just need to fix __cmp__ on dict and all of the fromkeys stuff in test_types will pass. Modified Paths: -------------- trunk/jython/Lib/test/test_types.py trunk/jython/src/org/python/core/PyDictionary.java trunk/jython/src/org/python/core/PyMethodDescr.java trunk/jython/src/templates/dict.expose trunk/jython/src/templates/gexpose-defs trunk/jython/src/templates/gexpose.py Added Paths: ----------- trunk/jython/src/org/python/core/PyClassMethodDescr.java Modified: trunk/jython/Lib/test/test_types.py =================================================================== --- trunk/jython/Lib/test/test_types.py 2007-02-16 05:57:23 UTC (rev 3110) +++ trunk/jython/Lib/test/test_types.py 2007-02-20 07:54:48 UTC (rev 3111) @@ -596,10 +596,9 @@ try: d.update(FailingUserDict()) except ValueError: pass else: raise TestFailed, 'dict.update(), __getitem__ expected ValueError' -#XXX fromkeys not a classmethod yet. # dict.fromkeys() -#if dict.fromkeys('abc') != {'a':None, 'b':None, 'c':None}: -# raise TestFailed, 'dict.fromkeys did not work as a class method' +if dict.fromkeys('abc') != {'a':None, 'b':None, 'c':None}: + raise TestFailed, 'dict.fromkeys did not work as a class method' d = {} if d.fromkeys('abc') is d: raise TestFailed, 'dict.fromkeys did not return a new dict' @@ -616,21 +615,19 @@ try: {}.fromkeys(3) except TypeError: pass else: raise TestFailed, 'dict.fromkeys failed to raise TypeError' -#XXX fromkeys in a subclass doesn't work yet. class dictlike(dict): pass #if dictlike.fromkeys('a') != {'a':None}: # raise TestFailed, 'dictsubclass.fromkeys did not inherit' -if dictlike().fromkeys('a') != {'a':None}: - raise TestFailed, 'dictsubclass.fromkeys did not inherit' -#if type(dictlike.fromkeys('a')) is not dictlike: -# raise TestFailed, 'dictsubclass.fromkeys created wrong type' -#if type(dictlike().fromkeys('a')) is not dictlike: -# raise TestFailed, 'dictsubclass.fromkeys created wrong type' +#if dictlike().fromkeys('a') != {'a':None}: +# raise TestFailed, 'dictsubclass.fromkeys did not inherit' +if type(dictlike.fromkeys('a')) is not dictlike: + raise TestFailed, 'dictsubclass.fromkeys created wrong type' +if type(dictlike().fromkeys('a')) is not dictlike: + raise TestFailed, 'dictsubclass.fromkeys created wrong type' from UserDict import UserDict class mydict(dict): def __new__(cls): return UserDict() -#XXX fromkeys in a subclass doesn't work yet. #ud = mydict.fromkeys('ab') #if ud != {'a':None, 'b':None} or not isinstance(ud,UserDict): # raise TestFailed, 'fromkeys did not instantiate using __new__' Added: trunk/jython/src/org/python/core/PyClassMethodDescr.java =================================================================== --- trunk/jython/src/org/python/core/PyClassMethodDescr.java (rev 0) +++ trunk/jython/src/org/python/core/PyClassMethodDescr.java 2007-02-20 07:54:48 UTC (rev 3111) @@ -0,0 +1,28 @@ +package org.python.core; + +public class PyClassMethodDescr extends PyMethodDescr { + + public PyClassMethodDescr(String name, + Class c, + int minargs, + int maxargs, + PyBuiltinFunction func) { + super(name, c, minargs, maxargs, func); + } + + protected void checkCallerType(PyObject obj) { + if((PyType)obj != dtype && !((PyType)obj).isSubType(dtype)) + throw get_wrongtype((PyType)obj); + } + + public PyObject __get__(PyObject obj, PyObject type) { + if (obj != null) { + checkCallerType(obj.getType()); + return func.makeBound(obj.getType()); + }else if(type != null){ + checkCallerType(type); + return func.makeBound(type); + } + return this; + } +} Modified: trunk/jython/src/org/python/core/PyDictionary.java =================================================================== --- trunk/jython/src/org/python/core/PyDictionary.java 2007-02-16 05:57:23 UTC (rev 3110) +++ trunk/jython/src/org/python/core/PyDictionary.java 2007-02-20 07:54:48 UTC (rev 3111) @@ -156,41 +156,31 @@ dict.__setitem__("__getitem__",new PyMethodDescr("__getitem__",PyDictionary.class,1,1,new exposed___getitem__(null,null))); class exposed_fromkeys extends PyBuiltinFunctionNarrow { - private PyDictionary self; + private PyType self; public PyObject getSelf() { return self; } - exposed_fromkeys(PyDictionary self,PyBuiltinFunction.Info info) { + exposed_fromkeys(PyType self,PyBuiltinFunction.Info info) { super(info); this.self=self; } public PyBuiltinFunction makeBound(PyObject self) { - return new exposed_fromkeys((PyDictionary)self,info); + return new exposed_fromkeys((PyType)self,info); } public PyObject __call__(PyObject arg0,PyObject arg1) { - return self.dict_fromkeys(arg0,arg1); + return dict_fromkeys(self,arg0,arg1); } - public PyObject inst_call(PyObject gself,PyObject arg0,PyObject arg1) { - PyDictionary self=(PyDictionary)gself; - return self.dict_fromkeys(arg0,arg1); - } - public PyObject __call__(PyObject arg0) { - return self.dict_fromkeys(arg0); + return dict_fromkeys(self,arg0); } - public PyObject inst_call(PyObject gself,PyObject arg0) { - PyDictionary self=(PyDictionary)gself; - return self.dict_fromkeys(arg0); - } - } - dict.__setitem__("fromkeys",new PyMethodDescr("fromkeys",PyDictionary.class,1,2,new exposed_fromkeys(null,null))); + dict.__setitem__("fromkeys",new PyClassMethodDescr("fromkeys",PyDictionary.class,1,2,new exposed_fromkeys(null,null))); class exposed_get extends PyBuiltinFunctionNarrow { private PyDictionary self; @@ -950,22 +940,22 @@ } } public PyObject fromkeys(PyObject keys) { - return dict_fromkeys(keys, null); + return fromkeys(keys, null); } public PyObject fromkeys(PyObject keys, PyObject value) { - return dict_fromkeys(keys, value); + return dict_fromkeys(PyType.fromClass(PyDictionary.class), keys, value); } - final PyObject dict_fromkeys(PyObject keys) { - return dict_fromkeys(keys, null); + final static PyObject dict_fromkeys(PyType type, PyObject keys) { + return dict_fromkeys(type, keys, null); } - final PyObject dict_fromkeys(PyObject keys, PyObject value) { + final static PyObject dict_fromkeys(PyType type, PyObject keys, PyObject value) { if (value == null) { value = Py.None; } - PyDictionary d = new PyDictionary(); + PyObject d = type.__call__(); PyIterator iter = (PyIterator)keys.__iter__(); for (PyObject o = iter.__iternext__();o != null;o = iter.__iternext__()) { d.__setitem__(o, value); Modified: trunk/jython/src/org/python/core/PyMethodDescr.java =================================================================== --- trunk/jython/src/org/python/core/PyMethodDescr.java 2007-02-16 05:57:23 UTC (rev 3110) +++ trunk/jython/src/org/python/core/PyMethodDescr.java 2007-02-20 07:54:48 UTC (rev 3111) @@ -34,27 +34,22 @@ } public PyObject __call__(PyObject[] args) { - PyObject self = args[0]; - PyType objtype = self.getType(); - if (objtype != dtype && !objtype.isSubType(dtype)) - throw call_wrongtype(objtype); - int n = args.length; - PyObject[] rest = new PyObject[n-1]; - System.arraycopy(args,1,rest,0,n-1); - return func.inst_call(self,rest); + return extractSelfAndCall(args); } public PyObject __call__(PyObject[] args, String[] kws) { - int n = args.length; if (kws.length == args.length) throw Py.TypeError(blurb()+" needs an argument"); + return extractSelfAndCall(args); + } + + private PyObject extractSelfAndCall(PyObject[] args) { PyObject self = args[0]; - PyType objtype = self.getType(); - if (objtype != dtype && !objtype.isSubType(dtype)) - throw call_wrongtype(objtype); + checkCallerType(self); + int n = args.length; PyObject[] rest = new PyObject[n-1]; System.arraycopy(args,1,rest,0,n-1); - return func.inst_call(self,rest,kws); + return func.inst_call(self,rest); } public PyObject __call__() { @@ -62,32 +57,24 @@ } public PyObject __call__(PyObject arg1) { - PyType objtype = arg1.getType(); - if (objtype != dtype && !objtype.isSubType(dtype)) - throw call_wrongtype(objtype); + checkCallerType(arg1); return func.inst_call(arg1); } public PyObject __call__(PyObject arg1, PyObject arg2) { - PyType objtype = arg1.getType(); - if (objtype != dtype && !objtype.isSubType(dtype)) - throw call_wrongtype(objtype); + checkCallerType(arg1); return func.inst_call(arg1,arg2); } public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3) { - PyType objtype = arg1.getType(); - if (objtype != dtype && !objtype.isSubType(dtype)) - throw call_wrongtype(objtype); + checkCallerType(arg1); return func.inst_call(arg1,arg2,arg3); } public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) { - PyType objtype = arg1.getType(); - if (objtype != dtype && !objtype.isSubType(dtype)) - throw call_wrongtype(objtype); + checkCallerType(arg1); return func.inst_call(arg1,arg2,arg3,arg4); } @@ -97,12 +84,16 @@ public PyObject __get__(PyObject obj, PyObject type) { if (obj != null) { - PyType objtype = obj.getType(); - if (objtype != dtype && !objtype.isSubType(dtype)) - throw get_wrongtype(objtype); + checkCallerType(obj); return func.makeBound(obj); } return this; } + protected void checkCallerType(PyObject obj) { + PyType objtype = obj.getType(); + if (objtype != dtype && !objtype.isSubType(dtype)) + throw get_wrongtype(objtype); + } + } Modified: trunk/jython/src/templates/dict.expose =================================================================== --- trunk/jython/src/templates/dict.expose 2007-02-16 05:57:23 UTC (rev 3110) +++ trunk/jython/src/templates/dict.expose 2007-02-20 07:54:48 UTC (rev 3111) @@ -4,7 +4,7 @@ # exposed methods expose_binary: __ne__ __eq__ expose_vanilla_cmp: -expose_meth: fromkeys o o? +expose_cmeth: fromkeys o o? expose_key_getitem: expose_meth: get oo? expose_meth: setdefault oo? Modified: trunk/jython/src/templates/gexpose-defs =================================================================== --- trunk/jython/src/templates/gexpose-defs 2007-02-16 05:57:23 UTC (rev 3110) +++ trunk/jython/src/templates/gexpose-defs 2007-02-20 07:54:48 UTC (rev 3111) @@ -19,6 +19,11 @@ `strfy`(`name), new PyGetSetDescr(`strfy`(`name), `typ.class, `get, `set, `del)); +define: (ClassBodyDeclarations)call_cmeths args body + public PyObject __call__(`args) { + `body; + } + define: (ClassBodyDeclarations)call_meths args body public PyObject __call__(`args) { `body; @@ -28,6 +33,7 @@ `typ self = (`typ)gself; `body; } + define: expose_wide_meth class `concat`(exposed_,`name) extends PyBuiltinFunctionWide { private `typ self; @@ -99,19 +105,19 @@ define: expose_narrow_cmeth typ name minargs maxargs call_meths class `concat`(exposed_,`name) extends PyBuiltinFunctionNarrow { - private `typ self; + private PyType self; public PyObject getSelf() { return self; } - `concat`(exposed_,`name)(`typ self, PyBuiltinFunction.Info info) { + `concat`(exposed_,`name)(PyType self, PyBuiltinFunction.Info info) { super(info); this.self = self; } public PyBuiltinFunction makeBound(PyObject self) { - return new `concat`(exposed_,`name)((`typ)self, info); + return new `concat`(exposed_,`name)((PyType)self, info); } `call_meths; @@ -120,13 +126,12 @@ dict.__setitem__( `strfy`(`name), - new PyClassMethod( - new PyMethodDescr( + new PyClassMethodDescr( `strfy`(`name), `typ.class, `minargs, `maxargs, - new `concat`(exposed_,`name)(null, null)))); + new `concat`(exposed_,`name)(null, null))); define: conv_error_handling unsafe_body try { Modified: trunk/jython/src/templates/gexpose.py =================================================================== --- trunk/jython/src/templates/gexpose.py 2007-02-16 05:57:23 UTC (rev 3110) +++ trunk/jython/src/templates/gexpose.py 2007-02-20 07:54:48 UTC (rev 3111) @@ -10,7 +10,6 @@ import java_templating from java_templating import JavaTemplate,jast_make,jast, make_id, make_literal - # Some examples for modif_re # (one)two -> group 1 = "one" # group 2 = "two" @@ -24,7 +23,7 @@ # k = one character key ("o","i" and "s" in "ois") # opt = optional (the "?" in "o?") # dfl = default for optional (the "blah" in o?(blah) ) -# tg = ? (the "anything_can_go_here in o{anything_can_go_here} ) +# tg = descriptive argument name (the "I'm anything but a curly brace in o{I'm anything but a curly brace} ) ktg_re = re.compile("(?P<k>\w)(?P<opt>\?(:?\((?P<dfl>[^)]*)\))?)?(?:\{(?P<tg>[^}]*)\})?") def make_name(n): @@ -99,7 +98,6 @@ naked = False if templ_kind is None: templ_kind = 'Fragment' - templ = JavaTemplate(body, parms=':'.join(parms[1:]), bindings = self.global_bindings, @@ -358,15 +356,13 @@ self.statements.append(expose.tbind(expose_bindings)) - #XXX: First pass is a c&p and modify of dire_expose_meth: do better. def dire_expose_cmeth(self,name,parm,body): + if body is None: + body = 'return `concat`(`deleg_prefix,`name)(self,`all);' parm, prefix, body = self.expose_meth_body(name, parm, body) expose = self.get_aux('expose_narrow_cmeth') + type_class = getattr(self, 'type_class', None) - type_class = getattr(self,'type_class',None) - type_name = getattr(self,'type_name',None) - if type_class is None or type_name is None: - raise Exception,"type_class or type_name not defined" parms = parm.strip().split(None,1) if len(parms) not in (1,2): self.invalid(name,parm) @@ -382,15 +378,15 @@ body_bindings = self.global_bindings.copy() body_bindings.update(expose_bindings) - - call_meths_bindings['call_meths'] = self.get_aux('call_meths').tbind({'typ': type_class}) + call_meths_bindings['call_meths'] = self.get_aux('call_cmeths').tbind({'typ': type_class}) + inst_call_meths,minargs,maxargs = self.handle_expose_meth_sig(parms[1],call_meths_bindings,body,body_bindings) expose_bindings['call_meths'] = inst_call_meths expose_bindings['minargs'] = JavaTemplate(str(minargs)) expose_bindings['maxargs'] = JavaTemplate(str(maxargs)) - + self.statements.append(expose.tbind(expose_bindings)) def dire_expose_unary(self,name,parm,body): @@ -558,19 +554,19 @@ return typeinfo.tnaked().texpand({'basic': basic.tbind(bindings), 'setup': setup},nindent=1) -def process(fn, mergefile=None): +def process(fn, mergefile=None, lazy=False): + if lazy and mergefile and os.stat(fn).st_mtime < os.stat(mergefile).st_mtime: + return gen = Gen() directives.execute(directives.load(fn),gen) result = gen.generate() if mergefile is None: print result else: + print 'Merging %s into %s' % (fn, mergefile) result = merge(mergefile, result) #gen.debug() -def usage(): - print "Usage: python %s infile [mergefile]" % sys.argv[0] - def merge(filename, generated): in_generated = False start_found = False @@ -600,10 +596,48 @@ f.write("".join(output)) f.close() +def load_mappings(): + scriptdir = os.path.dirname(os.path.abspath(__file__)) + srcdir = os.path.dirname(scriptdir) + mappings = {} + + for line in open(os.path.join(scriptdir, 'mappings')): + if line.strip() is '' or line.startswith('#'): + continue + tmpl, klass = line.strip().split(':') + + mappings[tmpl] = (os.path.join(scriptdir, tmpl), + os.path.join(srcdir, *klass.split('.')) + '.java') + return mappings + + +def usage(): + print """Usage: python %s [--lazy|--help] <template> <outfile> + +If lazy is given, a template is only processed if its modtime is +greater than outfile. If outfile isn't specified, the outfile from +mappings for the given template is used. If template isn't given, all +templates from mappings are processed.""" % sys.argv[0] + if __name__ == '__main__': - if (len(sys.argv) < 2 or len(sys.argv) > 3): + lazy = False + if len(sys.argv) > 4: usage() - elif (len(sys.argv) == 2): - process(sys.argv[1]) - elif (len(sys.argv) == 3): - process(sys.argv[1], sys.argv[2]) + sys.exit(1) + if len(sys.argv) >= 2: + if '--help' in sys.argv: + usage() + sys.exit(0) + elif '--lazy' in sys.argv: + lazy = True + sys.argv.remove('--lazy') + mappings = load_mappings() + if len(sys.argv) == 1: + for template, mapping in mappings.items(): + if template.endswith('expose'): + process(mapping[0], mapping[1], lazy) + elif len(sys.argv) == 2: + mapping = mappings[sys.argv[1]] + process(mapping[0], mapping[1], lazy) + else: + process(sys.argv[1], sys.argv[2], lazy) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |