From arigo at codespeak.net Sat Dec 4 13:38:00 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Dec 2004 13:38:00 +0100 (MET) Subject: [pypy-svn] r7749 - in pypy/trunk/src: goal pypy/objspace/flow pypy/translator pypy/translator/tool pypy/translator/tool/pygame Message-ID: <20041204123800.3CE9A5AF22@thoth.codespeak.net> Author: arigo Date: Sat Dec 4 13:37:58 2004 New Revision: 7749 Added: pypy/trunk/src/pypy/translator/tool/graphpage.py - copied, changed from r7715, pypy/trunk/src/pypy/translator/tool/pygame/flowviewer.py pypy/trunk/src/pypy/translator/tool/graphserver.py pypy/trunk/src/pypy/translator/tool/pygame/graphclient.py (contents, props changed) Removed: pypy/trunk/src/pypy/translator/tool/pygame/flowviewer.py Modified: pypy/trunk/src/goal/translate_pypy.py pypy/trunk/src/pypy/objspace/flow/model.py pypy/trunk/src/pypy/translator/tool/flowtrace.py pypy/trunk/src/pypy/translator/tool/make_dot.py pypy/trunk/src/pypy/translator/tool/pygame/drawgraph.py pypy/trunk/src/pypy/translator/tool/pygame/graphdisplay.py pypy/trunk/src/pypy/translator/translator.py Log: translate_pypy can now be a "web" server sending graphs to the "browser" in translator/tool/pygame/. (The protocol is not HTTP, though.) It is useful both for inspecting graphs generated by translate_pypy on a remote supercomputer, and to track the progress of a running translate_pypy -- the "server" is started early and runs in parallel with the annotation phase. (In the latter case, red blocks correspond to functions that containing pending blocks, not just dead-locked blocked blocks.) To enable this, translate_pypy must be run with a port number to listen to. For the stand-alone graph client run pypy/translator/tool/pygame/graphclient. Modified: pypy/trunk/src/goal/translate_pypy.py ============================================================================== --- pypy/trunk/src/goal/translate_pypy.py (original) +++ pypy/trunk/src/goal/translate_pypy.py Sat Dec 4 13:37:58 2004 @@ -4,6 +4,8 @@ """ Command-line options for translate_pypy: + port Listen on the given port number for connexions + (see pypy/translator/tool/pygame/graphclient.py) -text Don't start the Pygame viewer -no-a Don't infer annotations, just translate everything -no-c Don't generate the C code @@ -46,6 +48,8 @@ # caches (as far as analyzing the entry_point is concerned) entry_point() t = Translator(entry_point, verbose=True, simplifying=True) + if listen_port: + run_async_server() if not options['-no-a']: a = t.annotate([]) a.simplify() @@ -138,6 +142,13 @@ cleanup(*cleanup_args) return threading.Thread(target=_run_in_thread, args=()) +def run_async_server(): + from pypy.translator.tool import graphpage, graphserver + homepage = graphpage.TranslatorPage(t) + graphserver.run_server(homepage, port=listen_port, background=True) + options['-text'] = True + + if __name__ == '__main__': options = {'-text': False, @@ -149,12 +160,16 @@ '-tcc': False, '-no-d': False, } + listen_port = None for arg in sys.argv[1:]: if arg in ('-h', '--help'): print __doc__.strip() sys.exit() - assert arg in options, "unknown option %r" % (arg,) - options[arg] = True + try: + listen_port = int(arg) + except ValueError: + assert arg in options, "unknown option %r" % (arg,) + options[arg] = True if options['-tcc']: os.environ['PYPY_CC'] = 'tcc -shared -o "%s.so" "%s.c"' if options['-no-d']: @@ -186,14 +201,15 @@ print "don't know about", x def run_server(): - from pypy.translator.tool.pygame.flowviewer import TranslatorLayout + from pypy.translator.tool.graphpage import TranslatorPage + from pypy.translator.tool.pygame.graphclient import get_layout from pypy.translator.tool.pygame.graphdisplay import GraphDisplay import pygame if not options['-no-mark-some-objects']: find_someobjects(t, quiet=True) - display = GraphDisplay(TranslatorLayout(t)) + display = GraphDisplay(get_layout(TranslatorPage(t))) async_quit = display.async_quit return display.run, async_quit, pygame.quit Modified: pypy/trunk/src/pypy/objspace/flow/model.py ============================================================================== --- pypy/trunk/src/pypy/objspace/flow/model.py (original) +++ pypy/trunk/src/pypy/objspace/flow/model.py Sat Dec 4 13:37:58 2004 @@ -43,8 +43,8 @@ return self._onlyex def show(self): - from pypy.translator.tool.pygame.flowviewer import SingleGraphLayout - SingleGraphLayout(self).display() + from pypy.translator.tool.graphpage import SingleGraphPage + SingleGraphPage(self).display() class Link: def __init__(self, args, target, exitcase=None): Modified: pypy/trunk/src/pypy/translator/tool/flowtrace.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/flowtrace.py (original) +++ pypy/trunk/src/pypy/translator/tool/flowtrace.py Sat Dec 4 13:37:58 2004 @@ -260,12 +260,12 @@ """Shows the control flow graph with annotations if computed. Requires 'dot' and pygame.""" from pypy.translator.tool.pygame.graphdisplay import GraphDisplay - from pypy.translator.tool.pygame.flowviewer import FlowGraphLayout + from pypy.translator.tool.graphpage import FlowGraphPage from pypy.translator.translator import Translator t = Translator(func) t.simplify() #t.annotate([int]) - GraphDisplay(FlowGraphLayout(t)).run() + FlowGraphPage(t).display() def timeit(num, func, *args): from time import time as now Copied: pypy/trunk/src/pypy/translator/tool/graphpage.py (from r7715, pypy/trunk/src/pypy/translator/tool/pygame/flowviewer.py) ============================================================================== --- pypy/trunk/src/pypy/translator/tool/pygame/flowviewer.py (original) +++ pypy/trunk/src/pypy/translator/tool/graphpage.py Sat Dec 4 13:37:58 2004 @@ -1,27 +1,52 @@ -import autopath import inspect -from pypy.translator.tool.pygame.drawgraph import GraphLayout -from pypy.translator.tool.make_dot import DotGen +from pypy.objspace.flow.model import traverse +from pypy.translator.tool.make_dot import DotGen, make_dot, make_dot_graphs from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS from pypy.annotation import model from pypy.annotation.classdef import ClassDef from pypy.tool.uid import uid -class SingleGraphLayout(GraphLayout): - """ A GraphLayout showing a single precomputed FlowGraph.""" +class GraphPage: + """Base class for the server-side content of one of the 'pages' + (one graph) sent over to and displayed by the client. + """ + def __init__(self, *args): + self.args = args + + def content(self): + """Compute the content of the page. + This doesn't modify the page in place; it returns a new GraphPage. + """ + if hasattr(self, 'source'): + return self + else: + new = self.__class__() + new.source = '' # '''dot source''' + new.links = {} # {'word': 'statusbar text'} + new.compute(*self.args) # defined in subclasses + return new + + def followlink(self, word): + raise KeyError + + def display(self): + "Display a graph page locally." + from pypy.translator.tool.pygame.graphclient import get_layout + get_layout(self).display() - def __init__(self, graph): - from pypy.translator.tool.make_dot import make_dot - fn = make_dot(graph.name, graph, target='plain') - GraphLayout.__init__(self, fn) +class SingleGraphPage(GraphPage): + """ A GraphPage showing a single precomputed FlowGraph.""" -class VariableHistoryGraphLayout(GraphLayout): - """ A GraphLayout showing the history of variable bindings. """ + def compute(self, graph): + self.source = make_dot(graph.name, graph, target=None) - def __init__(self, translator, name, info, caused_by, history, func_names): - self.links = {} + +class VariableHistoryGraphPage(GraphPage): + """ A GraphPage showing the history of variable bindings. """ + + def compute(self, translator, name, info, caused_by, history, func_names): self.linkinfo = {} self.translator = translator self.func_names = func_names @@ -44,9 +69,7 @@ label += '\\n' + self.createlink(caused_by) dotgen.emit_node(str(n+1), shape="box", label=label) dotgen.emit_edge(str(n+1), str(n)) - links = self.links # GraphLayout.__init__ will override it with {} - GraphLayout.__init__(self, dotgen.generate(target='plain')) - self.links.update(links) + self.source = dotgen.generate(target=None) def createlink(self, position_key, wording='Caused by a call from'): fn, block, pos = position_key @@ -66,14 +89,13 @@ def followlink(self, funcname): fn, block, pos = self.linkinfo[funcname] # It would be nice to focus on the block - return FlowGraphLayout(self.translator, [fn], self.func_names) + return FlowGraphPage(self.translator, [fn], self.func_names) -class FlowGraphLayout(GraphLayout): - """ A GraphLayout showing a Flow Graph (or a few flow graphs). +class FlowGraphPage(GraphPage): + """ A GraphPage showing a Flow Graph (or a few flow graphs). """ - def __init__(self, translator, functions=None, func_names=None): - from pypy.translator.tool.make_dot import make_dot_graphs + def compute(self, translator, functions=None, func_names=None): self.translator = translator self.annotator = translator.annotator self.func_names = func_names or {} @@ -84,8 +106,7 @@ for block, was_annotated in self.annotator.annotated.items(): if not was_annotated: block.fillcolor = "red" - fn = make_dot_graphs(graphs[0].name + "_graph", gs, target='plain') - GraphLayout.__init__(self, fn) + self.source = make_dot_graphs(graphs[0].name+"_graph", gs, target=None) # make the dictionary of links -- one per annotated variable self.binding_history = {} self.current_value = {} @@ -109,7 +130,7 @@ caused_by = self.caused_by[varname] history = list(self.binding_history.get(varname, [])) history.reverse() - return VariableHistoryGraphLayout(self.translator, varname, cur_value, + return VariableHistoryGraphPage(self.translator, varname, cur_value, caused_by, history, self.func_names) @@ -127,10 +148,10 @@ return '\\n'.join(lines) -class ClassDefLayout(GraphLayout): - """A GraphLayout showing the attributes of a class. +class ClassDefPage(GraphPage): + """A GraphPage showing the attributes of a class. """ - def __init__(self, translator, cdef): + def compute(self, translator, cdef): self.translator = translator dotgen = DotGen(cdef.cls.__name__, rankdir="LR") @@ -152,14 +173,14 @@ prevcdef = cdef cdef = cdef.basedef - GraphLayout.__init__(self, dotgen.generate(target='plain')) + self.source = dotgen.generate(target=None) -class TranslatorLayout(GraphLayout): - """A GraphLayout showing a the call graph between functions +class TranslatorPage(GraphPage): + """A GraphPage showing a the call graph between functions as well as the class hierarchy.""" - def __init__(self, translator): + def compute(self, translator): self.translator = translator self.object_by_name = {} self.name_by_object = {} @@ -168,10 +189,16 @@ # show the call graph functions = translator.functions + blocked_functions = {} if translator.annotator: - blocked_functions = translator.annotator.blocked_functions - else: - blocked_functions = {} + # don't use translator.annotator.blocked_functions here because + # it is not populated until the annotator finishes. + annotated = translator.annotator.annotated + for fn, graph in translator.flowgraphs.items(): + def visit(node): + if annotated.get(node) is False: + blocked_functions[fn] = True + traverse(visit, graph) highlight_functions = getattr(translator, 'highlight_functions', {}) # XXX dotgen.emit_node('entry', fillcolor="green", shape="octagon", label="Translator\\nEntry Point") @@ -201,7 +228,7 @@ dotgen.emit_node(nameof(classdef), label=data, shape="box") dotgen.emit_edge(nameof(classdef.basedef), nameof(classdef)) - GraphLayout.__init__(self, dotgen.generate(target='plain')) + self.source = dotgen.generate(target=None) # link the function names to the individual flow graphs for name, obj in self.object_by_name.iteritems(): @@ -232,9 +259,9 @@ def followlink(self, name): obj = self.object_by_name[name] if isinstance(obj, ClassDef): - return ClassDefLayout(self.translator, obj) + return ClassDefPage(self.translator, obj) else: - return FlowGraphLayout(self.translator, [obj], self.name_by_object) + return FlowGraphPage(self.translator, [obj], self.name_by_object) def nameof(obj, cache={}): @@ -246,22 +273,3 @@ result = '%s__0x%x' % (getattr(obj, '__name__', ''), uid(obj)) cache[obj] = result return result - -# ____________________________________________________________ - -if __name__ == '__main__': - from pypy.translator.translator import Translator - from pypy.translator.test import snippet - from pypy.translator.tool.pygame.graphdisplay import GraphDisplay - - t = Translator(snippet.powerset) - #t.simplify() - a = t.annotate([int]) - a.simplify() - GraphDisplay(FlowGraphLayout(t)).run() - -## t = Translator(snippet._methodcall1) -## t.simplify() -## a = t.annotate([int]) -## a.simplify() -## GraphDisplay(TranslatorLayout(t)).run() Added: pypy/trunk/src/pypy/translator/tool/graphserver.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/tool/graphserver.py Sat Dec 4 13:37:58 2004 @@ -0,0 +1,77 @@ +""" +A socket server for GraphPages. +""" + +import autopath, sys, thread, struct, marshal + + +def run_server(homepage, port=8888, quiet=False, background=False): + import socket + server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_sock.bind(('', port)) + server_sock.listen(5) + if not quiet: + print >> sys.stderr, 'Accepting connexions on port %d...' % port + def accept_connexions(): + while True: + conn, addr = server_sock.accept() + if not quiet: + print >> sys.stderr, 'Connected by %r.' % (addr,) + thread.start_new_thread(serve_connexion, (conn, homepage)) + if background: + thread.start_new_thread(accept_connexions, ()) + else: + accept_connexions() + + +def recv_all(s, count): + buf = '' + while len(buf) < count: + data = s.recv(count - len(buf)) + if not data: + raise SystemExit # thread exit, rather + buf += data + return buf + +def recv_msg(s): + hdr_size = struct.calcsize("!i") + msg_size, = struct.unpack("!i", recv_all(s, hdr_size)) + msg = recv_all(s, msg_size) + return marshal.loads(msg) + +def send_msg(s, msg): + data = marshal.dumps(msg) + s.sendall(struct.pack("!i", len(data)) + data) + + +def serve_connexion(s, homepage): + pages = {0: homepage} + while True: + key, link = recv_msg(s) + page = pages[key] + if link is not None: + try: + page = page.content().followlink(link) + key = len(pages) + except KeyError: + page = MissingPage() + key = -1 + pages[key] = page + page = page.content() + reply = { + 'key': key, + 'dot': page.source, + 'links': page.links, + } + send_msg(s, reply) + + +class MissingPage: + links = {} + source = ''' +digraph error { +msg [shape="box", label="Error: a link has gone missing.", color="black", fillcolor="red", style="filled"]; +} +''' + def content(self): + return self Modified: pypy/trunk/src/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/make_dot.py (original) +++ pypy/trunk/src/pypy/translator/tool/make_dot.py Sat Dec 4 13:37:58 2004 @@ -23,6 +23,8 @@ def generate(self, storedir=None, target='ps'): source = self.get_source() + if target is None: + return source # unprocessed if storedir is None: storedir = udir pdot = storedir.join('%s.dot' % self.graphname) Modified: pypy/trunk/src/pypy/translator/tool/pygame/drawgraph.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/pygame/drawgraph.py (original) +++ pypy/trunk/src/pypy/translator/tool/pygame/drawgraph.py Sat Dec 4 13:37:58 2004 @@ -79,6 +79,9 @@ from pypy.translator.tool.pygame.graphdisplay import GraphDisplay GraphDisplay(self).run() + def reload(self): + return self + class Node: def __init__(self, name, x, y, w, h, label, style, shape, color, fillcolor): self.name = name Deleted: /pypy/trunk/src/pypy/translator/tool/pygame/flowviewer.py ============================================================================== --- /pypy/trunk/src/pypy/translator/tool/pygame/flowviewer.py Sat Dec 4 13:37:58 2004 +++ (empty file) @@ -1,267 +0,0 @@ -import autopath -import inspect -from pypy.translator.tool.pygame.drawgraph import GraphLayout -from pypy.translator.tool.make_dot import DotGen -from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS -from pypy.annotation import model -from pypy.annotation.classdef import ClassDef -from pypy.tool.uid import uid - - -class SingleGraphLayout(GraphLayout): - """ A GraphLayout showing a single precomputed FlowGraph.""" - - def __init__(self, graph): - from pypy.translator.tool.make_dot import make_dot - fn = make_dot(graph.name, graph, target='plain') - GraphLayout.__init__(self, fn) - - -class VariableHistoryGraphLayout(GraphLayout): - """ A GraphLayout showing the history of variable bindings. """ - - def __init__(self, translator, name, info, caused_by, history, func_names): - self.links = {} - self.linkinfo = {} - self.translator = translator - self.func_names = func_names - dotgen = DotGen('binding') - label = "Most recent binding of %s\\n\\n%s" % (name, nottoowide(info)) - if info.origin is not None: - label += "\\n" + self.createlink(info.origin, 'Originated at') - if caused_by is not None: - label += '\\n' + self.createlink(caused_by) - if info.caused_by_merge is not None: - data = 'unionof%r' % (info.caused_by_merge,) - label += '\\n%s' % nottoowide(data) - - dotgen.emit_node('0', shape="box", color="red", label=label) - for n, (data, caused_by) in zip(range(len(history)), history): - label = nottoowide(data) - if data.origin is not None: - label += "\\n" + self.createlink(data.origin, 'Originated at') - if caused_by is not None: - label += '\\n' + self.createlink(caused_by) - dotgen.emit_node(str(n+1), shape="box", label=label) - dotgen.emit_edge(str(n+1), str(n)) - links = self.links # GraphLayout.__init__ will override it with {} - GraphLayout.__init__(self, dotgen.generate(target='plain')) - self.links.update(links) - - def createlink(self, position_key, wording='Caused by a call from'): - fn, block, pos = position_key - basename = self.func_names.get(fn, fn.func_name) - linkname = basename - n = 1 - while self.linkinfo.get(linkname, position_key) != position_key: - n += 1 - linkname = '%s_%d' % (basename, n) - self.linkinfo[linkname] = position_key - # It would be nice to get the block name somehow - blockname = block.__class__.__name__ - self.links[linkname] = '%s, %s, position %r:\n%s' % (basename, - blockname, pos, block.operations[pos]) - return '%s %s' % (wording, linkname) - - def followlink(self, funcname): - fn, block, pos = self.linkinfo[funcname] - # It would be nice to focus on the block - return FlowGraphLayout(self.translator, [fn], self.func_names) - - -class FlowGraphLayout(GraphLayout): - """ A GraphLayout showing a Flow Graph (or a few flow graphs). - """ - def __init__(self, translator, functions=None, func_names=None): - from pypy.translator.tool.make_dot import make_dot_graphs - self.translator = translator - self.annotator = translator.annotator - self.func_names = func_names or {} - functions = functions or translator.functions - graphs = [translator.getflowgraph(func) for func in functions] - gs = [(graph.name, graph) for graph in graphs] - if self.annotator and self.annotator.blocked_functions: - for block, was_annotated in self.annotator.annotated.items(): - if not was_annotated: - block.fillcolor = "red" - fn = make_dot_graphs(graphs[0].name + "_graph", gs, target='plain') - GraphLayout.__init__(self, fn) - # make the dictionary of links -- one per annotated variable - self.binding_history = {} - self.current_value = {} - self.caused_by = {} - if self.annotator: - for var in self.annotator.bindings: - s_value = self.annotator.binding(var) - info = '%s: %s' % (var.name, s_value) - self.links[var.name] = info - self.current_value[var.name] = s_value - self.caused_by[var.name] = ( - self.annotator.binding_caused_by.get(var)) - for var, history in self.annotator.bindingshistory.items(): - cause_history = ( - self.annotator.binding_cause_history.get(var, [])) - self.binding_history[var.name] = zip(history, cause_history) - - def followlink(self, varname): - # clicking on a variable name shows its binding history - cur_value = self.current_value[varname] - caused_by = self.caused_by[varname] - history = list(self.binding_history.get(varname, [])) - history.reverse() - return VariableHistoryGraphLayout(self.translator, varname, cur_value, - caused_by, history, self.func_names) - - -def nottoowide(text, width=72): - parts = str(text).split(' ') - lines = [] - line = parts.pop(0) - for s in parts: - if len(line)+len(s) < width: - line = line + ' ' + s - else: - lines.append(line) - line = s - lines.append(line) - return '\\n'.join(lines) - - -class ClassDefLayout(GraphLayout): - """A GraphLayout showing the attributes of a class. - """ - def __init__(self, translator, cdef): - self.translator = translator - dotgen = DotGen(cdef.cls.__name__, rankdir="LR") - - def writecdef(cdef): - dotgen.emit_node(nameof(cdef), color="red", shape="octagon", - label=repr(cdef.cls)) - attrs = cdef.attrs.items() - attrs.sort() - for name, attrdef in attrs: - s_value = attrdef.s_value - dotgen.emit_node(name, shape="box", label=nottoowide(s_value)) - dotgen.emit_edge(nameof(cdef), name, label=name) - - prevcdef = None - while cdef is not None: - writecdef(cdef) - if prevcdef: - dotgen.emit_edge(nameof(cdef), nameof(prevcdef), color="red") - prevcdef = cdef - cdef = cdef.basedef - - GraphLayout.__init__(self, dotgen.generate(target='plain')) - - -class TranslatorLayout(GraphLayout): - """A GraphLayout showing a the call graph between functions - as well as the class hierarchy.""" - - def __init__(self, translator): - self.translator = translator - self.object_by_name = {} - self.name_by_object = {} - dotgen = DotGen('translator') - dotgen.emit('mclimit=15.0') - - # show the call graph - functions = translator.functions - if translator.annotator: - blocked_functions = translator.annotator.blocked_functions - else: - blocked_functions = {} - highlight_functions = getattr(translator, 'highlight_functions', {}) # XXX - dotgen.emit_node('entry', fillcolor="green", shape="octagon", - label="Translator\\nEntry Point") - for func in functions: - name = func.func_name - class_ = getattr(func, 'class_', None) - if class_ is not None: - name = '%s.%s' % (class_.__name__, name) - data = self.labelof(func, name) - if func in blocked_functions: - kw = {'fillcolor': 'red'} - elif func in highlight_functions: - kw = {'fillcolor': '#ffcccc'} - else: - kw = {} - dotgen.emit_node(nameof(func), label=data, shape="box", **kw) - dotgen.emit_edge('entry', nameof(functions[0]), color="green") - for f1, f2 in translator.callgraph.itervalues(): - dotgen.emit_edge(nameof(f1), nameof(f2)) - - # show the class hierarchy - if self.translator.annotator: - dotgen.emit_node(nameof(None), color="red", shape="octagon", - label="Root Class\\nobject") - for classdef in self.translator.annotator.getuserclassdefinitions(): - data = self.labelof(classdef, classdef.cls.__name__) - dotgen.emit_node(nameof(classdef), label=data, shape="box") - dotgen.emit_edge(nameof(classdef.basedef), nameof(classdef)) - - GraphLayout.__init__(self, dotgen.generate(target='plain')) - - # link the function names to the individual flow graphs - for name, obj in self.object_by_name.iteritems(): - if isinstance(obj, ClassDef): - #data = '%s.%s' % (obj.cls.__module__, obj.cls.__name__) - data = repr(obj.cls) - else: - func = obj - try: - source = inspect.getsource(func) - except IOError: # e.g. when func is defined interactively - source = func.func_name - data = '%s:%d\n%s' % (func.func_globals.get('__name__', '?'), - func.func_code.co_firstlineno, - source.split('\n')[0]) - self.links[name] = data - - def labelof(self, obj, objname): - name = objname - i = 1 - while name in self.object_by_name: - i += 1 - name = '%s__%d' % (objname, i) - self.object_by_name[name] = obj - self.name_by_object[obj] = name - return name - - def followlink(self, name): - obj = self.object_by_name[name] - if isinstance(obj, ClassDef): - return ClassDefLayout(self.translator, obj) - else: - return FlowGraphLayout(self.translator, [obj], self.name_by_object) - - -def nameof(obj, cache={}): - # NB. the purpose of the cache is not performance, but to ensure that - # two objects that compare equal get the same name - try: - return cache[obj] - except KeyError: - result = '%s__0x%x' % (getattr(obj, '__name__', ''), uid(obj)) - cache[obj] = result - return result - -# ____________________________________________________________ - -if __name__ == '__main__': - from pypy.translator.translator import Translator - from pypy.translator.test import snippet - from pypy.translator.tool.pygame.graphdisplay import GraphDisplay - - t = Translator(snippet.powerset) - #t.simplify() - a = t.annotate([int]) - a.simplify() - GraphDisplay(FlowGraphLayout(t)).run() - -## t = Translator(snippet._methodcall1) -## t.simplify() -## a = t.annotate([int]) -## a.simplify() -## GraphDisplay(TranslatorLayout(t)).run() Added: pypy/trunk/src/pypy/translator/tool/pygame/graphclient.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/tool/pygame/graphclient.py Sat Dec 4 13:37:58 2004 @@ -0,0 +1,79 @@ +#! /usr/bin/env python +""" +Client for a graph server (either in-process or over a socket). +""" + +import autopath +from pypy.translator.tool.pygame.drawgraph import GraphLayout +from pypy.translator.tool.graphserver import send_msg, recv_msg, MissingPage +from pypy.tool.udir import udir +from py.process import cmdexec + + +DOT_FILE = udir.join('graph.dot') +PLAIN_FILE = udir.join('graph.plain') + + +class ClientGraphLayout(GraphLayout): + + def __init__(self, connexion, key, dot, links, **ignored): + # generate a temporary .dot file and call dot on it + DOT_FILE.write(dot) + cmdexec('dot -Tplain %s>%s' % (str(DOT_FILE),str(PLAIN_FILE))) + GraphLayout.__init__(self, PLAIN_FILE) + self.connexion = connexion + self.key = key + self.links.update(links) + + def followlink(self, name): + return self.connexion.download(self.key, name) + + def reload(self): + return self.connexion.download(self.key) + + +class InProcessConnexion: + + def download(self, page, link=None): + if link is not None: + try: + page = page.content().followlink(link) + except KeyError: + page = MissingPage() + key = page + page = page.content() + return ClientGraphLayout(self, key, page.source, page.links) + + +class SocketConnexion: + + def __init__(self, s): + self.s = s + + def download(self, key, link=None): + send_msg(self.s, (key, link)) + data = recv_msg(self.s) + return ClientGraphLayout(self, **data) + + +def get_layout(homepage): + return InProcessConnexion().download(homepage) + +def get_remote_layout(hostname, port=8888): + import socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((hostname, port)) + return SocketConnexion(s).download(0) + + +if __name__ == '__main__': + import sys + if len(sys.argv) != 2 or sys.argv[1].count(':') != 1: + print >> sys.stderr, 'Connects to a graph server like goal/translate_pypy.' + print >> sys.stderr, 'Usage: %s hostname:port' % (sys.argv[0],) + print >> sys.stderr, ' or %s :port' % (sys.argv[0],) + sys.exit(2) + hostname, port = sys.argv[1].split(':') + port = int(port) + layout = get_remote_layout(hostname, port) + layout.display() Modified: pypy/trunk/src/pypy/translator/tool/pygame/graphdisplay.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/pygame/graphdisplay.py (original) +++ pypy/trunk/src/pypy/translator/tool/pygame/graphdisplay.py Sat Dec 4 13:37:58 2004 @@ -89,6 +89,7 @@ '/': 'search', 'n': 'find_next', 'p': 'find_prev', + 'r': 'reload', 'left' : ('pan', (-1, 0)), 'right' : ('pan', (1, 0)), 'up' : ('pan', (0, -1)), @@ -114,6 +115,7 @@ Backspace Go back in history Meta Left Go back in history Meta Right Go forward in history + R Reload the page F or / Search for text N Find next occurrence @@ -388,6 +390,12 @@ self.layout = self.viewer.graphlayout self.updated_viewer() + def reload(self): + self.setstatusbar('reloading...') + self.redraw_now() + newlayout = self.layout.reload() + self.setlayout(newlayout) + def setstatusbar(self, text, fgcolor=None, bgcolor=None): info = (text, fgcolor or self.STATUSBAR_FGCOLOR, bgcolor or self.STATUSBAR_BGCOLOR) if info != self.statusbarinfo: @@ -438,10 +446,13 @@ def notifyclick(self, pos): word = self.viewer.at_position(pos) if word in self.layout.links: + self.setstatusbar('loading...') + self.redraw_now() newlayout = self.layout.followlink(word) if newlayout is not None: self.setlayout(newlayout) return + self.setstatusbar('') node = self.viewer.node_at_position(pos) if node: self.look_at_node(node) @@ -539,12 +550,7 @@ bumpscale*t*(1-t)) self.viewer.setcenter(cx1*(1-t) + cx2*t, cy1*(1-t) + cy2*t) self.updated_viewer(keep_highlight=keep_highlight) - self.viewer.render() - if self.statusbarinfo: - self.drawstatusbar() - else: - self.status_bar_height = 0 - pygame.display.flip() + self.redraw_now() return moving def peek(self, typ): @@ -619,7 +625,16 @@ def quit(self): raise StopIteration - + + def redraw_now(self): + self.viewer.render() + if self.statusbarinfo: + self.drawstatusbar() + else: + self.status_bar_height = 0 + pygame.display.flip() + self.must_redraw = False + def run(self): self.dragging = self.click_origin = self.click_time = None events = self.events = [] @@ -628,13 +643,7 @@ while True: if self.must_redraw and not events: - self.viewer.render() - if self.statusbarinfo: - self.drawstatusbar() - else: - self.status_bar_height = 0 - pygame.display.flip() - self.must_redraw = False + self.redraw_now() if not events: events.append(pygame.event.wait()) Modified: pypy/trunk/src/pypy/translator/translator.py ============================================================================== --- pypy/trunk/src/pypy/translator/translator.py (original) +++ pypy/trunk/src/pypy/translator/translator.py Sat Dec 4 13:37:58 2004 @@ -108,8 +108,8 @@ def view(self, *functions): """Shows the control flow graph with annotations if computed. Requires 'dot' and pygame.""" - from pypy.translator.tool.pygame.flowviewer import FlowGraphLayout - FlowGraphLayout(self).display() + from pypy.translator.tool.graphpage import FlowGraphPage + FlowGraphPage(self).display() def simplify(self, func=None): """Simplifies the control flow graph (default: for all functions).""" From arigo at codespeak.net Mon Dec 6 16:45:58 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Dec 2004 16:45:58 +0100 (MET) Subject: [pypy-svn] r7759 - pypy/trunk/src/pypy/translator Message-ID: <20041206154558.2B4CD5AA4D@thoth.codespeak.net> Author: arigo Date: Mon Dec 6 16:45:57 2004 New Revision: 7759 Modified: pypy/trunk/src/pypy/translator/annrpython.py Log: Simplified the pendingblocks manipulation, giving a large speed-up. (Credits to mwh) Modified: pypy/trunk/src/pypy/translator/annrpython.py ============================================================================== --- pypy/trunk/src/pypy/translator/annrpython.py (original) +++ pypy/trunk/src/pypy/translator/annrpython.py Mon Dec 6 16:45:57 2004 @@ -21,7 +21,7 @@ def __init__(self, translator=None): self.translator = translator - self.pendingblocks = [] # list of (fn, block, list-of-SomeValues-args) + self.pendingblocks = {} # map {block: function} self.bindings = {} # map Variables to SomeValues self.annotated = {} # set of blocks already seen self.links_followed = {} # set of links that have ever been followed @@ -110,15 +110,18 @@ assert self.translator is None or fn in self.translator.flowgraphs for a in cells: assert isinstance(a, annmodel.SomeObject) - self.pendingblocks.append((fn, block, cells, called_from)) + if block not in self.annotated: + self.bindinputargs(block, cells, called_from) + else: + self.mergeinputargs(block, cells, called_from) + if not self.annotated[block]: + self.pendingblocks[block] = fn def complete(self): """Process pending blocks until none is left.""" while self.pendingblocks: - # XXX don't know if it is better to pop from the head or the tail. - # but suspect from the tail is better in the new Factory model. - fn, block, cells, called_from = self.pendingblocks.pop() - self.processblock(fn, block, cells, called_from) + block, fn = self.pendingblocks.popitem() + self.processblock(fn, block) if False in self.annotated.values(): if annmodel.DEBUG: for block in self.annotated: @@ -277,7 +280,7 @@ #___ flowing annotations in blocks _____________________ - def processblock(self, fn, block, cells, called_from=None): + def processblock(self, fn, block): # Important: this is not called recursively. # self.flowin() can only issue calls to self.addpendingblock(). # The analysis of a block can be in three states: @@ -291,31 +294,26 @@ # input variables). #print '* processblock', block, cells - if block not in self.annotated: - self.bindinputargs(block, cells, called_from) - elif cells is not None: - self.mergeinputargs(block, cells, called_from) - if not self.annotated[block]: - self.annotated[block] = fn or True - try: - self.flowin(fn, block) - except BlockedInference, e: - #print '_'*60 - #print 'Blocked at %r:' % (e.break_at,) - #import traceback, sys - #traceback.print_tb(sys.exc_info()[2]) - self.annotated[block] = False # failed, hopefully temporarily - if annmodel.DEBUG: - import sys - self.why_not_annotated[block] = sys.exc_info() - except Exception, e: - # hack for debug tools only - if not hasattr(e, '__annotator_block'): - setattr(e, '__annotator_block', block) - raise + self.annotated[block] = fn or True + try: + self.flowin(fn, block) + except BlockedInference, e: + #print '_'*60 + #print 'Blocked at %r:' % (e.break_at,) + #import traceback, sys + #traceback.print_tb(sys.exc_info()[2]) + self.annotated[block] = False # failed, hopefully temporarily + if annmodel.DEBUG: + import sys + self.why_not_annotated[block] = sys.exc_info() + except Exception, e: + # hack for debug tools only + if not hasattr(e, '__annotator_block'): + setattr(e, '__annotator_block', block) + raise def reflowpendingblock(self, fn, block): - self.pendingblocks.append((fn, block, None, None)) + self.pendingblocks[block] = fn assert block in self.annotated self.annotated[block] = False # must re-flow From mwh at codespeak.net Mon Dec 6 16:59:07 2004 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 6 Dec 2004 16:59:07 +0100 (MET) Subject: [pypy-svn] r7760 - pypy/trunk/src/pypy/annotation Message-ID: <20041206155907.5FE995AA4D@thoth.codespeak.net> Author: mwh Date: Mon Dec 6 16:59:06 2004 New Revision: 7760 Modified: pypy/trunk/src/pypy/annotation/model.py Log: Smarter SomeObject.__repr__ (especially for SomePBC, but also some other bits). Modified: pypy/trunk/src/pypy/annotation/model.py ============================================================================== --- pypy/trunk/src/pypy/annotation/model.py (original) +++ pypy/trunk/src/pypy/annotation/model.py Mon Dec 6 16:59:06 2004 @@ -51,8 +51,20 @@ def __ne__(self, other): return not (self == other) def __repr__(self): - kwds = ', '.join(['%s=%r' % item for item in self.__dict__.items()]) + items = self.__dict__.items() + items.sort() + args = [] + for k, v in items: + m = getattr(self, 'fmt_' + k, repr) + r = m(v) + if r is not None: + args.append('%s=%s'%(k, r)) + kwds = ', '.join(args) return '%s(%s)' % (self.__class__.__name__, kwds) + + def fmt_knowntype(self, t): + return t.__name__ + def contains(self, other): return self == other or pair(self, other).union() == self def is_constant(self): @@ -150,6 +162,10 @@ self.classdef = classdef self.knowntype = classdef.cls self.revision = classdef.revision + def fmt_knowntype(self, kt): + return None + def fmt_classdef(self, cd): + return cd.cls.__name__ def new_or_old_class(c): if hasattr(c, '__class__'): @@ -185,6 +201,18 @@ if isinstance(x.im_self, classdef.cls): del self.prebuiltinstances[x] + def fmt_prebuiltinstances(self, pbis): + if hasattr(self, 'const'): + return None + else: + return '{...%s...}'%(len(pbis),) + + def fmt_knowntype(self, kt): + if self.is_constant(): + return None + else: + return kt.__name__ + class SomeBuiltin(SomePBC): "Stands for a built-in function or method with special-cased analysis." knowntype = BuiltinFunctionType # == BuiltinMethodType From mwh at codespeak.net Mon Dec 6 17:01:15 2004 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 6 Dec 2004 17:01:15 +0100 (MET) Subject: [pypy-svn] r7761 - pypy/trunk/src/pypy/annotation Message-ID: <20041206160115.BF1AC5AA4D@thoth.codespeak.net> Author: mwh Date: Mon Dec 6 17:01:15 2004 New Revision: 7761 Modified: pypy/trunk/src/pypy/annotation/binaryop.py Log: Be a bit more cautious in (SomeTuple, SomeInteger).getitem(). Always do (SomePBC, SomePBC).union() the more efficient way round. Modified: pypy/trunk/src/pypy/annotation/binaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/binaryop.py (original) +++ pypy/trunk/src/pypy/annotation/binaryop.py Mon Dec 6 17:01:15 2004 @@ -224,7 +224,10 @@ def getitem((tup1, int2)): if int2.is_constant(): - return tup1.items[int2.const] + try: + return tup1.items[int2.const] + except IndexError: + return SomeImpossibleValue() else: return unionof(*tup1.items) @@ -282,6 +285,8 @@ def union((pbc1, pbc2)): if isinstance(pbc1, SomeBuiltin) or isinstance(pbc2, SomeBuiltin): assert False, "merging builtin & PBC == BAD!" + if len(pbc2.prebuiltinstances) > len(pbc1.prebuiltinstances): + pbc1, pbc2 = pbc2, pbc1 d = pbc1.prebuiltinstances.copy() for x, classdef in pbc2.prebuiltinstances.items(): if x in d: From arigo at codespeak.net Mon Dec 6 17:30:15 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Dec 2004 17:30:15 +0100 (MET) Subject: [pypy-svn] r7762 - pypy/trunk/src/pypy/objspace/std Message-ID: <20041206163015.D2E425AA4D@thoth.codespeak.net> Author: arigo Date: Mon Dec 6 17:30:15 2004 New Revision: 7762 Modified: pypy/trunk/src/pypy/objspace/std/fake.py Log: Turned the short but buggy and not-RPythonic fake_descriptor() into a long and verbose but hopefully more correct class W_FakeDescriptor. Modified: pypy/trunk/src/pypy/objspace/std/fake.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/fake.py (original) +++ pypy/trunk/src/pypy/objspace/std/fake.py Mon Dec 6 17:30:15 2004 @@ -109,13 +109,53 @@ _fake_type_cache.content[type(list.append)] = fake_builtin_callable _fake_type_cache.content[type(type(None).__repr__)] = fake_builtin_callable -from pypy.interpreter.typedef import GetSetProperty -def fake_descriptor(space, d): - "NOT_RPYTHON (don't try to fake extra descriptors after initialization!)" - n = d.__name__ - return space.wrap(GetSetProperty(lambda x:getattr(x, n), - lambda x,y:setattr(x, n, y))) +from pypy.interpreter.baseobjspace import Wrappable +from pypy.interpreter.typedef import TypeDef +from pypy.interpreter.gateway import interp2app -_fake_type_cache.content[type(file.softspace)] = fake_descriptor -_fake_type_cache.content[type(type.__dict__['__dict__'])] = fake_descriptor +class W_FakeDescriptor(Wrappable): + # Mimics pypy.interpreter.typedef.GetSetProperty. + + def __init__(self, space, d): + self.name = d.__name__ + + def descr_descriptor_get(space, w_descriptor, w_obj, w_cls=None): + # XXX HAAAAAAAAAAAACK (but possibly a good one) + if w_obj == space.w_None and not space.is_true(space.is_(w_cls, space.type(space.w_None))): + #print w_descriptor, w_obj, w_cls + return w_descriptor + else: + name = space.unwrap(w_descriptor).name + obj = space.unwrap(w_obj) + try: + val = getattr(obj, name) # this gives a "not RPython" warning + except: + wrap_exception(space) + return space.wrap(val) + + def descr_descriptor_set(space, w_descriptor, w_obj, w_value): + name = space.unwrap(w_descriptor).name + obj = space.unwrap(w_obj) + val = space.unwrap(w_value) + try: + setattr(obj, name, val) # this gives a "not RPython" warning + except: + wrap_exception(space) + + def descr_descriptor_del(space, w_descriptor, w_obj): + name = space.unwrap(w_descriptor).name + obj = space.unwrap(w_obj) + try: + delattr(obj, name) + except: + wrap_exception(space) + + typedef = TypeDef("FakeDescriptor", + __get__ = interp2app(descr_descriptor_get), + __set__ = interp2app(descr_descriptor_set), + __delete__ = interp2app(descr_descriptor_del), + ) + +_fake_type_cache.content[type(file.softspace)] = W_FakeDescriptor +_fake_type_cache.content[type(type.__dict__['__dict__'])] = W_FakeDescriptor From lac at codespeak.net Mon Dec 6 22:06:31 2004 From: lac at codespeak.net (lac at codespeak.net) Date: Mon, 6 Dec 2004 22:06:31 +0100 (MET) Subject: [pypy-svn] r7763 - pypy/trunk/doc Message-ID: <20041206210631.3BB625AA4D@thoth.codespeak.net> Author: lac Date: Mon Dec 6 22:06:29 2004 New Revision: 7763 Modified: pypy/trunk/doc/cmodules.txt Log: Update the wiki to mark done cmodules. Modified: pypy/trunk/doc/cmodules.txt ============================================================================== --- pypy/trunk/doc/cmodules.txt (original) +++ pypy/trunk/doc/cmodules.txt Mon Dec 6 22:06:29 2004 @@ -64,7 +64,7 @@ mathmodule -md5module +md5module - done operator - done in PyPy @@ -74,7 +74,7 @@ sgimodule -shamodule +shamodule - done stropmodule From arigo at codespeak.net Tue Dec 7 16:35:38 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 7 Dec 2004 16:35:38 +0100 (MET) Subject: [pypy-svn] r7768 - pypy/trunk/src/pypy/interpreter Message-ID: <20041207153538.89E6F5A943@thoth.codespeak.net> Author: arigo Date: Tue Dec 7 16:35:38 2004 New Revision: 7768 Modified: pypy/trunk/src/pypy/interpreter/pycode.py Log: Boring rewrite of PyCode._from_code() because it's needed at run-time :-( Modified: pypy/trunk/src/pypy/interpreter/pycode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode.py Tue Dec 7 16:35:38 2004 @@ -38,8 +38,7 @@ self.co_lnotab = "" # string: encoding addr<->lineno mapping def _from_code(self, code): - """ NOT_RPYTHON - Initialize the code object from a real (CPython) one. + """ Initialize the code object from a real (CPython) one. This is just a hack, until we have our own compile. At the moment, we just fake this. This method is called by our compile builtin function. @@ -47,15 +46,42 @@ import types assert isinstance(code, types.CodeType) # simply try to suck in all attributes we know of - for name in self.__dict__.keys(): - value = getattr(code, name) - setattr(self, name, value) - newconsts = () + # with a lot of boring asserts to enforce type knowledge + # XXX get rid of that ASAP with a real compiler! + x = code.co_argcount; assert isinstance(x, int) + self.co_argcount = x + x = code.co_nlocals; assert isinstance(x, int) + self.co_nlocals = x + x = code.co_stacksize; assert isinstance(x, int) + self.co_stacksize = x + x = code.co_flags; assert isinstance(x, int) + self.co_flags = x + x = code.co_code; assert isinstance(x, str) + self.co_code = x + #self.co_consts = + x = code.co_names; assert isinstance(x, tuple) + self.co_names = x + x = code.co_varnames; assert isinstance(x, tuple) + self.co_varnames = x + x = code.co_freevars; assert isinstance(x, tuple) + self.co_freevars = x + x = code.co_cellvars; assert isinstance(x, tuple) + self.co_cellvars = x + x = code.co_filename; assert isinstance(x, str) + self.co_filename = x + x = code.co_name; assert isinstance(x, str) + self.co_name = x + x = code.co_firstlineno; assert isinstance(x, int) + self.co_firstlineno = x + x = code.co_lnotab; assert isinstance(x, str) + self.co_lnotab = x + # recursively _from_code()-ify the code objects in code.co_consts + newconsts = [] for const in code.co_consts: if isinstance(const, types.CodeType): const = PyCode()._from_code(const) - newconsts = newconsts + (const,) - self.co_consts = newconsts + newconsts.append(const) + self.co_consts = tuple(newconsts) return self def create_frame(self, space, w_globals, closure=None): From arigo at codespeak.net Tue Dec 7 16:37:47 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 7 Dec 2004 16:37:47 +0100 (MET) Subject: [pypy-svn] r7769 - pypy/trunk/src/pypy/annotation Message-ID: <20041207153747.1E5E95A943@thoth.codespeak.net> Author: arigo Date: Tue Dec 7 16:37:46 2004 New Revision: 7769 Modified: pypy/trunk/src/pypy/annotation/builtin.py Log: builtin_compile(). Modified: pypy/trunk/src/pypy/annotation/builtin.py ============================================================================== --- pypy/trunk/src/pypy/annotation/builtin.py (original) +++ pypy/trunk/src/pypy/annotation/builtin.py Tue Dec 7 16:37:46 2004 @@ -2,6 +2,7 @@ Built-in functions. """ +import types from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool from pypy.annotation.model import SomeList, SomeString, SomeTuple from pypy.annotation.bookkeeper import getbookkeeper @@ -126,6 +127,11 @@ print "XXX ignoring apply%r" % (stuff,) return SomeObject() +def builtin_compile(*stuff): + s = SomeObject() + s.knowntype = types.CodeType + return s + def exception_init(s_self, *args): s_self.setattr(immutablevalue('args'), SomeTuple(args)) From arigo at codespeak.net Tue Dec 7 16:44:37 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 7 Dec 2004 16:44:37 +0100 (MET) Subject: [pypy-svn] r7770 - pypy/trunk/src/pypy/objspace/test Message-ID: <20041207154437.BD1055A943@thoth.codespeak.net> Author: arigo Date: Tue Dec 7 16:44:37 2004 New Revision: 7770 Added: pypy/trunk/src/pypy/objspace/test/test_descriptor.py Log: Added a first test for descriptors. Added: pypy/trunk/src/pypy/objspace/test/test_descriptor.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/objspace/test/test_descriptor.py Tue Dec 7 16:44:37 2004 @@ -0,0 +1,18 @@ +import autopath +from pypy.tool import testit + +class Test_TraceObjSpace(testit.AppTestCase): + + def test_member(self): + import sys + self.assertEquals(sys.stdin.softspace, 0) + self.assertEquals(file.softspace.__get__(sys.stdin), 0) + sys.stdin.softspace = 1 + self.assertEquals(sys.stdin.softspace, 1) + file.softspace.__set__(sys.stdin, 0) + self.assertEquals(sys.stdin.softspace, 0) + self.assertRaises(TypeError, delattr, sys.stdin, 'softspace') + self.assertRaises(TypeError, file.softspace.__delete__, sys.stdin) + +if __name__ == '__main__': + testit.main() From arigo at codespeak.net Tue Dec 7 17:05:41 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 7 Dec 2004 17:05:41 +0100 (MET) Subject: [pypy-svn] r7771 - pypy/trunk/src/pypy/objspace/test Message-ID: <20041207160541.71ABE5A943@thoth.codespeak.net> Author: arigo Date: Tue Dec 7 17:05:40 2004 New Revision: 7771 Modified: pypy/trunk/src/pypy/objspace/test/test_descriptor.py Log: a new test... Modified: pypy/trunk/src/pypy/objspace/test/test_descriptor.py ============================================================================== --- pypy/trunk/src/pypy/objspace/test/test_descriptor.py (original) +++ pypy/trunk/src/pypy/objspace/test/test_descriptor.py Tue Dec 7 17:05:40 2004 @@ -1,7 +1,18 @@ import autopath from pypy.tool import testit -class Test_TraceObjSpace(testit.AppTestCase): +class Test_Descriptor(testit.AppTestCase): + + def test_non_data_descr(self): + class X(object): + def f(self): + return 42 + x = X() + self.assertEquals(x.f(), 42) + x.f = 43 + self.assertEquals(x.f, 43) + del x.f + self.assertEquals(x.f(), 42) def test_member(self): import sys From arigo at codespeak.net Tue Dec 7 17:24:13 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 7 Dec 2004 17:24:13 +0100 (MET) Subject: [pypy-svn] r7772 - in pypy/trunk/src/pypy: annotation translator/test Message-ID: <20041207162413.34FB05A943@thoth.codespeak.net> Author: arigo Date: Tue Dec 7 17:24:12 2004 New Revision: 7772 Modified: pypy/trunk/src/pypy/annotation/binaryop.py pypy/trunk/src/pypy/annotation/bookkeeper.py pypy/trunk/src/pypy/annotation/factory.py pypy/trunk/src/pypy/annotation/model.py pypy/trunk/src/pypy/annotation/unaryop.py pypy/trunk/src/pypy/translator/test/snippet.py pypy/trunk/src/pypy/translator/test/test_annrpython.py Log: Modified SomeDict() to represent a dictionary with variable keys, but whose keys are of a consistent types, and whose values idem. Disabled the now-failing test_knownkeysdict() and replaced it with a test_generaldict(). Modified: pypy/trunk/src/pypy/annotation/binaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/binaryop.py (original) +++ pypy/trunk/src/pypy/annotation/binaryop.py Tue Dec 7 17:24:12 2004 @@ -197,27 +197,18 @@ class __extend__(pairtype(SomeDict, SomeDict)): def union((dic1, dic2)): - result = dic1.items.copy() - for key, s_value in dic2.items.items(): - if key in result: - result[key] = unionof(result[key], s_value) - else: - result[key] = s_value - return SomeDict(setunion(dic1.factories, dic2.factories), result) + return SomeDict(setunion(dic1.factories, dic2.factories), + unionof(dic1.s_key, dic2.s_key), + unionof(dic1.s_value, dic2.s_value)) class __extend__(pairtype(SomeDict, SomeObject)): def getitem((dic1, obj2)): - if obj2.is_constant(): - return dic1.items.get(obj2.const, SomeImpossibleValue()) - else: - return unionof(*dic1.items.values()) + return dic1.s_value def setitem((dic1, obj2), s_value): - assert obj2.is_constant() - key = obj2.const - generalize(dic1.factories, key, s_value) + generalize(dic1.factories, obj2, s_value) class __extend__(pairtype(SomeTuple, SomeInteger)): Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/trunk/src/pypy/annotation/bookkeeper.py (original) +++ pypy/trunk/src/pypy/annotation/bookkeeper.py Tue Dec 7 17:24:12 2004 @@ -85,10 +85,9 @@ items_s = [self.immutablevalue(e) for e in x] result = SomeList({}, unionof(*items_s)) elif tp is dict: # exactly a dict - items = {} - for key, value in x.items(): - items[key] = self.immutablevalue(value) - result = SomeDict({}, items) + keys_s = [self.immutablevalue(e) for e in x.keys()] + values_s = [self.immutablevalue(e) for e in x.values()] + result = SomeDict({}, unionof(*keys_s), unionof(*values_s)) elif ishashable(x) and x in BUILTIN_ANALYZERS: result = SomeBuiltin(BUILTIN_ANALYZERS[x]) elif callable(x) or isinstance(x, staticmethod): # XXX Modified: pypy/trunk/src/pypy/annotation/factory.py ============================================================================== --- pypy/trunk/src/pypy/annotation/factory.py (original) +++ pypy/trunk/src/pypy/annotation/factory.py Tue Dec 7 17:24:12 2004 @@ -44,24 +44,25 @@ class DictFactory: - items = {} + s_key = SomeImpossibleValue() + s_value = SomeImpossibleValue() def __repr__(self): - return '%s(items=%r)' % (self.__class__.__name__, self.items) + return '%s(s_key=%r, s_value=%r)' % (self.__class__.__name__, + self.s_key, self.s_value) def create(self): - return SomeDict(factories = {self: True}, items = self.items) - - def generalize(self, key, s_new_value): - self.items = self.items.copy() - if key not in self.items: - self.items[key] = s_new_value - return True - elif not self.items[key].contains(s_new_value): - self.items[key] = unionof(self.items[key], s_new_value) - return True - else: + return SomeDict(factories = {self: True}, + s_key = self.s_key, + s_value = self.s_value) + + def generalize(self, s_new_key, s_new_value): + if (self.s_key.contains(s_new_key) and + self.s_value.contains(s_new_value)): return False + self.s_key = unionof(self.s_key, s_new_key) + self.s_value = unionof(self.s_value, s_new_value) + return True def generalize(factories, *args): Modified: pypy/trunk/src/pypy/annotation/model.py ============================================================================== --- pypy/trunk/src/pypy/annotation/model.py (original) +++ pypy/trunk/src/pypy/annotation/model.py Tue Dec 7 17:24:12 2004 @@ -142,11 +142,12 @@ class SomeDict(SomeObject): - "Stands for a dict with known keys." + "Stands for a dict." knowntype = dict - def __init__(self, factories, items): + def __init__(self, factories, s_key, s_value): self.factories = factories - self.items = items # dict {realkey: s_value} + self.s_key = s_key + self.s_value = s_value class SomeIterator(SomeObject): Modified: pypy/trunk/src/pypy/annotation/unaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/unaryop.py (original) +++ pypy/trunk/src/pypy/annotation/unaryop.py Tue Dec 7 17:24:12 2004 @@ -80,11 +80,6 @@ def iter(tup): return SomeIterator(unionof(*tup.items)) -class __extend__(SomeDict): - - def len(dic): - return immutablevalue(len(dic.items)) - class __extend__(SomeList): Modified: pypy/trunk/src/pypy/translator/test/snippet.py ============================================================================== --- pypy/trunk/src/pypy/translator/test/snippet.py (original) +++ pypy/trunk/src/pypy/translator/test/snippet.py Tue Dec 7 17:24:12 2004 @@ -373,6 +373,11 @@ d = {'b': -123} return d['b'] +def generaldict(key=str, value=int, key2=str, value2=int): + d = {key: value} + d[key2] = value2 + return d[key or key2] + def prime(n=int): return len([i for i in range(1,n+1) if n%i==0]) == 2 Modified: pypy/trunk/src/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/trunk/src/pypy/translator/test/test_annrpython.py (original) +++ pypy/trunk/src/pypy/translator/test/test_annrpython.py Tue Dec 7 17:24:12 2004 @@ -199,14 +199,20 @@ self.assertEquals(classes[snippet.H].attrs.keys(), ['attr']) self.assertEquals(classes[snippet.H].about_attribute('attr'), a.bookkeeper.immutablevalue(1)) - - def test_knownkeysdict(self): + def DISABLED_test_knownkeysdict(self): + # disabled, SomeDict() is now a general {s_key: s_value} dict a = RPythonAnnotator() s = a.build_types(snippet.knownkeysdict, [int]) # result should be an integer self.assertEquals(s.knowntype, int) + def test_generaldict(self): + a = RPythonAnnotator() + s = a.build_types(snippet.generaldict, [str, int, str, int]) + # result should be an integer + self.assertEquals(s.knowntype, int) + def test_somebug1(self): a = RPythonAnnotator() s = a.build_types(snippet._somebug1, [int]) From arigo at codespeak.net Wed Dec 8 13:48:01 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Dec 2004 13:48:01 +0100 (MET) Subject: [pypy-svn] r7774 - pypy/trunk/src/pypy/annotation Message-ID: <20041208124801.18C8B5A95A@thoth.codespeak.net> Author: arigo Date: Wed Dec 8 13:48:00 2004 New Revision: 7774 Modified: pypy/trunk/src/pypy/annotation/binaryop.py Log: Patch from odie, with 'xor' fixed. Modified: pypy/trunk/src/pypy/annotation/binaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/binaryop.py (original) +++ pypy/trunk/src/pypy/annotation/binaryop.py Wed Dec 8 13:48:00 2004 @@ -20,6 +20,7 @@ # XXX unify this with ObjSpace.MethodTable BINARY_OPERATIONS = set(['add', 'sub', 'mul', 'div', 'mod', + 'and_', 'or_', 'xor', 'getitem', 'setitem', 'inplace_add', 'inplace_sub', 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'is_', @@ -125,15 +126,15 @@ return SomeInteger(nonneg = int1.nonneg and int2.nonneg, unsigned = int1.unsigned or int2.unsigned) - def add((int1, int2)): - return SomeInteger(nonneg = int1.nonneg and int2.nonneg, - unsigned = int1.unsigned or int2.unsigned) - - mul = div = mod = add + add = mul = div = mod = or_ = xor = union def sub((int1, int2)): return SomeInteger(unsigned = int1.unsigned or int2.unsigned) + def and_((int1, int2)): + return SomeInteger(nonneg = int1.nonneg or int1.nonneg, + unsigned = int1.unsigned or int2.unsigned) + class __extend__(pairtype(SomeBool, SomeBool)): From hpk at codespeak.net Wed Dec 8 13:54:19 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 8 Dec 2004 13:54:19 +0100 (MET) Subject: [pypy-svn] r7775 - pypy/trunk/doc/funding/negotiations Message-ID: <20041208125419.DA6B55A95A@thoth.codespeak.net> Author: hpk Date: Wed Dec 8 13:50:57 2004 New Revision: 7775 Added: pypy/trunk/doc/funding/negotiations/strep-consortium-model.sxw (contents, props changed) Log: added the model consortium agreement in OpenOffice format, obtained from this source: http://www.ipr-helpdesk.org/controlador.jsp?cuerpo=cuerpoSubsecCA&seccion=FP6&len=en They offer two possible STREP-consortium models but the other one in there seems to be much much further away than the one i now commit. Added: pypy/trunk/doc/funding/negotiations/strep-consortium-model.sxw ============================================================================== Binary file. No diff available. From lac at codespeak.net Wed Dec 8 13:59:17 2004 From: lac at codespeak.net (lac at codespeak.net) Date: Wed, 8 Dec 2004 13:59:17 +0100 (MET) Subject: [pypy-svn] r7776 - pypy/trunk/doc Message-ID: <20041208125917.D51945A95A@thoth.codespeak.net> Author: lac Date: Wed Dec 8 13:59:17 2004 New Revision: 7776 Modified: pypy/trunk/doc/developers.txt Log: Adding odie before we forget, we found that we had left out Bob and Marius. Ooops. Have we left out anybody else? Modified: pypy/trunk/doc/developers.txt ============================================================================== --- pypy/trunk/doc/developers.txt (original) +++ pypy/trunk/doc/developers.txt Wed Dec 8 13:59:17 2004 @@ -14,6 +14,7 @@ Guenter Jantzen Stefan Schwarzer Dinu Gherman Patrick Maupin Rocco Moretti Andreas Friedge - Theo de Ridder + Theo de Ridder Olivier Dormond + Bob Ippolito Marius Gedminas PyPy Webpage: http://codespeak.net/pypy From hpk at codespeak.net Wed Dec 8 14:09:19 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 8 Dec 2004 14:09:19 +0100 (MET) Subject: [pypy-svn] r7777 - pypy/trunk/doc/funding/negotiations Message-ID: <20041208130919.63B425A95A@thoth.codespeak.net> Author: hpk Date: Wed Dec 8 14:09:18 2004 New Revision: 7777 Added: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw (contents, props changed) Log: This is to supposedly become our final consortium contract. It still needs a lot of work though. The idea is that you can compare this document always against strep-consortium-model.sxw in the same directory in order to see the differences. Added: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw ============================================================================== Binary file. No diff available. From hpk at codespeak.net Wed Dec 8 14:09:19 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 8 Dec 2004 14:09:19 +0100 (MET) Subject: [pypy-svn] r7777 - pypy/trunk/doc/funding/negotiations Message-ID: <20041208130919.80A085B0B1@thoth.codespeak.net> Author: hpk Date: Wed Dec 8 14:09:18 2004 New Revision: 7777 Added: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw (contents, props changed) Log: This is to supposedly become our final consortium contract. It still needs a lot of work though. The idea is that you can compare this document always against strep-consortium-model.sxw in the same directory in order to see the differences. Added: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw ============================================================================== Binary file. No diff available. From lene at codespeak.net Wed Dec 8 15:38:23 2004 From: lene at codespeak.net (lene at codespeak.net) Date: Wed, 8 Dec 2004 15:38:23 +0100 (MET) Subject: [pypy-svn] r7778 - pypy/trunk/doc/funding/negotiations Message-ID: <20041208143823.D94D25A95A@thoth.codespeak.net> Author: lene Date: Wed Dec 8 15:38:23 2004 New Revision: 7778 Added: pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc (contents, props changed) Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf Log: Added merlinux to the CPF as participant No. 6. Please note that I used CPF Editor version 2.8. Budget shifts (sec. A3.1 of the CPF) are not yet made. I think it would be better if Alastair and Jacob did the budget adjustments. Added form b accession for merlinux (modified from the document that was sent to pypy-funding). However, there is a small detail about the appropriate DFKI representative missing which i cannot fill in. Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf ============================================================================== --- pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf (original) +++ pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf Wed Dec 8 15:38:23 2004 @@ -2,94 +2,94 @@ - @@ -125,198 +125,198 @@ - @@ -545,6 +545,51 @@ 888016618 N + + + 004779 + PYPY + 6 + merlinux GmbH + HRB 3565 + merlinux + + Gerlandstr. 8 + + DE + 31139 Hildesheim + http://www.merlinux.de + + RES + N + + + + + + + DE814082730 + + + + + 2 + 1 + 0 + 1 + FCF + + PRIV + + + + + C + software research, developement, integration + Y + + N + @@ -561,209 +606,209 @@ - @@ -1022,6 +1067,57 @@ + + + 004779 + PYPY + 6 + Wagner + Lene + Ms + F + +4951216028381 + + wagner at merlinux.de + Krekel + Holger + Mr + M + + + krekel at merlinux.de + merlinux + + + + + + + Krekel + Holger + Mr + M + +49512147247 + + krekel at merlinux.de + N + + + + + + + + + + managing director + technical director + technical director + + + + + @@ -1038,134 +1134,134 @@ - @@ -1229,6 +1325,18 @@ + + + 004779 + PYPY + 6 + merlinux GmbH + Wagner + + Lene + Y + + @@ -1245,162 +1353,162 @@ - @@ -1599,6 +1707,45 @@ 2332210 1353000 + + + 004779 + PYPY + 6 + merlinux + FCF + + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 of 1 + 2237810 + 1258600 + 0 + 0 + 94400 + 94400 + 0 + 2332210 + 1353000 + @@ -1615,77 +1762,77 @@ - @@ -1782,208 +1929,208 @@ - @@ -2046,103 +2193,103 @@ - @@ -2216,6 +2363,20 @@ + + + 004779 + PYPY + 6 + + + N + N + + + + + @@ -2232,324 +2393,324 @@ - @@ -3003,6 +3164,96 @@ 0 0 + + + 004779 + PYPY + 6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + Added: pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc ============================================================================== Binary file. No diff available. From lene at codespeak.net Wed Dec 8 15:38:24 2004 From: lene at codespeak.net (lene at codespeak.net) Date: Wed, 8 Dec 2004 15:38:24 +0100 (MET) Subject: [pypy-svn] r7778 - pypy/trunk/doc/funding/negotiations Message-ID: <20041208143824.25D895B0B1@thoth.codespeak.net> Author: lene Date: Wed Dec 8 15:38:23 2004 New Revision: 7778 Added: pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc (contents, props changed) Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf Log: Added merlinux to the CPF as participant No. 6. Please note that I used CPF Editor version 2.8. Budget shifts (sec. A3.1 of the CPF) are not yet made. I think it would be better if Alastair and Jacob did the budget adjustments. Added form b accession for merlinux (modified from the document that was sent to pypy-funding). However, there is a small detail about the appropriate DFKI representative missing which i cannot fill in. Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf ============================================================================== --- pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf (original) +++ pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf Wed Dec 8 15:38:23 2004 @@ -2,94 +2,94 @@ - @@ -125,198 +125,198 @@ - @@ -545,6 +545,51 @@ 888016618 N + + + 004779 + PYPY + 6 + merlinux GmbH + HRB 3565 + merlinux + + Gerlandstr. 8 + + DE + 31139 Hildesheim + http://www.merlinux.de + + RES + N + + + + + + + DE814082730 + + + + + 2 + 1 + 0 + 1 + FCF + + PRIV + + + + + C + software research, developement, integration + Y + + N + @@ -561,209 +606,209 @@ - @@ -1022,6 +1067,57 @@ + + + 004779 + PYPY + 6 + Wagner + Lene + Ms + F + +4951216028381 + + wagner at merlinux.de + Krekel + Holger + Mr + M + + + krekel at merlinux.de + merlinux + + + + + + + Krekel + Holger + Mr + M + +49512147247 + + krekel at merlinux.de + N + + + + + + + + + + managing director + technical director + technical director + + + + + @@ -1038,134 +1134,134 @@ - @@ -1229,6 +1325,18 @@ + + + 004779 + PYPY + 6 + merlinux GmbH + Wagner + + Lene + Y + + @@ -1245,162 +1353,162 @@ - @@ -1599,6 +1707,45 @@ 2332210 1353000 + + + 004779 + PYPY + 6 + merlinux + FCF + + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 of 1 + 2237810 + 1258600 + 0 + 0 + 94400 + 94400 + 0 + 2332210 + 1353000 + @@ -1615,77 +1762,77 @@ - @@ -1782,208 +1929,208 @@ - @@ -2046,103 +2193,103 @@ - @@ -2216,6 +2363,20 @@ + + + 004779 + PYPY + 6 + + + N + N + + + + + @@ -2232,324 +2393,324 @@ - @@ -3003,6 +3164,96 @@ 0 0 + + + 004779 + PYPY + 6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + Added: pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc ============================================================================== Binary file. No diff available. From arigo at codespeak.net Thu Dec 9 18:19:13 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 18:19:13 +0100 (MET) Subject: [pypy-svn] r7791 - in pypy/trunk/src/pypy: annotation interpreter interpreter/test objspace objspace/flow objspace/flow/test objspace/std tool translator translator/tool Message-ID: <20041209171913.142835A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 18:19:11 2004 New Revision: 7791 Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py pypy/trunk/src/pypy/annotation/unaryop.py pypy/trunk/src/pypy/interpreter/argument.py pypy/trunk/src/pypy/interpreter/function.py pypy/trunk/src/pypy/interpreter/gateway.py pypy/trunk/src/pypy/interpreter/pycode.py pypy/trunk/src/pypy/interpreter/pyopcode.py pypy/trunk/src/pypy/interpreter/test/test_gateway.py pypy/trunk/src/pypy/interpreter/test/test_interpreter.py pypy/trunk/src/pypy/objspace/flow/objspace.py pypy/trunk/src/pypy/objspace/flow/specialcase.py pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py pypy/trunk/src/pypy/objspace/std/objecttype.py pypy/trunk/src/pypy/objspace/std/typeobject.py pypy/trunk/src/pypy/objspace/trivial.py pypy/trunk/src/pypy/tool/traceop.py pypy/trunk/src/pypy/translator/annrpython.py pypy/trunk/src/pypy/translator/genpyrex.py pypy/trunk/src/pypy/translator/tool/flowtrace.py pypy/trunk/src/pypy/translator/transform.py Log: Extended the Arguments class to include a 'w_stararg' attribute, which can hold a non-unpacked *argument. The main change for the flow graphs is the operation 'call_args' replacing the 'call' operation. ('simple_call' is still there for simple cases.) See the description of 'call_args' at the beginning of translator.transform. The goal was to make *arg unpacking lazy; the 'call_args' operation can now specify explicit keywords (not built as a dict) as well as this unpacked *arg. In other words, all argument information is stored into the Arguments class and packed unmodified in the 'call_args' operation, without having to expand the *arg. This starts to look a bit nicer, particularly for translator.annrpython, where a pagefull of code has been replaced by just a call to Arguments.parse(). It's nice to be able to use the same parsing logic in the annotation phase, though it's still not 100% clean: the Arguments class depends on the presence of a space, but we don't have any during annotation. There is a pseudo-space RPythonCallsSpace in annotation.unaryop, but it's a hack. The Arguments class should be rewritten to be more independent on any space. Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/trunk/src/pypy/annotation/bookkeeper.py (original) +++ pypy/trunk/src/pypy/annotation/bookkeeper.py Thu Dec 9 18:19:11 2004 @@ -7,7 +7,6 @@ from pypy.annotation.model import * from pypy.annotation.classdef import ClassDef from pypy.interpreter.miscutils import getthreadlocals -from pypy.interpreter.pycode import CO_VARARGS from pypy.tool.hack import func_with_new_name class Bookkeeper: @@ -156,7 +155,7 @@ o.knowntype = t return o - def pycall(self, func, *args): + def pycall(self, func, args): if func is None: # consider None as a NULL function pointer return SomeImpossibleValue() if isinstance(func, (type, ClassType)) and \ @@ -184,9 +183,12 @@ else: assert isinstance(init, BuiltinMethodType) s_init = self.immutablevalue(init) - s_init.simple_call(s_instance, *args) + s_init.call(args.prepend(s_instance)) else: - assert not args, "no __init__ found in %r" % (cls,) + try: + args.fixedunpack(0) + except ValueError: + raise Exception, "no __init__ found in %r" % (cls,) return s_instance if hasattr(func, '__call__') and \ isinstance(func.__call__, MethodType): @@ -194,7 +196,7 @@ if hasattr(func, 'im_func'): if func.im_self is not None: s_self = self.immutablevalue(func.im_self) - args = [s_self] + list(args) + args = args.prepend(s_self) # for debugging only, but useful to keep anyway: try: func.im_func.class_ = func.im_class @@ -219,12 +221,12 @@ else: raise Exception, "unsupported specialization type '%s'"%(x,) - elif func.func_code.co_flags & CO_VARARGS: - # calls to *arg functions: create one version per number of args - func = self.specialize_by_key(func, len(args), - name='%s__%d' % (func.func_name, - len(args))) - return self.annotator.recursivecall(func, self.position_key, *args) +## elif func.func_code.co_flags & CO_VARARGS: +## # calls to *arg functions: create one version per number of args +## func = self.specialize_by_key(func, len(args), +## name='%s__%d' % (func.func_name, +## len(args))) + return self.annotator.recursivecall(func, self.position_key, args) def specialize_by_key(self, thing, key, name=None): key = thing, key @@ -259,7 +261,8 @@ def short_type_name(args): l = [] - for x in args: + shape, args_w = args.flatten() + for x in args_w: if isinstance(x, SomeInstance) and hasattr(x, 'knowntype'): name = "SI_" + x.knowntype.__name__ else: Modified: pypy/trunk/src/pypy/annotation/unaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/unaryop.py (original) +++ pypy/trunk/src/pypy/annotation/unaryop.py Thu Dec 9 18:19:11 2004 @@ -3,6 +3,7 @@ """ from types import FunctionType +from pypy.interpreter.argument import Arguments from pypy.annotation.pairtype import pair from pypy.annotation.model import SomeObject, SomeInteger, SomeBool from pypy.annotation.model import SomeString, SomeChar, SomeList, SomeDict @@ -18,7 +19,8 @@ def immutablevalue(x): return getbookkeeper().immutablevalue(x) -UNARY_OPERATIONS = set(['len', 'is_true', 'getattr', 'setattr', 'simple_call', +UNARY_OPERATIONS = set(['len', 'is_true', 'getattr', 'setattr', + 'simple_call', 'call_args', 'iter', 'next']) for opname in UNARY_OPERATIONS: @@ -62,9 +64,17 @@ def bindcallables(obj, classdef): return obj # default unbound __get__ implementation - def simple_call(*obj_and_args): - #raise Exception, "cannot follow simple_call%r" % (obj_and_args,) - print "*** cannot follow simple_call%r" % (obj_and_args,) + def simple_call(obj, *args_s): + space = RPythonCallsSpace(getbookkeeper()) + return obj.call(Arguments(space, args_s)) + + def call_args(obj, s_shape, *args_s): + space = RPythonCallsSpace(getbookkeeper()) + return obj.call(Arguments.fromshape(space, s_shape.const, args_s)) + + def call(obj, args): + #raise Exception, "cannot follow call_args%r" % (obj_and_args,) + print "*** cannot follow call(%r, %r)" % (obj, args) return SomeObject() @@ -192,7 +202,7 @@ print "*** WARNING: setattr not wanted on %r" % pbc pass - def simple_call(pbc, *args): + def call(pbc, args): bookkeeper = getbookkeeper() results = [] for func, classdef in pbc.prebuiltinstances.items(): @@ -201,9 +211,10 @@ s_self = SomeInstance(classdef) classdef.instantiation_locations[ bookkeeper.position_key] = True - results.append(bookkeeper.pycall(func, s_self, *args)) + args1 = args.prepend(s_self) else: - results.append(bookkeeper.pycall(func, *args)) + args1 = args + results.append(bookkeeper.pycall(func, args1)) return unionof(*results) def bindcallables(pbc, classdef): @@ -223,3 +234,27 @@ d[func] = value return SomePBC(d) + +class RPythonCallsSpace: + """Pseudo Object Space providing almost no real operation. + For the Arguments class: if it really needs other operations, it means + that the call pattern is too complex for R-Python. + """ + def __init__(self, bookkeeper): + self.bookkeeper = bookkeeper + + def newtuple(self, items_s): + return SomeTuple(items_s) + + def newdict(self, stuff): + raise Exception, "call pattern too complicated (** argument)" + + # XXX the following is only a hack to lead Arguments.parse() believe + # XXX that the *arg is always a tuple! + w_tuple = object() + def type(self, w_obj): + return self.w_tuple + def is_(self, w1, w2): + return w1 is w2 + def is_true(self, x): + return bool(x) Modified: pypy/trunk/src/pypy/interpreter/argument.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/argument.py (original) +++ pypy/trunk/src/pypy/interpreter/argument.py Thu Dec 9 18:19:11 2004 @@ -16,64 +16,92 @@ blind_arguments = 0 - def __init__(self, space, args_w=[], kwds_w={}): + def __init__(self, space, args_w=[], kwds_w={}, + w_stararg=None, w_starstararg=None): self.space = space - self.args_w = args_w - self.kwds_w = kwds_w + self.arguments_w = list(args_w) + self.kwds_w = kwds_w.copy() + self.w_stararg = w_stararg + if w_starstararg is not None: + # unlike the * argument we unpack the ** argument immediately. + # maybe we could allow general mappings? + if not space.is_true(space.isinstance(w_starstararg, space.w_dict)): + raise OperationError(space.w_TypeError, + space.wrap("the keywords must be " + "a dictionary")) + for w_key in space.unpackiterable(w_starstararg): + key = space.unwrap(w_key) + if not isinstance(key, str): + raise OperationError(space.w_TypeError, + space.wrap("keywords must be strings")) + if key in self.kwds_w: + raise OperationError(self.space.w_TypeError, + self.space.wrap("got multiple values " + "for keyword argument " + "'%s'" % key)) + self.kwds_w[key] = space.getitem(w_starstararg, w_key) def frompacked(space, w_args=None, w_kwds=None): - """Static method to build an Arguments - from a wrapped sequence and optionally a wrapped dictionary. - """ - if w_args is None: - args_w = [] - else: - args_w = space.unpackiterable(w_args) - if w_kwds is None: - return Arguments(space, args_w) - # maybe we could allow general mappings? - if not space.is_true(space.isinstance(w_kwds, space.w_dict)): - raise OperationError(space.w_TypeError, - space.wrap("the keywords must be " - "a dictionary")) - kwds_w = {} - for w_key in space.unpackiterable(w_kwds): - key = space.unwrap(w_key) - if not isinstance(key, str): - raise OperationError(space.w_TypeError, - space.wrap("keywords must be strings")) - kwds_w[key] = space.getitem(w_kwds, w_key) - return Arguments(space, args_w, kwds_w) + """Convenience static method to build an Arguments + from a wrapped sequence and a wrapped dictionary.""" + return Arguments(space, w_stararg=w_args, w_starstararg=w_kwds) frompacked = staticmethod(frompacked) + def __repr__(self): + if self.w_stararg is None: + if not self.kwds_w: + return 'Arguments(%s)' % (self.arguments_w,) + else: + return 'Arguments(%s, %s)' % (self.arguments_w, self.kwds_w) + else: + return 'Arguments(%s, %s, %s)' % (self.arguments_w, + self.kwds_w, + self.w_stararg) + ### Manipulation ### + def unpack(self): + "Return a ([w1,w2...], {'kw':w3...}) pair." + if self.w_stararg is not None: + self.arguments_w += self.space.unpackiterable(self.w_stararg) + self.w_stararg = None + return self.arguments_w, self.kwds_w + def prepend(self, w_firstarg): "Return a new Arguments with a new argument inserted first." - args = Arguments(self.space, [w_firstarg] + self.args_w, self.kwds_w) + args = Arguments(self.space, [w_firstarg] + self.arguments_w, + self.kwds_w, self.w_stararg) args.blind_arguments = self.blind_arguments + 1 return args - def join(self, other): - "Return a new Arguments combining the content of two Arguments." - args_w = self.args_w + other.args_w - kwds_w = self.kwds_w.copy() - for key, w_value in other.kwds_w.items(): - if key in kwds_w: - raise OperationError(self.space.w_TypeError, - self.space.wrap("got multiple values for " - "keyword argument '%s'" % - key)) - kwds_w[key] = w_value - return Arguments(self.space, args_w, kwds_w) - - def pack(self): - "Return a (wrapped tuple, wrapped dictionary)." - space = self.space - w_args = space.newtuple(self.args_w) - w_kwds = space.newdict([(space.wrap(key), w_value) - for key, w_value in self.kwds_w.items()]) - return w_args, w_kwds + def fixedunpack(self, argcount): + """The simplest argument parsing: get the 'argcount' arguments, + or raise a real ValueError if the length is wrong.""" + if self.kwds_w: + raise ValueError, "no keyword arguments expected" + if len(self.arguments_w) > argcount: + raise ValueError, "too many arguments (%d expected)" % argcount + if self.w_stararg is not None: + self.arguments_w += self.space.unpackiterable(self.w_stararg, + argcount - len(self.arguments_w)) + self.w_stararg = None + elif len(self.arguments_w) < argcount: + raise ValueError, "not enough arguments (%d expected)" % argcount + return self.arguments_w + + def firstarg(self): + "Return the first argument for inspection." + if self.arguments_w: + return self.arguments_w[0] + if self.w_stararg is None: + return None + w_iter = self.space.iter(self.w_stararg) + try: + return self.space.next(w_iter) + except OperationError, e: + if not e.match(self.space, self.space.w_StopIteration): + raise + return None ### Parsing for function calls ### @@ -82,8 +110,6 @@ according to the signature of code object. """ space = self.space - args_w = self.args_w - kwds_w = self.kwds_w argnames, varargname, kwargname = signature # # args_w = list of the normal actual parameters, wrapped @@ -95,6 +121,17 @@ # very informative. # co_argcount = len(argnames) # expected formal arguments, without */** + if self.w_stararg is not None: + # There is a case where we don't have to unpack() a w_stararg: + # if it matches exactly a *arg in the signature. + if (len(self.arguments_w) == co_argcount and varargname is not None + and space.is_true(space.is_(space.type(self.w_stararg), + space.w_tuple))): + pass + else: + self.unpack() # sets self.w_stararg to None + args_w = self.arguments_w + kwds_w = self.kwds_w # put as many positional input arguments into place as available scope_w = args_w[:co_argcount] @@ -125,7 +162,10 @@ # collect extra positional arguments into the *vararg if varargname is not None: - scope_w.append(space.newtuple(args_w[co_argcount:])) + if self.w_stararg is None: # common case + scope_w.append(space.newtuple(args_w[co_argcount:])) + else: # shortcut for the non-unpack() case above + scope_w.append(self.w_stararg) elif len(args_w) > co_argcount: self.raise_argerr(fnname, signature, defaults_w, True) @@ -142,14 +182,15 @@ def raise_argerr(self, fnname, signature, defaults_w, too_many): argnames, varargname, kwargname = signature - nargs = len(self.args_w) + args_w, kwds_w = self.unpack() + nargs = len(args_w) n = len(argnames) if n == 0: if kwargname is not None: msg2 = "non-keyword " else: msg2 = "" - nargs += len(self.kwds_w) + nargs += len(kwds_w) msg = "%s() takes no %sargument (%d given)" % ( fnname, msg2, @@ -181,7 +222,7 @@ raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) def raise_argerr_multiple_values(self, fnname, argname): - msg = "%s() got multiple values for keyword argument %s" % ( + msg = "%s() got multiple values for keyword argument '%s'" % ( fnname, argname) raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) @@ -196,3 +237,26 @@ fnname, len(kwds_w)) raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) + + ### Argument <-> list of w_objects together with "shape" information + + def flatten(self): + shape_cnt = len(self.arguments_w) # Number of positional args + shape_keys = self.kwds_w.keys() # List of keywords (strings) + shape_star = self.w_stararg is not None # Flag: presence of *arg + data_w = self.arguments_w + [self.kwds_w[key] for key in shape_keys] + if shape_star: + data_w.append(self.w_stararg) + return (shape_cnt, tuple(shape_keys), shape_star), data_w + + def fromshape(space, (shape_cnt, shape_keys, shape_star), data_w): + args_w = data_w[:shape_cnt] + kwds_w = {} + for i in range(len(shape_keys)): + kwds_w[shape_keys[i]] = data_w[shape_cnt+i] + if shape_star: + w_star = data_w[-1] + else: + w_star = None + return Arguments(space, args_w, kwds_w, w_star) + fromshape = staticmethod(fromshape) Modified: pypy/trunk/src/pypy/interpreter/function.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/function.py (original) +++ pypy/trunk/src/pypy/interpreter/function.py Thu Dec 9 18:19:11 2004 @@ -102,8 +102,9 @@ args = args.prepend(self.w_instance) else: # unbound method - if (len(args.args_w) >= 1 and self.space.is_true( - self.space.isinstance(args.args_w[0], self.w_class))): + w_firstarg = args.firstarg() + if w_firstarg is not None and self.space.is_true( + self.space.isinstance(w_firstarg, self.w_class)): pass # ok else: msg = ("unbound method must be called with " Modified: pypy/trunk/src/pypy/interpreter/gateway.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/gateway.py (original) +++ pypy/trunk/src/pypy/interpreter/gateway.py Thu Dec 9 18:19:11 2004 @@ -94,9 +94,9 @@ def performance_shortcut_call(self, space, args): # this shortcut is only used for performance reasons - if self.generalargs or args.kwds_w: + args_w, kwds_w = args.unpack() + if self.generalargs or kwds_w: return None - args_w = args.args_w if not (self.minargs <= len(args_w) <= self.maxargs): return None if self.ismethod: @@ -120,16 +120,17 @@ else: return None else: - if args.kwds_w: + args_w, kwds_w = args.unpack() + if kwds_w: return None - if not (self.minargs <= 1+len(args.args_w) <= self.maxargs): + if not (self.minargs <= 1+len(args_w) <= self.maxargs): return None if self.ismethod: w_obj = space.unwrap(w_obj) # abuse name w_obj if self.spacearg: - w_result = self.func(space, w_obj, *args.args_w) + w_result = self.func(space, w_obj, *args_w) else: - w_result = self.func(w_obj, *args.args_w) + w_result = self.func(w_obj, *args_w) if w_result is None: w_result = space.w_None return w_result Modified: pypy/trunk/src/pypy/interpreter/pycode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pycode.py (original) +++ pypy/trunk/src/pypy/interpreter/pycode.py Thu Dec 9 18:19:11 2004 @@ -170,3 +170,7 @@ else: return cache.getorbuild((newclass, baseclass), _really_enhanceclass, None) + + +def cpython_code_signature(co): + return PyCode()._from_code(co).signature() Modified: pypy/trunk/src/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/pyopcode.py (original) +++ pypy/trunk/src/pypy/interpreter/pyopcode.py Thu Dec 9 18:19:11 2004 @@ -690,7 +690,7 @@ block = pyframe.FinallyBlock(f, f.next_instr + offsettoend) f.blockstack.push(block) - def CALL_FUNCTION(f, oparg, extra_args=None): + def CALL_FUNCTION(f, oparg, w_star=None, w_starstar=None): n_arguments = oparg & 0xff n_keywords = (oparg>>8) & 0xff keywords = {} @@ -701,28 +701,23 @@ keywords[key] = w_value arguments = [f.valuestack.pop() for i in range(n_arguments)] arguments.reverse() - args = Arguments(f.space, arguments, keywords) - if extra_args: - args = args.join(extra_args) + args = Arguments(f.space, arguments, keywords, w_star, w_starstar) w_function = f.valuestack.pop() w_result = f.space.call_args(w_function, args) f.valuestack.push(w_result) def CALL_FUNCTION_VAR(f, oparg): w_varargs = f.valuestack.pop() - extra_args = Arguments.frompacked(f.space, w_varargs) - f.CALL_FUNCTION(oparg, extra_args) + f.CALL_FUNCTION(oparg, w_varargs) def CALL_FUNCTION_KW(f, oparg): w_varkw = f.valuestack.pop() - extra_args = Arguments.frompacked(f.space, w_kwds=w_varkw) - f.CALL_FUNCTION(oparg, extra_args) + f.CALL_FUNCTION(oparg, None, w_varkw) def CALL_FUNCTION_VAR_KW(f, oparg): w_varkw = f.valuestack.pop() w_varargs = f.valuestack.pop() - extra_args = Arguments.frompacked(f.space, w_varargs, w_varkw) - f.CALL_FUNCTION(oparg, extra_args) + f.CALL_FUNCTION(oparg, w_varargs, w_varkw) def MAKE_FUNCTION(f, numdefaults): w_codeobj = f.valuestack.pop() Modified: pypy/trunk/src/pypy/interpreter/test/test_gateway.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_gateway.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_gateway.py Thu Dec 9 18:19:11 2004 @@ -41,10 +41,11 @@ def test_call_args(self): def c(space, w_x, w_y, __args__): + args_w, kwds_w = __args__.unpack() u = space.unwrap w = space.wrap - return w((u(w_x) - u(w_y) + len(__args__.args_w)) - * u(__args__.kwds_w['boo'])) + return w((u(w_x) - u(w_y) + len(args_w)) + * u(kwds_w['boo'])) code = gateway.BuiltinCode(c) w = self.space.wrap w_dict = self.space.newdict([ Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Thu Dec 9 18:19:11 2004 @@ -180,6 +180,50 @@ ''' % ((longexpr,)*10) self.assertEquals(self.codetest(code, 'f', [3]), 0) + def test_call_star_starstar(self): + code = ''' +def f1(n): + return n*2 +def f38(n): + f = f1 + r = [ + f(n, *[]), + f(n), + apply(f, (n,)), + apply(f, [n]), + f(*(n,)), + f(*[n]), + f(n=n), + f(**{'n': n}), + apply(f, (n,), {}), + apply(f, [n], {}), + f(*(n,), **{}), + f(*[n], **{}), + f(n, **{}), + f(n, *[], **{}), + f(n=n, **{}), + f(n=n, *[], **{}), + f(*(n,), **{}), + f(*[n], **{}), + f(*[], **{'n':n}), + ] + return r +''' + self.assertEquals(self.codetest(code, 'f38', [117]), [234]*19) + + def test_star_arg(self): + code = textwrap.dedent(''' + def f(x, *y): + return y + def g(u, v): + return f(u, *v) + ''') + self.assertEquals(self.codetest(code, 'g', [12, ()]), ()) + self.assertEquals(self.codetest(code, 'g', [12, (3,4)]), (3,4)) + self.assertEquals(self.codetest(code, 'g', [12, []]), ()) + self.assertEquals(self.codetest(code, 'g', [12, [3,4]]), (3,4)) + self.assertEquals(self.codetest(code, 'g', [12, {}]), ()) + self.assertEquals(self.codetest(code, 'g', [12, {3:1}]), (3,)) class AppTestInterpreter(testit.AppTestCase): def test_trivial(self): Modified: pypy/trunk/src/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/flow/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/flow/objspace.py Thu Dec 9 18:19:11 2004 @@ -154,25 +154,28 @@ def unpackiterable(self, w_iterable, expected_length=None): if isinstance(w_iterable, Variable) and expected_length is None: - # XXX TEMPORARY HACK XXX TEMPORARY HACK XXX TEMPORARY HACK - #print ("*** cannot unpack a Variable iterable " - # "without knowing its length,") - #print " assuming a list or tuple with up to 7 items" - items = [] - w_len = self.len(w_iterable) - i = 0 - while True: - w_i = self.wrap(i) - w_cond = self.eq(w_len, w_i) - if self.is_true(w_cond): - break # done - if i == 7: - # too many values - raise OperationError(self.w_AssertionError, self.w_None) - w_item = self.do_operation('getitem', w_iterable, w_i) - items.append(w_item) - i += 1 - return items + raise UnwrapException, ("cannot unpack a Variable iterable" + "without knowing its length") +## # XXX TEMPORARY HACK XXX TEMPORARY HACK XXX TEMPORARY HACK +## print ("*** cannot unpack a Variable iterable " +## "without knowing its length,") +## print " assuming a list or tuple with up to 7 items" +## items = [] +## w_len = self.len(w_iterable) +## i = 0 +## while True: +## w_i = self.wrap(i) +## w_cond = self.eq(w_len, w_i) +## if self.is_true(w_cond): +## break # done +## if i == 7: +## # too many values +## raise OperationError(self.w_AssertionError, self.w_None) +## w_item = self.do_operation('getitem', w_iterable, w_i) +## items.append(w_item) +## i += 1 +## return items +## # XXX TEMPORARY HACK XXX TEMPORARY HACK XXX TEMPORARY HACK elif expected_length is not None: w_len = self.len(w_iterable) w_correct = self.eq(w_len, self.wrap(expected_length)) @@ -180,7 +183,6 @@ raise OperationError(self.w_ValueError, self.w_None) return [self.do_operation('getitem', w_iterable, self.wrap(i)) for i in range(expected_length)] - # XXX TEMPORARY HACK XXX TEMPORARY HACK XXX TEMPORARY HACK return ObjSpace.unpackiterable(self, w_iterable, expected_length) # ____________________________________________________________ @@ -220,11 +222,18 @@ else: return sc(self, fn, args) - if args.kwds_w: - w_args, w_kwds = args.pack() - w_res = self.do_operation('call', w_callable, w_args, w_kwds) + try: + args_w, kwds_w = args.unpack() + except UnwrapError: + args_w, kwds_w = '?', '?' + if not kwds_w: + # simple case + w_res = self.do_operation('simple_call', w_callable, *args_w) else: - w_res = self.do_operation('simple_call', w_callable, *args.args_w) + # general case + shape, args_w = args.flatten() + w_res = self.do_operation('call_args', w_callable, Constant(shape), + *args_w) # maybe the call has generated an exception (any one) # but, let's say, not if we are calling a built-in class or function Modified: pypy/trunk/src/pypy/objspace/flow/specialcase.py ============================================================================== --- pypy/trunk/src/pypy/objspace/flow/specialcase.py (original) +++ pypy/trunk/src/pypy/objspace/flow/specialcase.py Thu Dec 9 18:19:11 2004 @@ -34,8 +34,7 @@ - assumes that Arg is the value you want for the exception, and that Class is exactly the exception class. No check or normalization. """ - assert len(args.args_w) == 3 and args.kwds_w == {} - w_arg1, w_arg2, w_tb = args.args_w + w_arg1, w_arg2, w_tb = args.fixedunpack(3) # w_arg3 (the traceback) is ignored and replaced with None # if it is a Variable, because pyopcode.py tries to unwrap it. @@ -70,18 +69,18 @@ # by FlowObjSpace.unpacktuple() def sc_import(space, fn, args): - assert len(args.args_w) == 4 and args.kwds_w == {} - unwrapped_args = [] - for w_arg in args.args_w: - assert isinstance(w_arg, Constant) - unwrapped_args.append(space.unwrap(w_arg)) - return space.wrap(__import__(*unwrapped_args)) + w_name, w_glob, w_loc, w_frm = args.fixedunpack(4) + return space.wrap(__import__(space.unwrap(w_name), + space.unwrap(w_glob), + space.unwrap(w_loc), + space.unwrap(w_frm))) def sc_operator(space, fn, args): # XXX do this more cleanly - assert args.kwds_w == {} + args_w, kwds_w = args.unpack() + assert kwds_w == {} opname = fn.__name__.replace('__', '') - return space.do_operation(opname, *args.args_w) + return space.do_operation(opname, *args_w) def setup(space): fn = pyframe.normalize_exception.get_function(space) Modified: pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/trunk/src/pypy/objspace/flow/test/test_objspace.py Thu Dec 9 18:19:11 2004 @@ -1,6 +1,7 @@ import autopath from pypy.tool import testit from pypy.objspace.flow.model import Constant +from pypy.interpreter.argument import Arguments class TestFlowObjSpace(testit.TestCase): Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/objecttype.py (original) +++ pypy/trunk/src/pypy/objspace/std/objecttype.py Thu Dec 9 18:19:11 2004 @@ -26,9 +26,13 @@ # don't allow arguments if the default object.__init__() is about # to be called w_parentinit, w_ignored = w_type.lookup_where('__init__') - if w_parentinit is space.w_object and (__args__.args_w or __args__.kwds_w): - raise OperationError(space.w_TypeError, - space.wrap("default __new__ takes no parameters")) + if w_parentinit is space.w_object: + try: + __args__.fixedunpack(0) + except ValueError: + raise OperationError(space.w_TypeError, + space.wrap("default __new__ takes " + "no parameters")) w_obj = space.allocate_instance(W_ObjectObject, w_type) w_obj.__init__(space) return w_obj Modified: pypy/trunk/src/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/src/pypy/objspace/std/typeobject.py Thu Dec 9 18:19:11 2004 @@ -106,9 +106,13 @@ def call__Type(space, w_type, w_args, w_kwds): args = Arguments.frompacked(space, w_args, w_kwds) # special case for type(x) - if (space.is_true(space.is_(w_type, space.w_type)) and - len(args.args_w) == 1 and not args.kwds_w): - return space.type(args.args_w[0]) + if space.is_true(space.is_(w_type, space.w_type)): + try: + w_obj, = args.fixedunpack(1) + except ValueError: + pass + else: + return space.type(w_obj) # invoke the __new__ of the type w_newfunc = space.getattr(w_type, space.wrap('__new__')) w_newobject = space.call_args(w_newfunc, args.prepend(w_type)) Modified: pypy/trunk/src/pypy/objspace/trivial.py ============================================================================== --- pypy/trunk/src/pypy/objspace/trivial.py (original) +++ pypy/trunk/src/pypy/objspace/trivial.py Thu Dec 9 18:19:11 2004 @@ -341,7 +341,8 @@ obj = self.unwrap(w_obj) if hasattr(w_descr, '__get__'): obj = w_descr.__get__(obj, type(obj)) - return obj(*args.args_w, **args.kwds_w) + args_w, kwds_w = args.unpack() + return obj(*args_w, **kwds_w) except: #import traceback; traceback.print_exc() self.reraise() Modified: pypy/trunk/src/pypy/tool/traceop.py ============================================================================== --- pypy/trunk/src/pypy/tool/traceop.py (original) +++ pypy/trunk/src/pypy/tool/traceop.py Thu Dec 9 18:19:11 2004 @@ -199,9 +199,6 @@ if isinstance(value, Method): res = "Method(%s, %s)" % (value.w_function.name, value.w_function.code) - if isinstance(value, Arguments): - res = "Argument(%s, %s)" % (value.args_w, value.kwds_w) - except Exception, exc: pass Modified: pypy/trunk/src/pypy/translator/annrpython.py ============================================================================== --- pypy/trunk/src/pypy/translator/annrpython.py (original) +++ pypy/trunk/src/pypy/translator/annrpython.py Thu Dec 9 18:19:11 2004 @@ -8,7 +8,7 @@ from pypy.objspace.flow.model import Variable, Constant, UndefinedConstant from pypy.objspace.flow.model import SpaceOperation, FunctionGraph from pypy.objspace.flow.model import last_exception, last_exc_value -from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS +from pypy.interpreter.pycode import cpython_code_signature class AnnotatorError(Exception): @@ -176,7 +176,7 @@ #___ interface for annotator.factory _______ - def recursivecall(self, func, position_key, *args): + def recursivecall(self, func, position_key, args): parent_fn, parent_block, parent_index = position_key graph = self.translator.getflowgraph(func, parent_fn, position_key) @@ -185,45 +185,18 @@ # return block of this graph has been analysed. callpositions = self.notify.setdefault(graph.returnblock, {}) callpositions[position_key] = True + + # parse the arguments according to the function we are calling + defs_s = [] + if func.func_defaults: + for x in func.func_defaults: + defs_s.append(self.bookkeeper.immutablevalue(x)) + inputcells = args.parse(func.func_name, + cpython_code_signature(func.func_code), + defs_s) + # generalize the function's input arguments - block = graph.startblock - inputcells = list(args) - # process *varargs in the called function - expectedargs = len(block.inputargs) - if func.func_code.co_flags & CO_VARARGS: - expectedargs -= 1 - if func.func_code.co_flags & CO_VARKEYWORDS: - expectedargs -= 1 - extracells = [] - if func.func_code.co_flags & CO_VARARGS: - s_varargs = annmodel.SomeTuple(inputcells[expectedargs:]) - extracells = [s_varargs] - del inputcells[expectedargs:] - if func.func_code.co_flags & CO_VARKEYWORDS: - raise AnnotatorError, "** argument of %r unsupported" % (func,) - # add default arguments if necessary - if len(inputcells) != expectedargs: - missingargs = expectedargs - len(inputcells) - nbdefaults = len(func.func_defaults or ()) - if not (0 <= missingargs <= nbdefaults): - # XXX hack to avoid "*args" related processing - # to bail out - #v = graph.getreturnvar() - #return self.bindings.get(v, annmodel.SomeImpossibleValue()) - # XXX end hack - if nbdefaults: - msg = "%d to %d" % (expectedargs-nbdefaults, - expectedargs) - else: - msg = "%d" % expectedargs - print ("!!! AnnotatorError, (ignored!!!)" - "got %d inputcells in call to %r; expected %s" % ( - len(inputcells), func, msg)) - return annmodel.SomeImpossibleValue() - for extra in func.func_defaults[-missingargs:]: - inputcells.append(self.bookkeeper.immutablevalue(extra)) - inputcells.extend(extracells) - self.addpendingblock(func, block, inputcells, position_key) + self.addpendingblock(func, graph.startblock, inputcells, position_key) # get the (current) return value v = graph.getreturnvar() @@ -319,6 +292,7 @@ def bindinputargs(self, block, inputcells, called_from=None): # Create the initial bindings for the input args of a block. + assert len(block.inputargs) == len(inputcells) for a, cell in zip(block.inputargs, inputcells): self.setbinding(a, cell, called_from) self.annotated[block] = False # must flowin. Modified: pypy/trunk/src/pypy/translator/genpyrex.py ============================================================================== --- pypy/trunk/src/pypy/translator/genpyrex.py (original) +++ pypy/trunk/src/pypy/translator/genpyrex.py Thu Dec 9 18:19:11 2004 @@ -3,6 +3,7 @@ """ from pypy.interpreter.baseobjspace import ObjSpace +from pypy.interpreter.argument import Arguments from pypy.objspace.flow.model import Variable, Constant, UndefinedConstant from pypy.objspace.flow.model import mkentrymap, last_exception from pypy.translator.annrpython import RPythonAnnotator @@ -108,9 +109,16 @@ a = self.argnames return "%s = slice(%s, %s, %s)" % (self.resultname, a[0], a[1], a[2]) - def op_call(self): + def op_call_args(self): a = self.argnames - return "%s = %s(*%s, **%s)" % (self.resultname, a[0], a[1], a[2]) + shape = self.op.args[1].value + args = Arguments.fromshape(None, shape, a[2:]) + lst = args.arguments_w[:] + for key, value in args.kwds_w: + lst.append("%s=%s" % (key, value)) + if args.w_stararg is not None: + lst.append("*%s" % args.w_stararg) + return "%s = %s(%s)" % (self.resultname, a[0], ", ".join(lst)) def op_simple_call(self): a = self.argnames Modified: pypy/trunk/src/pypy/translator/tool/flowtrace.py ============================================================================== --- pypy/trunk/src/pypy/translator/tool/flowtrace.py (original) +++ pypy/trunk/src/pypy/translator/tool/flowtrace.py Thu Dec 9 18:19:11 2004 @@ -19,6 +19,7 @@ from pypy.objspace.flow.model import traverse, Constant, Variable, Block, Link from pypy.translator.simplify import simplify_graph from pypy.interpreter.baseobjspace import OperationError +from pypy.interpreter.argument import Arguments class FlowTracer(object): @@ -141,9 +142,11 @@ else: res = self.space.w_None - elif op.opname == "simple_call": - assert (len(opargs) >= 1) - res = self.simple_call(opargs[0], *opargs[1:]) + elif op.opname == "call_args": + assert (len(opargs) >= 2) + shape = self.space.unwrap(opargs[1]) + args = Arguments.fromshape(shape, *opargs[2:]) + res = self.call_args(opargs[0], args) else: # More special cases @@ -225,15 +228,16 @@ return result.e_value - def simple_call(self, w_func, *args_w): + def call_args(self, w_func, args): func = self.space.unwrap(w_func) if hasattr(func, "func_code"): graph = self.flow_space.build_flow(func) simplify_graph(graph) if self.debug: - debug(func) - return self.execute_function(graph, *args_w) + debug(func) + scope_w = args.parse(func.name, func.code.signature(), func.defs_w) + return self.execute_function(graph, *scope_w) else: # XXX We could try creating the flow graph by runnning another @@ -244,7 +248,7 @@ if self.trace: print "WOA! Cheating!", w_func - return self.space.call_function(w_func, *args_w) + return self.space.call_args(w_func, args) def call(self, f, *args): @@ -252,7 +256,7 @@ args_w = [w(ii) for ii in args] w_func = w(f) - res = self.simple_call(w_func, *args_w) + res = self.call_args(w_func, Arguments(self.space, args_w)) return self.space.unwrap(res) @@ -282,7 +286,6 @@ import new from pypy.interpreter.gateway import app2interp - from pypy.interpreter.argument import Arguments # Horrible hack (ame needs to start with "app_") app_func = new.function(app_func.func_code, Modified: pypy/trunk/src/pypy/translator/transform.py ============================================================================== --- pypy/trunk/src/pypy/translator/transform.py (original) +++ pypy/trunk/src/pypy/translator/transform.py Thu Dec 9 18:19:11 2004 @@ -12,6 +12,20 @@ # XXX: Lots of duplicated codes. Fix this! +# ---------------------------------------------------------------------- +# The 'call_args' operation is the strangest one. The meaning of its +# arguments is as follows: +# +# call_args(, , , , ...) +# +# The shape must be a constant object, which describes how the remaining +# arguments are regrouped. The class pypy.interpreter.argument.Arguments +# has a method 'fromshape(shape, list-of-args)' that reconstructs a complete +# Arguments instance from this information. Don't try to interpret the +# shape anywhere else, but for reference, it is a 3-tuple: +# (number-of-pos-arg, tuple-of-keyword-names, flag-presence-of-*-arg) +# ---------------------------------------------------------------------- + # [a] * b # --> # c = newlist(a) @@ -75,7 +89,7 @@ # --> # e = simple_call(a, *b) -## REMOVED: now FlowObjSpace produces 'simple_call' operations only +## REMOVED: now FlowObjSpace produces 'call_args' operations only ##def transform_simple_call(self): ## """Transforms call(a, (...), {}) to simple_call(a, ...)""" ## for block in self.annotated: From arigo at codespeak.net Thu Dec 9 18:22:54 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 18:22:54 +0100 (MET) Subject: [pypy-svn] r7792 - pypy/trunk/src/pypy/objspace/flow Message-ID: <20041209172254.A04155A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 18:22:54 2004 New Revision: 7792 Modified: pypy/trunk/src/pypy/objspace/flow/objspace.py Log: Typo. Modified: pypy/trunk/src/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/trunk/src/pypy/objspace/flow/objspace.py (original) +++ pypy/trunk/src/pypy/objspace/flow/objspace.py Thu Dec 9 18:22:54 2004 @@ -224,7 +224,7 @@ try: args_w, kwds_w = args.unpack() - except UnwrapError: + except UnwrapException: args_w, kwds_w = '?', '?' if not kwds_w: # simple case From arigo at codespeak.net Thu Dec 9 19:23:57 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 19:23:57 +0100 (MET) Subject: [pypy-svn] r7793 - pypy/trunk/src/pypy/annotation Message-ID: <20041209182357.DD61D5A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 19:23:55 2004 New Revision: 7793 Modified: pypy/trunk/src/pypy/annotation/binaryop.py pypy/trunk/src/pypy/annotation/model.py pypy/trunk/src/pypy/annotation/unaryop.py Log: - why does SomeBuiltin inherit from SomePBC? Can't find a good reason any more... Fixed. - yet another hack in RPythonCallsSpace. Modified: pypy/trunk/src/pypy/annotation/binaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/binaryop.py (original) +++ pypy/trunk/src/pypy/annotation/binaryop.py Thu Dec 9 19:23:55 2004 @@ -275,8 +275,6 @@ class __extend__(pairtype(SomePBC, SomePBC)): def union((pbc1, pbc2)): - if isinstance(pbc1, SomeBuiltin) or isinstance(pbc2, SomeBuiltin): - assert False, "merging builtin & PBC == BAD!" if len(pbc2.prebuiltinstances) > len(pbc1.prebuiltinstances): pbc1, pbc2 = pbc2, pbc1 d = pbc1.prebuiltinstances.copy() Modified: pypy/trunk/src/pypy/annotation/model.py ============================================================================== --- pypy/trunk/src/pypy/annotation/model.py (original) +++ pypy/trunk/src/pypy/annotation/model.py Thu Dec 9 19:23:55 2004 @@ -214,7 +214,7 @@ else: return kt.__name__ -class SomeBuiltin(SomePBC): +class SomeBuiltin(SomeObject): "Stands for a built-in function or method with special-cased analysis." knowntype = BuiltinFunctionType # == BuiltinMethodType def __init__(self, analyser, s_self=None): Modified: pypy/trunk/src/pypy/annotation/unaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/unaryop.py (original) +++ pypy/trunk/src/pypy/annotation/unaryop.py Thu Dec 9 19:23:55 2004 @@ -249,6 +249,14 @@ def newdict(self, stuff): raise Exception, "call pattern too complicated (** argument)" + def unpackiterable(self, s_obj, expected_length=None): + if isinstance(s_obj, SomeTuple): + if (expected_length is not None and + expected_length != len(s_obj.items)): + raise ValueError + return s_obj.items + raise Exception, "RPythonCallsSpace.unpackiterable(): only for tuples" + # XXX the following is only a hack to lead Arguments.parse() believe # XXX that the *arg is always a tuple! w_tuple = object() From arigo at codespeak.net Thu Dec 9 21:50:06 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 21:50:06 +0100 (MET) Subject: [pypy-svn] r7794 - in pypy/trunk/src/pypy: annotation objspace/std Message-ID: <20041209205006.768145A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 21:50:05 2004 New Revision: 7794 Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py pypy/trunk/src/pypy/objspace/std/multimethod.py pypy/trunk/src/pypy/objspace/std/stdtypedef.py Log: - fixed the specialization of functions taking a *arg based on the number of actual arguments provided, which was disabled after the recent extension of the Arguments class. - replaced a regular args with a *args in multimethod.py to trigger the above specialization. But this kind of rewrite isn't enough e.g. for BuiltinFrame.run()... Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/trunk/src/pypy/annotation/bookkeeper.py (original) +++ pypy/trunk/src/pypy/annotation/bookkeeper.py Thu Dec 9 21:50:05 2004 @@ -8,6 +8,7 @@ from pypy.annotation.classdef import ClassDef from pypy.interpreter.miscutils import getthreadlocals from pypy.tool.hack import func_with_new_name +from pypy.interpreter.pycode import CO_VARARGS class Bookkeeper: """The log of choices that have been made while analysing the operations. @@ -221,11 +222,18 @@ else: raise Exception, "unsupported specialization type '%s'"%(x,) -## elif func.func_code.co_flags & CO_VARARGS: -## # calls to *arg functions: create one version per number of args -## func = self.specialize_by_key(func, len(args), -## name='%s__%d' % (func.func_name, -## len(args))) + elif func.func_code.co_flags & CO_VARARGS: + # calls to *arg functions: create one version per number of args + assert not args.kwds_w, ( + "keyword forbidden in calls to *arg functions") + nbargs = len(args.arguments_w) + if args.w_stararg is not None: + s_len = args.w_stararg.len() + assert s_len.is_constant(), "calls require known number of args" + nbargs += s_len.const + func = self.specialize_by_key(func, nbargs, + name='%s__%d' % (func.func_name, + nbargs)) return self.annotator.recursivecall(func, self.position_key, args) def specialize_by_key(self, thing, key, name=None): Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/multimethod.py (original) +++ pypy/trunk/src/pypy/objspace/std/multimethod.py Thu Dec 9 21:50:05 2004 @@ -466,7 +466,7 @@ raise TypeError, ("multimethod needs at least %d arguments" % self.multimethod.arity) try: - return self.perform_call(args) + return self.perform_call(*args) except FailedToImplement, e: if e.args: raise OperationError(e.args[0], e.args[1]) @@ -485,7 +485,7 @@ w_value = self.space.wrap(message) raise OperationError(self.space.w_TypeError, w_value) - def perform_call(self, args): + def perform_call(self, *args): for a in args: assert isinstance(a, self.ASSERT_BASE_TYPE), ( "'%s' multimethod got a non-wrapped argument: %r" % ( Modified: pypy/trunk/src/pypy/objspace/std/stdtypedef.py ============================================================================== --- pypy/trunk/src/pypy/objspace/std/stdtypedef.py (original) +++ pypy/trunk/src/pypy/objspace/std/stdtypedef.py Thu Dec 9 21:50:05 2004 @@ -176,7 +176,7 @@ args = list(self.fastlocals_w) args.insert(0, args.pop(self.code.bound_position)) try: - return self.code.mm.perform_call(args) + return self.code.mm.perform_call(*args) except FailedToImplement, e: if e.args: raise OperationError(e.args[0], e.args[1]) From arigo at codespeak.net Thu Dec 9 22:25:54 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 22:25:54 +0100 (MET) Subject: [pypy-svn] r7795 - pypy/trunk/src/pypy/interpreter Message-ID: <20041209212554.9FE7A5A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 22:25:54 2004 New Revision: 7795 Modified: pypy/trunk/src/pypy/interpreter/argument.py Log: Fix the following misleading error message: >>> def f(x, *y): pass ... >>> f() TypeError: f() takes exactly 1 argument (0 given) ^^^^^^^ Modified: pypy/trunk/src/pypy/interpreter/argument.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/argument.py (original) +++ pypy/trunk/src/pypy/interpreter/argument.py Thu Dec 9 22:25:54 2004 @@ -197,7 +197,7 @@ nargs) else: defcount = len(defaults_w) - if defcount == 0: + if defcount == 0 and varargname is None: msg1 = "exactly" elif too_many: msg1 = "at most" From arigo at codespeak.net Thu Dec 9 22:40:56 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 22:40:56 +0100 (MET) Subject: [pypy-svn] r7796 - in pypy/trunk/src/pypy: annotation interpreter translator Message-ID: <20041209214056.9A6D25A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 22:40:56 2004 New Revision: 7796 Modified: pypy/trunk/src/pypy/annotation/unaryop.py pypy/trunk/src/pypy/interpreter/argument.py pypy/trunk/src/pypy/translator/annrpython.py Log: In class Arguments, split method parse() in two: the outer parse() with the same semantics now calls an inner match_signature() which makes little use of self.space and raises ArgErr exceptions, which parse() turns into OperationErrors with complete error messages. Allows some clean-up of the RPythonCallsSpace hack and reintroduction of the hack in annrpython which allows mismatching calls to be ignored (with a warning message). Modified: pypy/trunk/src/pypy/annotation/unaryop.py ============================================================================== --- pypy/trunk/src/pypy/annotation/unaryop.py (original) +++ pypy/trunk/src/pypy/annotation/unaryop.py Thu Dec 9 22:40:56 2004 @@ -65,11 +65,11 @@ return obj # default unbound __get__ implementation def simple_call(obj, *args_s): - space = RPythonCallsSpace(getbookkeeper()) + space = RPythonCallsSpace() return obj.call(Arguments(space, args_s)) def call_args(obj, s_shape, *args_s): - space = RPythonCallsSpace(getbookkeeper()) + space = RPythonCallsSpace() return obj.call(Arguments.fromshape(space, s_shape.const, args_s)) def call(obj, args): @@ -240,14 +240,11 @@ For the Arguments class: if it really needs other operations, it means that the call pattern is too complex for R-Python. """ - def __init__(self, bookkeeper): - self.bookkeeper = bookkeeper - def newtuple(self, items_s): return SomeTuple(items_s) def newdict(self, stuff): - raise Exception, "call pattern too complicated (** argument)" + raise CallPatternTooComplex, "'**' argument" def unpackiterable(self, s_obj, expected_length=None): if isinstance(s_obj, SomeTuple): @@ -255,14 +252,7 @@ expected_length != len(s_obj.items)): raise ValueError return s_obj.items - raise Exception, "RPythonCallsSpace.unpackiterable(): only for tuples" + raise CallPatternTooComplex, "'*' argument must be SomeTuple" - # XXX the following is only a hack to lead Arguments.parse() believe - # XXX that the *arg is always a tuple! - w_tuple = object() - def type(self, w_obj): - return self.w_tuple - def is_(self, w1, w2): - return w1 is w2 - def is_true(self, x): - return bool(x) +class CallPatternTooComplex(Exception): + pass Modified: pypy/trunk/src/pypy/interpreter/argument.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/argument.py (original) +++ pypy/trunk/src/pypy/interpreter/argument.py Thu Dec 9 22:40:56 2004 @@ -110,6 +110,23 @@ according to the signature of code object. """ space = self.space + # If w_stararg is not exactly a tuple, unpack it now: + # self.match_signature() assumes that it can use it directly for + # a matching *arg in the callee's signature. + if self.w_stararg is not None: + if not space.is_true(space.is_(space.type(self.w_stararg), + space.w_tuple)): + self.unpack() + try: + return self.match_signature(signature, defaults_w) + except ArgErr, e: + raise OperationError(space.w_TypeError, + space.wrap(e.getmsg(self, fnname))) + + def match_signature(self, signature, defaults_w=[]): + """Parse args and kwargs according to the signature of a code object, + or raise ArgumentMatch in case of failure. + """ argnames, varargname, kwargname = signature # # args_w = list of the normal actual parameters, wrapped @@ -117,16 +134,11 @@ # argnames = list of formal parameter names # scope_w = resulting list of wrapped values # - # We try to give error messages following CPython's, which are - # very informative. - # co_argcount = len(argnames) # expected formal arguments, without */** if self.w_stararg is not None: # There is a case where we don't have to unpack() a w_stararg: # if it matches exactly a *arg in the signature. - if (len(self.arguments_w) == co_argcount and varargname is not None - and space.is_true(space.is_(space.type(self.w_stararg), - space.w_tuple))): + if len(self.arguments_w) == co_argcount and varargname is not None: pass else: self.unpack() # sets self.w_stararg to None @@ -144,7 +156,7 @@ if kwds_w: for name in argnames[self.blind_arguments:input_argcount]: if name in kwds_w: - self.raise_argerr_multiple_values(fnname, name) + raise ArgErrMultipleValues(name) remainingkwds_w = kwds_w.copy() if input_argcount < co_argcount: @@ -158,31 +170,64 @@ elif i >= def_first: scope_w.append(defaults_w[i-def_first]) else: - self.raise_argerr(fnname, signature, defaults_w, False) + raise ArgErrCount(signature, defaults_w, False) # collect extra positional arguments into the *vararg if varargname is not None: if self.w_stararg is None: # common case - scope_w.append(space.newtuple(args_w[co_argcount:])) + scope_w.append(self.space.newtuple(args_w[co_argcount:])) else: # shortcut for the non-unpack() case above scope_w.append(self.w_stararg) elif len(args_w) > co_argcount: - self.raise_argerr(fnname, signature, defaults_w, True) + raise ArgErrCount(signature, defaults_w, True) # collect extra keyword arguments into the **kwarg if kwargname is not None: - w_kwds = space.newdict([(space.wrap(key), w_value) - for key, w_value in remainingkwds_w.items()]) + w_kwds = self.space.newdict([]) + for key, w_value in remainingkwds_w.items(): + self.space.setitem(w_kwds, self.space.wrap(key), w_value) scope_w.append(w_kwds) elif remainingkwds_w: - self.raise_argerr_unknown_kwds(fnname, remainingkwds_w) + raise ArgErrUnknownKwds(remainingkwds_w) return scope_w - # helper functions to build error message for the above + ### Argument <-> list of w_objects together with "shape" information + + def flatten(self): + shape_cnt = len(self.arguments_w) # Number of positional args + shape_keys = self.kwds_w.keys() # List of keywords (strings) + shape_star = self.w_stararg is not None # Flag: presence of *arg + data_w = self.arguments_w + [self.kwds_w[key] for key in shape_keys] + if shape_star: + data_w.append(self.w_stararg) + return (shape_cnt, tuple(shape_keys), shape_star), data_w + + def fromshape(space, (shape_cnt, shape_keys, shape_star), data_w): + args_w = data_w[:shape_cnt] + kwds_w = {} + for i in range(len(shape_keys)): + kwds_w[shape_keys[i]] = data_w[shape_cnt+i] + if shape_star: + w_star = data_w[-1] + else: + w_star = None + return Arguments(space, args_w, kwds_w, w_star) + fromshape = staticmethod(fromshape) - def raise_argerr(self, fnname, signature, defaults_w, too_many): + +# +# ArgErr family of exceptions raised in case of argument mismatch. +# We try to give error messages following CPython's, which are very informative. +# + +class ArgErr(Exception): + pass + +class ArgErrCount(ArgErr): + def getmsg(self, args, fnname): + signature, defaults_w, too_many = self.args # from self.__init__() argnames, varargname, kwargname = signature - args_w, kwds_w = self.unpack() + args_w, kwds_w = args.unpack() nargs = len(args_w) n = len(argnames) if n == 0: @@ -219,15 +264,19 @@ msg2, plural, nargs) - raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) + return msg - def raise_argerr_multiple_values(self, fnname, argname): +class ArgErrMultipleValues(ArgErr): + def getmsg(self, args, fnname): + argname, = self.args # from self.__init__() msg = "%s() got multiple values for keyword argument '%s'" % ( fnname, argname) - raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) + return msg - def raise_argerr_unknown_kwds(self, fnname, kwds_w): +class ArgErrUnknownKwds(ArgErr): + def getmsg(self, args, fnname): + kwds_w, = self.args # from self.__init__() if len(kwds_w) == 1: msg = "%s() got an unexpected keyword argument '%s'" % ( fnname, @@ -236,27 +285,4 @@ msg = "%s() got %d unexpected keyword arguments" % ( fnname, len(kwds_w)) - raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) - - ### Argument <-> list of w_objects together with "shape" information - - def flatten(self): - shape_cnt = len(self.arguments_w) # Number of positional args - shape_keys = self.kwds_w.keys() # List of keywords (strings) - shape_star = self.w_stararg is not None # Flag: presence of *arg - data_w = self.arguments_w + [self.kwds_w[key] for key in shape_keys] - if shape_star: - data_w.append(self.w_stararg) - return (shape_cnt, tuple(shape_keys), shape_star), data_w - - def fromshape(space, (shape_cnt, shape_keys, shape_star), data_w): - args_w = data_w[:shape_cnt] - kwds_w = {} - for i in range(len(shape_keys)): - kwds_w[shape_keys[i]] = data_w[shape_cnt+i] - if shape_star: - w_star = data_w[-1] - else: - w_star = None - return Arguments(space, args_w, kwds_w, w_star) - fromshape = staticmethod(fromshape) + return msg Modified: pypy/trunk/src/pypy/translator/annrpython.py ============================================================================== --- pypy/trunk/src/pypy/translator/annrpython.py (original) +++ pypy/trunk/src/pypy/translator/annrpython.py Thu Dec 9 22:40:56 2004 @@ -9,6 +9,7 @@ from pypy.objspace.flow.model import SpaceOperation, FunctionGraph from pypy.objspace.flow.model import last_exception, last_exc_value from pypy.interpreter.pycode import cpython_code_signature +from pypy.interpreter.argument import ArgErr class AnnotatorError(Exception): @@ -187,13 +188,16 @@ callpositions[position_key] = True # parse the arguments according to the function we are calling + signature = cpython_code_signature(func.func_code) defs_s = [] if func.func_defaults: for x in func.func_defaults: defs_s.append(self.bookkeeper.immutablevalue(x)) - inputcells = args.parse(func.func_name, - cpython_code_signature(func.func_code), - defs_s) + try: + inputcells = args.match_signature(signature, defs_s) + except ArgErr, e: + print 'IGNORED', e # hopefully temporary hack + return SomeImpossibleValue() # generalize the function's input arguments self.addpendingblock(func, graph.startblock, inputcells, position_key) From arigo at codespeak.net Thu Dec 9 22:48:56 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 22:48:56 +0100 (MET) Subject: [pypy-svn] r7797 - pypy/trunk/src/pypy/translator Message-ID: <20041209214856.D855A5A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 22:48:56 2004 New Revision: 7797 Modified: pypy/trunk/src/pypy/translator/annrpython.py Log: Oups! Typo again. Modified: pypy/trunk/src/pypy/translator/annrpython.py ============================================================================== --- pypy/trunk/src/pypy/translator/annrpython.py (original) +++ pypy/trunk/src/pypy/translator/annrpython.py Thu Dec 9 22:48:56 2004 @@ -197,7 +197,7 @@ inputcells = args.match_signature(signature, defs_s) except ArgErr, e: print 'IGNORED', e # hopefully temporary hack - return SomeImpossibleValue() + return annmodel.SomeImpossibleValue() # generalize the function's input arguments self.addpendingblock(func, graph.startblock, inputcells, position_key) From arigo at codespeak.net Thu Dec 9 23:01:02 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 23:01:02 +0100 (MET) Subject: [pypy-svn] r7798 - pypy/trunk/src/pypy/annotation Message-ID: <20041209220102.B78915A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 23:01:02 2004 New Revision: 7798 Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py Log: Too much specialization: don't need to specialize for the case of a *arg in a call to a function expecting a *arg. Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/trunk/src/pypy/annotation/bookkeeper.py (original) +++ pypy/trunk/src/pypy/annotation/bookkeeper.py Thu Dec 9 23:01:02 2004 @@ -222,8 +222,9 @@ else: raise Exception, "unsupported specialization type '%s'"%(x,) - elif func.func_code.co_flags & CO_VARARGS: - # calls to *arg functions: create one version per number of args + elif func.func_code.co_flags & CO_VARARGS and args.w_stararg is None: + # calls to *arg functions without an incoming w_stararg: + # create one version per number of args assert not args.kwds_w, ( "keyword forbidden in calls to *arg functions") nbargs = len(args.arguments_w) From arigo at codespeak.net Thu Dec 9 23:06:45 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Dec 2004 23:06:45 +0100 (MET) Subject: [pypy-svn] r7799 - pypy/trunk/src/pypy/annotation Message-ID: <20041209220645.EB3595A6E7@thoth.codespeak.net> Author: arigo Date: Thu Dec 9 23:06:45 2004 New Revision: 7799 Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py Log: Revert the latest check-in. We need a better idea to solve the current translate_pypy failure... Modified: pypy/trunk/src/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/trunk/src/pypy/annotation/bookkeeper.py (original) +++ pypy/trunk/src/pypy/annotation/bookkeeper.py Thu Dec 9 23:06:45 2004 @@ -222,9 +222,8 @@ else: raise Exception, "unsupported specialization type '%s'"%(x,) - elif func.func_code.co_flags & CO_VARARGS and args.w_stararg is None: - # calls to *arg functions without an incoming w_stararg: - # create one version per number of args + elif func.func_code.co_flags & CO_VARARGS: + # calls to *arg functions: create one version per number of args assert not args.kwds_w, ( "keyword forbidden in calls to *arg functions") nbargs = len(args.arguments_w) From arigo at codespeak.net Fri Dec 10 12:27:47 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 10 Dec 2004 12:27:47 +0100 (MET) Subject: [pypy-svn] r7804 - in pypy/trunk/src/pypy: interpreter translator translator/test Message-ID: <20041210112747.7BEB35AA8E@thoth.codespeak.net> Author: arigo Date: Fri Dec 10 12:27:46 2004 New Revision: 7804 Modified: pypy/trunk/src/pypy/interpreter/argument.py pypy/trunk/src/pypy/translator/genc.h pypy/trunk/src/pypy/translator/genc.py pypy/trunk/src/pypy/translator/test/snippet.py pypy/trunk/src/pypy/translator/test/test_ctrans.py Log: Implemented call_args() in genc.h. Note that genc.py generates functions that never accept any keyword parameter, even though call_args() can now send keyword parameters. Modified: pypy/trunk/src/pypy/interpreter/argument.py ============================================================================== --- pypy/trunk/src/pypy/interpreter/argument.py (original) +++ pypy/trunk/src/pypy/interpreter/argument.py Fri Dec 10 12:27:46 2004 @@ -213,6 +213,8 @@ w_star = None return Arguments(space, args_w, kwds_w, w_star) fromshape = staticmethod(fromshape) + # XXX the "shape" tuple should be considered as a black box from + # other code, but translator/genc.h examines it. # Modified: pypy/trunk/src/pypy/translator/genc.h ============================================================================== --- pypy/trunk/src/pypy/translator/genc.h (original) +++ pypy/trunk/src/pypy/translator/genc.h Fri Dec 10 12:27:46 2004 @@ -144,7 +144,7 @@ #define OP_SIMPLE_CALL(args,r,err) if (!(r=PyObject_CallFunctionObjArgs args)) \ FAIL(err) -#define OP_CALL(x,y,z,r,err) if (!(r=PyObject_Call(x,y,z))) FAIL(err) +#define OP_CALL_ARGS(args,r,err) if (!(r=CallWithShape args)) FAIL(err) /* Needs to act like getattr(x, '__class__', type(x)) */ #define OP_TYPE(x,r,err) { \ @@ -453,6 +453,73 @@ return NULL; } +static PyObject* CallWithShape(PyObject* callable, PyObject* shape, ...) +{ + /* XXX the 'shape' argument is a tuple as specified by + XXX pypy.interpreter.argument.fromshape(). This code should + XXX we made independent on the format of the 'shape' later... */ + PyObject* result = NULL; + PyObject* t = NULL; + PyObject* d = NULL; + PyObject* o; + PyObject* key; + PyObject* t2; + int i, nargs, nkwds, nvarargs, starflag; + va_list vargs; + + if (!PyTuple_Check(shape) || + PyTuple_GET_SIZE(shape) != 3 || + !PyInt_Check(PyTuple_GET_ITEM(shape, 0)) || + !PyTuple_Check(PyTuple_GET_ITEM(shape, 1)) || + !PyInt_Check(PyTuple_GET_ITEM(shape, 2))) { + Py_FatalError("in genc.h: invalid 'shape' argument"); + } + nargs = PyInt_AS_LONG(PyTuple_GET_ITEM(shape, 0)); + nkwds = PyTuple_GET_SIZE(PyTuple_GET_ITEM(shape, 1)); + starflag = PyInt_AS_LONG(PyTuple_GET_ITEM(shape, 2)); + + va_start(vargs, shape); + t = PyTuple_New(nargs); + if (t == NULL) + goto finally; + for (i = 0; i < nargs; i++) { + o = va_arg(vargs, PyObject *); + Py_INCREF(o); + PyTuple_SET_ITEM(t, i, o); + } + if (nkwds) { + d = PyDict_New(); + if (d == NULL) + goto finally; + for (i = 0; i < nkwds; i++) { + o = va_arg(vargs, PyObject *); + key = PyTuple_GET_ITEM(PyTuple_GET_ITEM(shape, 1), i); + if (PyDict_SetItem(d, key, o) < 0) + goto finally; + } + } + if (starflag) { + o = va_arg(vargs, PyObject *); + o = PySequence_Tuple(o); + if (o == NULL) + goto finally; + t2 = PySequence_Concat(t, o); + Py_DECREF(o); + Py_DECREF(t); + t = t2; + if (t == NULL) + goto finally; + } + va_end(vargs); + + result = PyObject_Call(callable, t, d); + + finally: + Py_XDECREF(d); + Py_XDECREF(t); + return result; +} + #if defined(USE_CALL_TRACE) Modified: pypy/trunk/src/pypy/translator/genc.py ============================================================================== --- pypy/trunk/src/pypy/translator/genc.py (original) +++ pypy/trunk/src/pypy/translator/genc.py Fri Dec 10 12:27:46 2004 @@ -11,7 +11,7 @@ from pypy.translator.simplify import remove_direct_loops from pypy.interpreter.pycode import CO_VARARGS from pypy.annotation import model as annmodel -from types import FunctionType +from types import FunctionType, CodeType from pypy.objspace.std.restricted_int import r_int, r_uint @@ -354,6 +354,7 @@ unicode:'&PyUnicode_Type', file: '&PyFile_Type', type(None): 'Py_None->ob_type', + CodeType: '&PyCode_Type', r_int: '&PyInt_Type', r_uint: '&PyInt_Type', @@ -817,6 +818,9 @@ args.append('NULL') return 'OP_SIMPLE_CALL((%s), %s, %s)' % (', '.join(args), r, err) + def OP_CALL_ARGS(self, args, r, err): + return 'OP_CALL_ARGS((%s), %s, %s)' % (', '.join(args), r, err) + # ____________________________________________________________ def cdecl(type, name): Modified: pypy/trunk/src/pypy/translator/test/snippet.py ============================================================================== --- pypy/trunk/src/pypy/translator/test/snippet.py (original) +++ pypy/trunk/src/pypy/translator/test/snippet.py Fri Dec 10 12:27:46 2004 @@ -534,6 +534,12 @@ return (default_and_star_args(111, u), default_and_star_args(-1000, -2000, -3000, -4000, -5000)) +def call_with_star(z): + return default_args(-20, *z) + +def call_with_keyword(z): + return default_args(-20, z=z) + def powerset(setsize=int): """Powerset Modified: pypy/trunk/src/pypy/translator/test/test_ctrans.py ============================================================================== --- pypy/trunk/src/pypy/translator/test/test_ctrans.py (original) +++ pypy/trunk/src/pypy/translator/test/test_ctrans.py Fri Dec 10 12:27:46 2004 @@ -140,6 +140,22 @@ self.assertEquals(call_default_and_star_args(42), (111+42+3+0, -1000-2000-3000+2)) + def test_call_with_star(self): + call_with_star = self.build_cfunc(snippet.call_with_star) + self.assertEquals(call_with_star(()), -15L) + self.assertEquals(call_with_star((4,)), -13L) + self.assertEquals(call_with_star((4,7)), -9L) + self.assertEquals(call_with_star([]), -15L) + self.assertEquals(call_with_star([4]), -13L) + self.assertEquals(call_with_star([4,7]), -9L) + self.assertRaises(TypeError, call_with_star, (4,7,12)) + self.assertRaises(TypeError, call_with_star, [4,7,12,63]) + self.assertRaises(TypeError, call_with_star, 521) + + def XXX_test_call_with_keyword(self): + call_with_keyword = self.build_cfunc(snippet.call_with_keyword) + self.assertEquals(call_with_keyword(100), 82) + def test_finallys(self): finallys = self.build_cfunc(snippet.finallys) self.assertEquals(finallys(['hello']), 8) From jacob at codespeak.net Sat Dec 11 21:14:58 2004 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sat, 11 Dec 2004 21:14:58 +0100 (MET) Subject: [pypy-svn] r7822 - pypy/trunk/doc/funding/negotiations Message-ID: <20041211201458.DD68E5A9B4@thoth.codespeak.net> Author: jacob Date: Sat Dec 11 21:14:58 2004 New Revision: 7822 Added: pypy/trunk/doc/funding/negotiations/part_b_2004_12_11.sxw (contents, props changed) Log: DoW with merlinux, tismerysoft, Heinrich-Heine-Universit?t D?sseldorf added. All abstract dates converted to real dates. Added: pypy/trunk/doc/funding/negotiations/part_b_2004_12_11.sxw ============================================================================== Binary file. No diff available. From jacob at codespeak.net Sat Dec 11 21:16:19 2004 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sat, 11 Dec 2004 21:16:19 +0100 (MET) Subject: [pypy-svn] r7823 - pypy/trunk/doc/funding/negotiations Message-ID: <20041211201619.98D565A9B4@thoth.codespeak.net> Author: jacob Date: Sat Dec 11 21:16:19 2004 New Revision: 7823 Added: pypy/trunk/doc/funding/negotiations/reports Modified: pypy/trunk/doc/funding/negotiations/part_b_2004_07_29.sxw Log: All reports required by the EU, with due dates. Modified: pypy/trunk/doc/funding/negotiations/part_b_2004_07_29.sxw ============================================================================== Binary files. No diff available. Added: pypy/trunk/doc/funding/negotiations/reports ============================================================================== --- (empty file) +++ pypy/trunk/doc/funding/negotiations/reports Sat Dec 11 21:16:19 2004 @@ -0,0 +1,123 @@ +Due 15 January 2006 ++++++++++++++++++++ + +The periodic activity report, +----------------------------- +containing an overview of the activities carried out during the +reporting period, describes the progress in relation to the project +objectives, the progress towards the milestones and deliverables set +for the period, and any problems encountered and corrective actions +taken. It also includes a Publishable executive summary and, as an +Annex, an updated Plan for using and disseminating the knowledge (for +the last reporting period this annex is not necessary) (Article +II.7.2.a of the contract). + +The periodic management report +------------------------------ +includes a detailed justification of the costs incurred and of the +resources deployed by each contractor linking them to activities +implemented and justifying their necessity, the financial statements +(Form C) from each contractor (which may require an Audit +certificate2) and a summary financial report consolidating the costs +of the contractors (Article II.7.2.b of the contract). + +The periodic report on the distribution of the Community's contribution +----------------------------------------------------------------------- +records the distribution of funding to each contractor during that +period (Article II.7.2.c of the contract). + +The interim science and society reporting questionnaire +------------------------------------------------------- +to be completed on-line by the co-ordinator at the end of the first +reporting period only (Article II.10.3 of the contract). + +The interim reporting questionnaire on workforce statistics +----------------------------------------------------------- +to be completed on-line by each contractor at the end of the first +reporting period only (Article II.10.3 of the contract). + +The interim socio-economic reporting questionnaire +-------------------------------------------------- +to be completed online by each contractor at the end of the first +reporting period only (Article II.10.3 of the contract). + +Due 15 january 2007 ++++++++++++++++++++ + +Periodic reports +================ + +The periodic activity report, +----------------------------- +containing an overview of the activities carried out during the +reporting period, describes the progress in relation to the project +objectives, the progress towards the milestones and deliverables set +for the period, and any problems encountered and corrective actions +taken. It also includes a Publishable executive summary and, as an +Annex, an updated Plan for using and disseminating the knowledge (for +the last reporting period this annex is not necessary) (Article +II.7.2.a of the contract). + +The periodic management report +------------------------------ +includes a detailed justification of the costs incurred and of the +resources deployed by each contractor linking them to activities +implemented and justifying their necessity, the financial statements +(Form C) from each contractor and a summary financial report +consolidating the costs of the contractors (Article II.7.2.b of the +contract). + +The periodic report on the distribution of the Community s contribution +----------------------------------------------------------------------- +records the distribution of funding to each contractor during that +period (Article II.7.2.c of the contract). + +Final reports +============= + +A publishable final activity report, +------------------------------------ +covering main aspects of the work, objectives, results and +conclusions, including the publishable results of the final plan for +using and disseminating the knowledge. If the final activity report is +not in a publishable form, a publishable summary should be included as +well (Article II.7.4.a of the contract). + +A final plan for using and disseminating the knowledge +------------------------------------------------------ +(Article II.7.4.a of the contract). + +A final management report +------------------------- +for the full duration of the project consolidating the claimed costs +of all the contractors in an aggregate form covering the entire +duration of the project, including the last reporting period (Article +II.7.4.b of the contract). + +A final science and society reporting questionnaire +--------------------------------------------------- +to be completed online by the co-ordinator (Article II.10.3 of the +contract). + +A final reporting questionnaire on workforce statistics +------------------------------------------------------- +consists of a questionnaire to be completed on-line by each contractor +(Article II.10.3 of the contract). + +A final socio-economic reporting questionnaire +---------------------------------------------- +to be completed on-line by each contractor (Article II.10.3 of the +contract). + +30 January 2007 +=============== + +Final reports +============= + +A final report on the distribution of the Community's contribution +------------------------------------------------------------------ +consolidating the funding distributed to each contractor over the +entire duration of the project (Article II.7.4.d of the contract). + + From jacob at codespeak.net Sat Dec 11 21:24:50 2004 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sat, 11 Dec 2004 21:24:50 +0100 (MET) Subject: [pypy-svn] r7824 - pypy/trunk/doc/funding/negotiations Message-ID: <20041211202450.EE5455A9B4@thoth.codespeak.net> Author: jacob Date: Sat Dec 11 21:24:50 2004 New Revision: 7824 Modified: pypy/trunk/doc/funding/negotiations/reports Log: Fixed last date. Due date is 60 days after receipt of final payment by coordinator according to footnote. Added URL to source EU document. Modified: pypy/trunk/doc/funding/negotiations/reports ============================================================================== --- pypy/trunk/doc/funding/negotiations/reports (original) +++ pypy/trunk/doc/funding/negotiations/reports Sat Dec 11 21:24:50 2004 @@ -1,3 +1,7 @@ +This is a customised extract from: +ftp://ftp.cordis.lu/pub/fp6/docs/reporting_in_fp6-main_en.pdf + + Due 15 January 2006 +++++++++++++++++++ @@ -109,8 +113,8 @@ to be completed on-line by each contractor (Article II.10.3 of the contract). -30 January 2007 -=============== +60 days after receipt of final payment by coordinator ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Final reports ============= From jacob at codespeak.net Sat Dec 11 23:17:14 2004 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sat, 11 Dec 2004 23:17:14 +0100 (MET) Subject: [pypy-svn] r7826 - pypy/trunk/doc/funding/negotiations Message-ID: <20041211221714.9C4475A9B4@thoth.codespeak.net> Author: jacob Date: Sat Dec 11 23:17:14 2004 New Revision: 7826 Added: pypy/trunk/doc/funding/negotiations/Calendar.sxc (contents, props changed) Modified: pypy/trunk/doc/funding/negotiations/part_b_2004_12_11.sxw Log: Added calendar of important dates (spreadsheet). Fixed some typos. Added: pypy/trunk/doc/funding/negotiations/Calendar.sxc ============================================================================== Binary file. No diff available. Modified: pypy/trunk/doc/funding/negotiations/part_b_2004_12_11.sxw ============================================================================== Binary files. No diff available. From hpk at codespeak.net Mon Dec 13 09:46:44 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 13 Dec 2004 09:46:44 +0100 (MET) Subject: [pypy-svn] r7831 - pypy/trunk/doc/funding/negotiations Message-ID: <20041213084644.2067D5AF25@thoth.codespeak.net> Author: hpk Date: Mon Dec 13 09:46:37 2004 New Revision: 7831 Modified: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw Log: rewrote the Section 10 (about "intellectual property" ) by refering to the MIT license (copyrights) and basically barring all partners from filing patents and trade secrets or trademarks (however the latter may be approved by the consortium). I am aware that this is probably not legalese english but hey, i mentioned that i am not a lawyer, didn't I :-) Also, i shortened "Section 12: Publications ..." because it would basically mean that each posting or sprint announcement would have to go to the full consortium committee (which we still have to substitute/amend with our bottom-up management structure anyway) Modified: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw ============================================================================== Binary files. No diff available. From tismer at codespeak.net Mon Dec 13 12:38:54 2004 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 13 Dec 2004 12:38:54 +0100 (MET) Subject: [pypy-svn] r7834 - pypy/trunk/src/pypy/translator Message-ID: <20041213113854.A18725AF25@thoth.codespeak.net> Author: tismer Date: Mon Dec 13 12:38:54 2004 New Revision: 7834 Modified: pypy/trunk/src/pypy/translator/genrpy.py Log: some stuff not yet checked in. Still needs much more work. Modified: pypy/trunk/src/pypy/translator/genrpy.py ============================================================================== --- pypy/trunk/src/pypy/translator/genrpy.py (original) +++ pypy/trunk/src/pypy/translator/genrpy.py Mon Dec 13 12:38:54 2004 @@ -26,58 +26,6 @@ import sys -def somefunc(arg): - pass - -def f(a,b): - print "start" - a = [] - a.append(3) - for i in range(3): - print i - if a > b: - try: - if b == 123: - raise ValueError - elif b == 321: - raise IndexError - return 123 - except ValueError: - raise TypeError - else: - dummy = somefunc(23) - return 42 - -def ff(a, b): - try: - raise SystemError, 42 - return a+b - finally: - a = 7 - -glob = 100 -def fff(): - global glob - return 42+glob - -def app_mod__String_ANY(format, values): - import _formatting - if isinstance(values, tuple): - return _formatting.format(format, values, None) - else: - if hasattr(values, 'keys'): - return _formatting.format(format, (values,), values) - else: - return _formatting.format(format, (values,), None) - -def app_str_decode__String_ANY_ANY(str, encoding=None, errors=None): - if encoding is None and errors is None: - return unicode(str) - elif errors is None: - return unicode(str, encoding) - else: - return unicode(str, encoding, errors) - def ordered_blocks(graph): # collect all blocks @@ -127,8 +75,31 @@ for name in "newtuple newlist newdict newstring".split(): self.has_listarg[name] = name + self.current_globals = {} + self.glob_names = [] + self.glob_values = [] + self.gen_source() + def adjust_namespace(self): + """ inspect the globals of self.current_func and build a searchable list + of the globals. + """ + g = self.current_func.func_globals + if g is self.current_globals: + return + self.current_globals = g + order = [(value, key) for key, value in g.items()] + order.sort() + self.glob_names = [key for value, key in order] + self.glob_values = [value for value, key in order] + + def find_global_name(self, obj): + for i in xrange(len(self.glob_values)): + if self.glob_values[i] is obj: + return self.glob_names[i] + return None + def nameof(self, obj): key = Constant(obj).key try: @@ -196,6 +167,9 @@ return "w(%s)" % value def nameof_str(self, value): + name = self.find_global_name(value) + if name: + return "w(%s)" % name return "w(%s)" % repr(value) def skipped_function(self, func): @@ -223,7 +197,7 @@ func.func_doc.lstrip().startswith('NOT_RPYTHON')): print "skipped", printable_name return self.skipped_function(func) - name = self.uniquename('gfunc_' + func.__name__) + name = func.__name__ self.initcode.append('INITCHK(%s = PyCFunction_New(' '&ml_%s, NULL))' % (name, name)) self.initcode.append('\t%s->ob_type = &PyGenCFunction_Type;' % name) @@ -288,35 +262,7 @@ return name def nameof_builtin_function_or_method(self, func): - if func.__self__ is None: - # builtin function - # where does it come from? Python2.2 doesn't have func.__module__ - for modname, module in sys.modules.items(): - if hasattr(module, '__file__'): - if (module.__file__.endswith('.py') or - module.__file__.endswith('.pyc') or - module.__file__.endswith('.pyo')): - continue # skip non-builtin modules - if func is getattr(module, func.__name__, None): - break - else: - raise Exception, '%r not found in any built-in module' % (func,) - name = self.uniquename('gbltin_' + func.__name__) - if modname == '__builtin__': - self.initcode.append('INITCHK(%s = PyMapping_GetItemString(' - 'PyEval_GetBuiltins(), "%s"))' % ( - name, func.__name__)) - else: - self.initcode.append('INITCHK(%s = PyObject_GetAttrString(' - '%s, "%s"))' % ( - name, self.nameof(module), func.__name__)) - else: - # builtin (bound) method - name = self.uniquename('gbltinmethod_' + func.__name__) - self.initcode.append('INITCHK(%s = PyObject_GetAttrString(' - '%s, "%s"))' % ( - name, self.nameof(func.__self__), func.__name__)) - return name + return "w(%s)" % func.__name__ def nameof_classobj(self, cls): if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'): @@ -399,6 +345,9 @@ return name def nameof_dict(self, dic): + name = self.find_global_name(dic) + if name: + return name return 'space.newdict([w("sorry", "not yet"])' assert dic is not __builtins__ assert '__builtins__' not in dic, 'Seems to be the globals of %s' % ( @@ -451,10 +400,12 @@ 'entrypoint': self.nameof(self.translator.functions[0]), } + # make sure + # function implementations while self.pendingfunctions: func = self.current_func = self.pendingfunctions.pop() - print "#######", func.__name__ + self.adjust_namespace() self.gen_rpyfunction(func) # collect more of the latercode after each function while self.latercode: @@ -465,6 +416,7 @@ self.initcode.append(line) self.debugstack = () #self.gen_global_declarations() + print >> f # footer # maybe not needed @@ -504,11 +456,19 @@ return ", ".join(res) def oper(op): - # specialcase is_true + print op.opname, op.args + if op.opname == "simple_call": + v = op.args[0] + if isinstance(v, Constant) and self.find_global_name(v.value): + fmt = "%s = %s(space, %s)" + else: + fmt = "%s = space.call(%s, space.newtuple([%s]))" + return fmt % (expr(op.result), expr(op.args[0]), arglist(op.args[1:])) if op.opname in self.has_listarg: fmt = "%s = %s([%s])" else: fmt = "%s = %s(%s)" + # specialcase is_true if op.opname == "is_true": return fmt % (expr(op.result, False), expr(op.opname), arglist(op.args)) return fmt % (expr(op.result), expr(op.opname), arglist(op.args)) @@ -591,7 +551,6 @@ for link in block.exits[1:]: assert issubclass(link.exitcase, Exception) yield "except OperationError, e:" - print "*"*10, link.exitcase for op in gen_link(link, { Constant(last_exception): 'e.w_type', Constant(last_exc_value): 'e.w_value'}): @@ -620,9 +579,62 @@ for block in blocks: blockno = blocknum[block] print >> f - print " if goto == %d:" % blockno + print >> f, " if goto == %d:" % blockno for line in render_block(block): - print " %s" % line + print >> f, " %s" % line + +def somefunc(arg): + pass + +def f(a,b): + print "start" + a = [] + a.append(3) + for i in range(3): + print i + if a > b: + try: + if b == 123: + raise ValueError + elif b == 321: + raise IndexError + return 123 + except ValueError: + raise TypeError + else: + dummy = somefunc(23) + return 42 + +def ff(a, b): + try: + raise SystemError, 42 + return a+b + finally: + a = 7 + +glob = 100 +def fff(): + global glob + return 42+glob + +def app_mod__String_ANY(format, values): + import _formatting + if isinstance(values, tuple): + return _formatting.format(format, values, None) + else: + if hasattr(values, 'keys'): + return _formatting.format(format, (values,), values) + else: + return _formatting.format(format, (values,), None) + +def app_str_decode__String_ANY_ANY(str, encoding=None, errors=None): + if encoding is None and errors is None: + return unicode(str) + elif errors is None: + return unicode(str, encoding) + else: + return unicode(str, encoding, errors) + def test_md5(): #import md5 @@ -630,7 +642,10 @@ from pypy.appspace import md5 digest = md5.new("hello") -entry_point = (f, ff, fff, app_str_decode__String_ANY_ANY, app_mod__String_ANY, test_md5) [-1] +def test_mod(): + return app_mod__String_ANY("-%s-", ["hallo"]) + +entry_point = (f, ff, fff, app_str_decode__String_ANY_ANY, test_mod, test_md5) [-2] import os, sys from pypy.interpreter import autopath @@ -641,7 +656,19 @@ hold = sys.path[:] sys.path.insert(0, appdir) t = Translator(entry_point, verbose=False, simplifying=True) - gen = GenRpy(sys.stdout, t) + if 0: + gen = GenRpy(sys.stdout, t) + else: + fil= file("d:/tmp/look.py", "w") + gen = GenRpy(fil, t) + print >> fil, \ +""" +from pypy.objspace.std import StdObjSpace +space = StdObjSpace() +space.simple_call = space.call +test_mod(space) +""" + fil.close() finally: sys.path[:] = hold #t.simplify() @@ -649,4 +676,3 @@ # debugging graph = t.getflowgraph() ab = ordered_blocks(graph) # use ctrl-b in PyWin with ab - From jacob at codespeak.net Mon Dec 13 12:46:51 2004 From: jacob at codespeak.net (jacob at codespeak.net) Date: Mon, 13 Dec 2004 12:46:51 +0100 (MET) Subject: [pypy-svn] r7835 - pypy/trunk/doc/funding/negotiations Message-ID: <20041213114651.CAEDF5AF25@thoth.codespeak.net> Author: jacob Date: Mon Dec 13 12:46:51 2004 New Revision: 7835 Added: pypy/trunk/doc/funding/negotiations/budget Log: Some thoughts on budget. Added: pypy/trunk/doc/funding/negotiations/budget ============================================================================== --- (empty file) +++ pypy/trunk/doc/funding/negotiations/budget Mon Dec 13 12:46:51 2004 @@ -0,0 +1,69 @@ +The project receives 862 538 Euro in pre-financing. This is about 63% +of the total EU funding. + +After 12 months of the project, we have to report the first 12-month +period. The reports must be submitted within 45 days from the end of +the period. The commission then takes 45-90 days to review the +reports. When this is done (and the reports are approved), the +pre-financing is converted into actual payments to the project. Once +this has happened, the commission will also replenish the +pre-financing. However, pre-financing can only be up to 85% of the EU +funding. This means that 202 950 Euro will be withheld until after the +final report from the project. + +After the end of the project the procedure is the same. We submit +reports for the period and final reports. We have 45 days to prepare +them and the commission takes 45-90 days for the review. Once the +reports are approved remaining funds are sent to the coordinator. + +We may need an audit certificate for each partner in order to get the +refill of the pre-financing. I'm still a bit hazy on that part. + +It is possible to finish the project early and receive outstanding +funds early. You can also ask the commission for a reasonable time +extension if you are lagging. However, this can be refused and you +don't get any more funds in any case. It is also a big administrative +hassle. + +If you have been a very good boy/girl and finished the project on time +and with all goals accomplished, it is possible for the commission to +grant more funds to extend the project. This is extremely rare. + +Since we have partners in the project who have quite limited liquidity +this all means that we need to be quick and accurate in our +reporting. Our aim should be to submit the reports within 10 days of +the end of the reporting period rather than 45. This requires that we +keep our records updated and that we start preparing the reports well +ahead of the deadlines. + +In the report you will have to motivate your costs. For staff, this +means that you need to keep track of time spent on the project and +which WP the work went into. It is even better if you have more detail +than that. If we fail in one goal or another, it may be important to +be able to show what effort went into trying to reach the goal. For +other things you can charge the project for reasonable costs. I +interpret that as saying that you can charge a reasonable amount for +office space, you can buy normal office furniture, normal computer +equipment etc, and charge it to the project. However, you can't rent +huge offices in top locations, buy gold plated furniture or buy +non-relevant computer equipment. Should you want to buy a digital +camera and charge it to the project, you need some very good +motivation for why it is needed. + +In the specific case of travel, regular fares for the normal way of +transportation to the destination is fine. This can sometimes mean +flying business class, as you are normally entitled to spend your +weekends at home according to your national labour laws. When I worked +at the Royal Library they had a policy that allowed me to charge the +project for extra hotel nights if that meant savings on the ticket +price. As long as the total was reduced everyone was happy. For hotel +costs the commission accepts whatever a single room in a middle class +hotel costs. However, most of us spend money that is 50% our own, so +we have a self interest in keeping costs down. + +On the subject of financing people's participation in sprints, if we +assume costs of 1500 - 3000 Euro for attending a sprint, all costs +included, then we can finance beween 30 and 60 sprint-weeks. That +means 2-4 funded sprinters per sprint. Please remember that only +residents of EU countries are qualified. + From hpk at codespeak.net Mon Dec 13 14:12:34 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 13 Dec 2004 14:12:34 +0100 (MET) Subject: [pypy-svn] r7838 - pypy/trunk/doc/funding/negotiations Message-ID: <20041213131234.EB1725A9B4@thoth.codespeak.net> Author: hpk Date: Mon Dec 13 14:12:34 2004 New Revision: 7838 Modified: pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc Log: small update to form-b for merlinux (now dated 1.12.2004 as the date of signature/accession) Modified: pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc ============================================================================== Binary files. No diff available. From alastair at codespeak.net Tue Dec 14 17:54:14 2004 From: alastair at codespeak.net (alastair at codespeak.net) Date: Tue, 14 Dec 2004 17:54:14 +0100 (MET) Subject: [pypy-svn] r7854 - pypy/trunk/doc/funding/negotiations Message-ID: <20041214165414.2E2A35AA09@thoth.codespeak.net> Author: alastair Date: Tue Dec 14 17:54:13 2004 New Revision: 7854 Modified: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw Log: As edited in Kickoff meeting Modified: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw ============================================================================== Binary files. No diff available. From alastair at codespeak.net Tue Dec 14 19:51:03 2004 From: alastair at codespeak.net (alastair at codespeak.net) Date: Tue, 14 Dec 2004 19:51:03 +0100 (MET) Subject: [pypy-svn] r7857 - pypy/trunk/doc/funding/negotiations/amendment Message-ID: <20041214185103.5A4155AA09@thoth.codespeak.net> Author: alastair Date: Tue Dec 14 19:51:00 2004 New Revision: 7857 Added: pypy/trunk/doc/funding/negotiations/amendment/ pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b hhud (blanko).doc (contents, props changed) pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b hhud (dfki).doc (contents, props changed) pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b mer tis (blanko).doc (contents, props changed) pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b mer tis (dfki).doc (contents, props changed) pypy/trunk/doc/funding/negotiations/amendment/contract-form-b-dfki tismer.doc (contents, props changed) Log: Amendment templates Added: pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b hhud (blanko).doc ============================================================================== Binary file. No diff available. Added: pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b hhud (dfki).doc ============================================================================== Binary file. No diff available. Added: pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b mer tis (blanko).doc ============================================================================== Binary file. No diff available. Added: pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b mer tis (dfki).doc ============================================================================== Binary file. No diff available. Added: pypy/trunk/doc/funding/negotiations/amendment/contract-form-b-dfki tismer.doc ============================================================================== Binary file. No diff available. From alastair at codespeak.net Tue Dec 14 19:55:14 2004 From: alastair at codespeak.net (alastair at codespeak.net) Date: Tue, 14 Dec 2004 19:55:14 +0100 (MET) Subject: [pypy-svn] r7858 - pypy/trunk/doc/funding/negotiations Message-ID: <20041214185514.041865AA89@thoth.codespeak.net> Author: alastair Date: Tue Dec 14 19:55:13 2004 New Revision: 7858 Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf Log: Added Tismerysoft and HHUD Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf ============================================================================== --- pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf (original) +++ pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf Tue Dec 14 19:55:13 2004 @@ -551,7 +551,7 @@ PYPY 6 merlinux GmbH - HRB 3565 + HRB 3564 merlinux Gerlandstr. 8 @@ -590,6 +590,96 @@ N + + + 004779 + PYPY + 7 + Tismerysoft GmbH + + TIS + + Johannes-Niemeyer-Weg 9A + 14109 + DE + Berlin + + + IND + N + + + + + + + 27/448/00384 + + + + + 1 + 1 + + 1 + FCF + + PRIV + + + N + + C + software research, developement, integration + N + + N + + + + 004779 + PYPY + 8 + Heinrich Heine Universitaet Duesseldorf + + HHUD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1118,6 +1208,108 @@ + + + 004779 + PYPY + 7 + Tismer + Christian + Mr + M + + + + + + + + + + + Tismerysoft + + + + + + + Tismer + Christian + Mr + F + +491732418776 + + tismer at stackless.com + N + + + + + + + + + + managing director + + managing director + + + + + + + + 004779 + PYPY + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1337,6 +1529,30 @@ Y + + + 004779 + PYPY + 7 + Tismerysoft GmbH + Tismer + + Christian + Y + + + + + 004779 + PYPY + 8 + Heinrich Heine Universitaet Duesseldorf + + + + + + @@ -1519,27 +1735,27 @@ 1 DFKI FC - 608942 - 547610 + 239580.40 + 215450 21795 39200 - 486278 + 191319.60 17405 - 630737 + 261375.40 0 - 503683 - 586810 - 1095220 + 208724.60 + 254650 + 430900 0 39200 - 1134420 + 470100 1 of 1 2237810 1258600 @@ -1558,8 +1774,8 @@ 2 USH AC - 279390 - 279390 + 0 + 0 @@ -1571,14 +1787,14 @@ - 279390 + 0 0 0 - 279390 - 279390 + 0 + 0 0 0 - 279390 + 0 1 of 1 2237810 1258600 @@ -1714,8 +1930,86 @@ 6 merlinux FCF - - + 260736 + 162960 + + + + + + 65184 + + + + + + 260736 + 0 + 65184 + 162960 + 325920 + 0 + 0 + 325920 + 1 of 1 + 2237810 + 1258600 + 0 + 0 + 94400 + 94400 + 0 + 2332210 + 1353000 + + + + 004779 + PYPY + 7 + TIS + FCF + 270720 + 169200 + + + + + + 67680 + + + + + + 270720 + 0 + 67680 + 169200 + 338400 + 0 + 0 + 338400 + 1 of 1 + 2237810 + 1258600 + 0 + 0 + 94400 + 94400 + 0 + 2332210 + 1353000 + + + + 004779 + PYPY + 8 + HHUD + + 279390 + 279390 @@ -1727,14 +2021,14 @@ - 0 + 279390 0 0 - 0 - 0 + 279390 + 279390 0 0 - 0 + 279390 1 of 1 2237810 1258600 @@ -2368,8 +2662,22 @@ 004779 PYPY 6 - - + N + N + N + N + + + + + + + + 004779 + PYPY + 7 + N + N N N @@ -2377,6 +2685,20 @@ + + + 004779 + PYPY + 8 + + + + + + + + + @@ -3254,6 +3576,186 @@ 0 0 + + + 004779 + PYPY + 7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 004779 + PYPY + 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + From alastair at codespeak.net Tue Dec 14 19:59:02 2004 From: alastair at codespeak.net (alastair at codespeak.net) Date: Tue, 14 Dec 2004 19:59:02 +0100 (MET) Subject: [pypy-svn] r7859 - pypy/trunk/doc/funding/negotiations Message-ID: <20041214185902.094375AA89@thoth.codespeak.net> Author: alastair Date: Tue Dec 14 19:59:01 2004 New Revision: 7859 Modified: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw Log: Updates Consortium Agreement Modified: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw ============================================================================== Binary files. No diff available. From hpk at codespeak.net Thu Dec 16 00:32:11 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 16 Dec 2004 00:32:11 +0100 (MET) Subject: [pypy-svn] r7866 - pypy/trunk/doc/funding/negotiations/minutes Message-ID: <20041215233211.CF1F95A628@thoth.codespeak.net> Author: hpk Date: Thu Dec 16 00:32:11 2004 New Revision: 7866 Added: pypy/trunk/doc/funding/negotiations/minutes/ pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf Log: kickoff-meeting minutes from Beatrice sent to me a couple of hours ago ... Added: pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf ============================================================================== --- (empty file) +++ pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf Thu Dec 16 00:32:11 2004 @@ -0,0 +1,209 @@ +{\rtf1\ansi\ansicpg1252\deff0\deflang1053{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial Black;}{\f1\fswiss\fprq2\fcharset0 Arial;}{\f2\fswiss\fcharset0 Arial;}{\f3\fnil\fcharset2 Symbol;}} +{\*\generator Msftedit 5.41.15.1503;}\viewkind4\uc1\pard\f0\fs28 Kick off meeting PyPy, Saarbrucken 041214\par +Minutes of meeting\par +\par +\f1\fs22 Attending:\par +Alastair Burt\tab\tab DFKI\par +Jacob Hall\'e9n\tab\tab AB Strakt\par +Laura Creighton\tab AB Strakt\par +Holger Krekel\tab\tab Merlinux\par +Lene\tab\tab\tab Merlinux\par +Christian Tismer\tab Tismerysoft\par +Armin Rigo\tab\tab Heinrich Heine University D\'fcsseldorf (HHUD)\par +Beatrice D\'fcring\tab Change Maker\par +\tab\tab\tab Logilab\par +\tab\tab\tab Logilab\par +Stefan Buserman\tab DFKI\par +Samuel Pedroni\tab AB Strakt?\par +\par +Agenda:\par +- Intro (Alastair)\par +- Handling the paperwork of adding and changing project partners (Alastair)\par +- Set up routines for time/cost reporting and other project administrative tasks (Alastair)\par +- Building av project calendar - dates for deliverables/budget etc. (Jacob)\par +- Communication: mailinglists and websites (Alastair)\par +- Consortium agreements (Holger)\par +- Roles and responsibilities (Holger)\par +- Procedures of accepting new individual partners (Laura)\par +- Closing \par +\f0\fs28\par +\f1\fs22 1. Intro (Alastair)\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 Short presentation of DFKI by Stefan Buserman.\par +{\pntext\f3\'B7\tab}Agenda walkthrough and acceptance\f0\par +\f2{\pntext\f3\'B7\tab}Chairman: Alistair Burt\par +{\pntext\f3\'B7\tab}Secretary: Beatrice D\'fcring\fs20\par +\pard\par +\fs22\par +2. \f1 Handling the paperwork of adding and changing project partners (Alastair)\par +\tab See meeting notes on wiki/codespeak\par +\par +\tab Consortium members - changes:\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 Out: University of Southampton\par +{\pntext\f3\'B7\tab}In: Heinrich Heine University D\'fcsseldorf (HHUD), Merlinux, Tismerysoft\par +{\pntext\f3\'B7\tab}Natural persons: Laura Creighton, Alex Martelli (postpone until his decision of his consortium participation is made more clear)\par +\pard\par +\tab Main problem: \par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 HHUD wants to see consortium agreement first before they fill out accession forms to join consortium/contract\par +{\pntext\f3\'B7\tab}Calender pressed: everything needs to be signed (accession forms, cpf:s etc - see wiki checklist) and sent to DFKI by 22/12 so this can be sent in before main deadline 30 days after project start - 30/12 2004.\par +{\pntext\f3\'B7\tab}Question to PO: does eveything need to be signed by 30/12 2004 or is it enough to show for example consortium agreement?\par +{\pntext\f3\'B7\tab}PyPyproject need to prepare to worst case send in all papers to meet deadline of 30/12 2004 without HHUD (OK for PO?)\par +{\pntext\f3\'B7\tab}Walkthrough of checklist on wiki for deliverables before 30/12 2004, each partner is responsible to do their utmost to have each respective document signed and sent to DFKI before 22/12 2004\par +{\pntext\f3\'B7\tab}DFKI/Alastair is responsible to call in support if the communication with partners and PO is pressed for time\par +{\pntext\f3\'B7\tab}Goal for the meeting today: finish CPF:s for new partners and have a v.1.0 of consortium agreement\par +\pard\par +3. Set up routines for time/cost reporting and other project administrative tasks (Alastair)\par +\tab Project tracking by:\par +\par +\tab Monthly status reports\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 amount of hours spent on each workpackage + description of acitivities\par +{\pntext\f3\'B7\tab}timesheets\par +{\pntext\f3\'B7\tab}travelcosts\par +{\pntext\f3\'B7\tab}other expenses\par +{\pntext\f3\'B7\tab}deviations from planned activities/reasons for this\par +{\pntext\f3\'B7\tab}templates for this will be circulated, no later than 2005-01-07 by Alastair\par +{\pntext\f3\'B7\tab}every sixth month, amalgameted will be compiled by the monthly reports\par +{\pntext\f3\'B7\tab}the cost statements at the end of the year must coincide with the report (audit certificates will be needed for cost statements)\par +{\pntext\f3\'B7\tab}Question for PO: does all parties have to make 2 audit certificates during he project, 14 in total taken from the management budget?\par +\pard\par +Main reasons for monthly reports is to keep tracking process up to date so that when the big periodic report 1, and period report 2 + final report are due to the Commission, all the paperwork are essentially done. This way the quality of the data is checked ongoing and the project is also able to handle audits from the Commission. Faling to do this (track ongoing) could risk serious delays to payments from Commission.\par +\par +Besides tracking cost and time spent on project, quality have to be checked. Quality need to be assured for the following three aspects of the project:\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 Project process (structure, planning, coordinating, managing, documenting, infrastructure, team etc)\par +{\pntext\f3\'B7\tab}Development process (sprints, pairprogramming, unit-testing etc)\par +{\pntext\f3\'B7\tab}Product (minireviews of deliverables and features of PyPy\par +\pard\par +A quality management plan will be compiled and circulated 22/12-04 for feedback from the team. The plan need to be sent to the Commission no later than 30/12-04. This is a deliverable in the project, assistant project manager Beatrice is responsible for this. Input to this plan is mentioned in the proposal, all ideas that teammewbers have around this - please send to Bea as soon as possible.\par +\par +A question regarding the time of the project coordinator, Alastairs allotted time came up. Will Alastair have allotted time for PyPy? Yes, and also there is a second support person from DFKI, Stefan Buserman. The team clearified the need for the project coordinator to communicate and delegate when time issues might become problems, see december 04 deadlines to the Commission as an urgent need.\par +\par +4. Communication: mailinglists and websites (Alastair)\par +\tab A discussion regarding transparency in the project followed. The team decided to implement total transparency (combined with sense and reason regarding what was being communicated and how) for now regarding project communication both internally and externally (as said in the proposal - "life in a fishbowl". Some effort need to be put in to the issue of readability and information design so that external parties actually can find relevant information within the transparency effort.\par +\par +The team decided that the project needed a website outside of codespeak and the domain pypy.org will be used for this. This sight will hold relevant information on the pypy/EU project and will then send people on to the codespeak/developer site for more specific information. This way the pypy/EU project gets its on "front door", at least in the eyes of external parties.\par +\par +Communication structure the team will need for the pypy/eu project:\par +- an issue tracker for the project deliverables and action items\par +- repositories with a structure of directories for documents (for code as well? Question by Bea)\par +- site with project information\par +\par +Holger will set up this infrastructure , no later than end of january 2005. Until then - use the existing and working infrastructure of codespeak.\par +Alastair raised the importance of getting a site up and running with pypy/EU logo as soon as possible as important.\par +\par +5. Building av project calendar - dates for deliverables/budget etc. (Jacob)\par +\tab See document distributed by Jacob before meeting.\par +\par +\tab Sprints in calendar:\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 Team decided that project manager, Jacob will act as sprint coordinator and be responsible for finding local sprint hosts.\par +{\pntext\f3\'B7\tab}The sprints during spring 2005 are: end january - Leysan Switzterland/end march PyCon Washington/midapril at ACCU conference Oxford/end june Europython Gothenburg.\par +{\pntext\f3\'B7\tab}Question for PO: will EU finance sprintcosts outside the EU?\par +{\pntext\f3\'B7\tab}Idea for sprint end august in South Korea, Holger will check with local community\par +\pard\par +\tab Comments on project calendar:\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 Month always equals end of month\par +{\pntext\f3\'B7\tab}Every deliverable needs to have a paper written on where it is to be found in the repository and in that way point to relevant release of prototype\par +{\pntext\f3\'B7\tab}When the deliverable is a paper, written analysis with written descriptions are needed\par +{\pntext\f3\'B7\tab}This calendar focus on all the external deliverables to the Commission, there are no internal deliverables as mentioned in proposal (project review workshops, quality management acitivities like audits etc, monthly reports, other reaccuring tasks, conferences etc)\par +{\pntext\f3\'B7\tab}The assistant project manager, Bea will create an integrated calendar with both internal and external deliverables\par +{\pntext\f3\'B7\tab}This calender will be updated with a column on who is the reponsible party for each deliverable\par +{\pntext\f3\'B7\tab}Crucial nonevelopment activities in the calender is the periodic report 1 (15 january 2006), periodic report 2 (15 january 2007) and the final report. Work with these needs to be driven over 3 months beforehand to make sure that these deliverables are handed in a qualitative and orderly manner (project manager and assistant project manager are responsible for this)\par +\pard\par +\par +6. Discussions/orientation of ongoing pypywork with pypyproject (Armin)\par +\tab Armin made a short high level summary of the status of PyPy today.\par +\par +\tab A discussion regarding the difference between PyPy and the PyPy/Strep project followed. There are issues here to be handled. \par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 The rest of the developer base might feel excluded because their not in the funding project and that maight impair their motivation in the PyPy community\par +{\pntext\f3\'B7\tab}There is a "management of expectations" to be made so that wishes from the community of developers to start to work on certain features of PyPy doesnt get hindered because of the projecr calender to the EU etc.\par +{\pntext\f3\'B7\tab}There is a need to be able to communicate a clear picture of relationship between funded project and the PypY developer community so that it will be easy for external stakeholders (noncommunity companies and organisations) to understand the scope of the project. And in doing this not trample on the community. The project needs an outspoken and decided strategy around this.\par +\pard\par +\tab No decisions were made by the team - the question needs to be discussed further, via email?\par +\par +/Lunchbreak/\par +\par +7. Consortium agreement (Holger)\par +\par +\tab The team created a v. 1.0 of the consortium agreement from the model contract that all parties present clearly stated that they would sign.\par +\tab Here is a summary of changes made in the model contract, v.1.0 is in the repository under negotiations/pypy consortium agreement.swx:\par +\tab (Comments in italics are unsolved issues)\par +\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720\i Page 2 References needs to be adjusted with correct data and filenames/dates\par +{\pntext\f3\'B7\tab}Table of contents needs to be adjusted, se text inserted under section 10 in table of contents\i0\par +{\pntext\f3\'B7\tab}Introduction - page 4 was changed from the model contract \par +{\pntext\f3\'B7\tab}Section 1 Definitions, 1.1 Additional definitions: Project Management Board were inserted, page 7\par +\i{\pntext\f3\'B7\tab}Section 1 Definitions, 1.3 Further understandings: discussions about deleting (b) "fair and...."/no decision was made\i0\par +{\pntext\f3\'B7\tab}Section 3 Project Organisation and management structure, 3.1 General structure (a): Project management board was added\par +{\pntext\f3\'B7\tab}Section 4 Responsibilities and authority: changes were made to\par +\pard\tab\tab 5.1 Establishment of the work plan\par +\tab\tab 5.2 Project Co-ordination Committe\par +\tab\tab 5.2.1 Responsibilities of the Project mangement board\par +\tab\tab 5.2.2 Decisions of the Project Co-ordination Committe\par +\tab\tab 5.2.4 Meetings of the Project Co-ordination Committe\par +\tab\tab 5.2.5 Kick off\par +\tab\tab 5.3 Co-ordinator\par +\tab\tab 5.3.2 Responsibilities of the Co-ordinator\par +\tab\par +\tab\i Check 5.2.1 (d): content of Annex II 34\i0\par +\tab\tab\par +\tab Explanation of changes in section 5: changes were made to integrate the project management board with the model contracts version of Project \tab Co-ordination Committe, electronic meeting were inserted, kick off meeting date changed to comply with actual fact etc.\par +\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 Section 6: Costs-Payments, 6.2 Payments: option was inserted and individual party/instalments was inserted\par +{\pntext\f3\'B7\tab}Section 10, Copyrights, trademarks, Trade secrets and patents: changes were made to:\par +\pard\tab\tab 10.1: MIT license inserted\par +\tab\tab 10.3 Contributions are not to be patent encumbered: during duration of project/section about trade secrets were deleted\par +\tab\par +\tab\i Check 10.2 Patents - what about USA - is this a risk?\par +\tab Change Section 10 headline; it has trade secrets in it although that was deleted?\i0\par +\par +\pard{\pntext\f3\'B7\tab}{\*\pn\pnlvlblt\pnf3\pnindent0{\pntxtb\'B7}}\fi-720\li720 Section 12: Publications, press releases, 12.2 Communication and procedure: restriction was added, second sentence\par +{\pntext\f3\'B7\tab}Section 18: Notices: no adresses inserted - instead responsiblities of keeping contact and banking data up to date was inserted\par +{\pntext\f3\'B7\tab}Annex A,B,C was deleted\par +\pard\par +\par +Meeting split up in working groups: one group worked on consortium agreement, one group worked on accession forms and cpf:s for Merlinux and Tismerysoft. A walkthrough was made by the entire team of version 1 of the consortium agreement before meeting ended.\par +\par +Meeting ended with following conclusions:\par +- Part of the agenda was not discussed: budget, roles and responsibilities, natural persons (contract handling, criteria, selection, decision)\par +- An IRC meeting was scheduled for friday 17/12-04 to follow up on december deadlines and action items, mainly paperwork to the Commission due 30/12-04. Meeting starts 15:00.\par +\par +An action list was compiled at the end of meeting and the team decided upon the following list of action items:\par +\par +1. Question PO about CPF/Consortium agreement: do they need to be signed 30/12-04? By all parties or can one sedn in after christmas? (Alastair)\par +2. Check DoW, every party checks their workpackages and descriptions before monday 20/12 (All)\par +3. Create monthly report december in january (Beatrice, Jacob)\par +4. Create template for time/cost reporting , no later than 2005-01-07 (Alastair)\par +5. Question PO about all parties needing to have 2 audit certificates during project period/from management budget? (Alastair)\par +6. Create Quality Management Plan, circulate example to all parties 22/12-04, to the Commission before 30/12-04 (Beatrice)\par +7. Create communication structure/infrastructure accortdin to minutes 041214 for pypy/EU, no later than end of january (Holger)\par +8. Check sprint planning (Jacop, Holger)\par +9. Update project calender with responsibilities (Jacob)\par +10. Create integrated calendar (Beatrice)\par +11. Discuss communication strategy pypy/pypy_eu via email/IRC (Beatrice)\par +12. Check version 1.0 of consortium agreement (in repository) (All)\par +13. Perform all december tasks on wiki "checklist" on kick off meeting agenda (signing paperwork for Commission deadline 30/12-04) (Alastair/all)\par +14. Correct v. 1.0 of consortium agreement (se minutes above, comments in italics) (Alastair)\par +15. Send out consortium agreement after corrections with clear deadline/timeline for all parties (Alastair)\par +16. Discuss and check management budget (meetings selffinanced for all that doesnt report to those wp:s and audit certificates, PO?) (Alastair)\par +17. Specify which other documents need to be signed by whom, when and sent where to meet commission deadline 30/12-04 (Alastair)\par +18. Write justification for partner switch and sign to accession forms (Alastair)\par +19. Check changed CPF budget before signed/sent to commission (Jacob)\par +20. Question PO about problem with consortium structure and natural persons (swinging door, junior partners etc) (Alastair)\par +21. Fill in all paper for Laura to enter consortium as natural person, coordinate changes with Alastair (Laura)\par +\par +\par +\par +\par +\par +\par +\par +\par +\par +\par +\par +\par +\par + \par +\par +\par +\f2\fs20\par +} + \ No newline at end of file From tismer at codespeak.net Thu Dec 16 00:53:07 2004 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 16 Dec 2004 00:53:07 +0100 (MET) Subject: [pypy-svn] r7867 - pypy/trunk/doc/funding/negotiations/amendment Message-ID: <20041215235307.2539C5ACB8@thoth.codespeak.net> Author: tismer Date: Thu Dec 16 00:53:06 2004 New Revision: 7867 Added: pypy/trunk/doc/funding/negotiations/amendment/contract-form_b_-dfki merlinux.doc (contents, props changed) Log: moved merlinux amendment to amendmentHinzugef?gt contract-form_b_-dfki merlinux.doc Gel?scht form_b_-merlinux.doc Added: pypy/trunk/doc/funding/negotiations/amendment/contract-form_b_-dfki merlinux.doc ============================================================================== Binary file. No diff available. From tismer at codespeak.net Thu Dec 16 00:54:53 2004 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 16 Dec 2004 00:54:53 +0100 (MET) Subject: [pypy-svn] r7868 - pypy/trunk/doc/funding/negotiations/amendment Message-ID: <20041215235453.A083C5AF25@thoth.codespeak.net> Author: tismer Date: Thu Dec 16 00:54:53 2004 New Revision: 7868 Added: pypy/trunk/doc/funding/negotiations/amendment/contract-form-b-dfki merlinux.doc - copied unchanged from r7867, pypy/trunk/doc/funding/negotiations/amendment/contract-form_b_-dfki merlinux.doc Removed: pypy/trunk/doc/funding/negotiations/amendment/contract-form_b_-dfki merlinux.doc Log: moved merlinux amendment to amendment Deleted: /pypy/trunk/doc/funding/negotiations/amendment/contract-form_b_-dfki merlinux.doc ============================================================================== Binary file. No diff available. From tismer at codespeak.net Thu Dec 16 01:20:22 2004 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 16 Dec 2004 01:20:22 +0100 (MET) Subject: [pypy-svn] r7869 - pypy/trunk/doc/funding/negotiations Message-ID: <20041216002022.E56065B1AA@thoth.codespeak.net> Author: tismer Date: Thu Dec 16 01:20:22 2004 New Revision: 7869 Removed: pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc Log: rest 0of renaming Deleted: /pypy/trunk/doc/funding/negotiations/form_b_-merlinux.doc ============================================================================== Binary file. No diff available. From hpk at codespeak.net Thu Dec 16 11:22:05 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 16 Dec 2004 11:22:05 +0100 (MET) Subject: [pypy-svn] r7876 - pypy/branch/src-pytest Message-ID: <20041216102205.716955B209@thoth.codespeak.net> Author: hpk Date: Thu Dec 16 11:22:04 2004 New Revision: 7876 Added: pypy/branch/src-pytest/ - copied from r7875, pypy/trunk/src/ Log: a branch to begin porting the pypy tests to pytest ... From pedronis at codespeak.net Thu Dec 16 15:14:48 2004 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Dec 2004 15:14:48 +0100 (MET) Subject: [pypy-svn] r7882 - pypy/trunk/doc/funding/negotiations/minutes Message-ID: <20041216141448.24FFD5AB2F@thoth.codespeak.net> Author: pedronis Date: Thu Dec 16 15:14:47 2004 New Revision: 7882 Modified: pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf Log: edit list of participants Modified: pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf ============================================================================== --- pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf (original) +++ pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf Thu Dec 16 15:14:47 2004 @@ -1,5 +1,5 @@ {\rtf1\ansi\ansicpg1252\deff0\deflang1053{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial Black;}{\f1\fswiss\fprq2\fcharset0 Arial;}{\f2\fswiss\fcharset0 Arial;}{\f3\fnil\fcharset2 Symbol;}} -{\*\generator Msftedit 5.41.15.1503;}\viewkind4\uc1\pard\f0\fs28 Kick off meeting PyPy, Saarbrucken 041214\par +\viewkind4\uc1\pard\f0\fs28 Kick off meeting PyPy, Saarbrucken 041214\par Minutes of meeting\par \par \f1\fs22 Attending:\par @@ -7,14 +7,14 @@ Jacob Hall\'e9n\tab\tab AB Strakt\par Laura Creighton\tab AB Strakt\par Holger Krekel\tab\tab Merlinux\par -Lene\tab\tab\tab Merlinux\par +Lene Wagner\tab\tab Merlinux\par Christian Tismer\tab Tismerysoft\par Armin Rigo\tab\tab Heinrich Heine University D\'fcsseldorf (HHUD)\par Beatrice D\'fcring\tab Change Maker\par -\tab\tab\tab Logilab\par -\tab\tab\tab Logilab\par -Stefan Buserman\tab DFKI\par -Samuel Pedroni\tab AB Strakt?\par +Adrien Di Mascio \tab Logilab\par +Ludovic Aubry \tab\tab Logilab\par +Stephan Buserman\tab DFKI\par +Samuele Pedroni\tab AB Strakt\par \par Agenda:\par - Intro (Alastair)\par From pedronis at codespeak.net Thu Dec 16 15:18:07 2004 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Dec 2004 15:18:07 +0100 (MET) Subject: [pypy-svn] r7883 - pypy/trunk/doc/funding/negotiations/minutes Message-ID: <20041216141807.2E8F95AB2F@thoth.codespeak.net> Author: pedronis Date: Thu Dec 16 15:18:06 2004 New Revision: 7883 Modified: pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf Log: last fix to list of partecipants Modified: pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf ============================================================================== --- pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf (original) +++ pypy/trunk/doc/funding/negotiations/minutes/kickoffpypy_041214bd.rtf Thu Dec 16 15:18:06 2004 @@ -13,7 +13,7 @@ Beatrice D\'fcring\tab Change Maker\par Adrien Di Mascio \tab Logilab\par Ludovic Aubry \tab\tab Logilab\par -Stephan Buserman\tab DFKI\par +Stephan Busemann\tab DFKI\par Samuele Pedroni\tab AB Strakt\par \par Agenda:\par From arigo at codespeak.net Thu Dec 16 15:20:45 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Dec 2004 15:20:45 +0100 (MET) Subject: [pypy-svn] r7884 - in pypy/trunk/src/pypy/translator: . test Message-ID: <20041216142045.B90225AB2F@thoth.codespeak.net> Author: arigo Date: Thu Dec 16 15:20:45 2004 New Revision: 7884 Modified: pypy/trunk/src/pypy/translator/genc.h pypy/trunk/src/pypy/translator/genc.py pypy/trunk/src/pypy/translator/test/test_ctrans.py Log: - supports keyword arguments in the functions created by genc.py. - some clean-up of a workaround for a C preprocessor limitation. Modified: pypy/trunk/src/pypy/translator/genc.h ============================================================================== --- pypy/trunk/src/pypy/translator/genc.h (original) +++ pypy/trunk/src/pypy/translator/genc.h Thu Dec 16 15:20:45 2004 @@ -199,6 +199,11 @@ #if defined(USE_CALL_TRACE) +#define TRACE_CALL __f, __tstate, +#define TRACE_ARGS PyFrameObject *__f, PyThreadState *__tstate, +#define TRACE_CALL_VOID __f, __tstate +#define TRACE_ARGS_VOID PyFrameObject *__f, PyThreadState *__tstate + #define FAIL(err) { __f->f_lineno = __f->f_code->co_firstlineno = __LINE__; goto err; } #define FUNCTION_HEAD(signature, self, args, names, file, line) \ @@ -215,6 +220,11 @@ #else /* !defined(USE_CALL_TRACE) */ +#define TRACE_CALL /* nothing */ +#define TRACE_ARGS /* nothing */ +#define TRACE_CALL_VOID /* nothing */ +#define TRACE_ARGS_VOID void + #define FAIL(err) { goto err; } #define FUNCTION_HEAD(signature, self, args, names, file, line) Modified: pypy/trunk/src/pypy/translator/genc.py ============================================================================== --- pypy/trunk/src/pypy/translator/genc.py (original) +++ pypy/trunk/src/pypy/translator/genc.py Thu Dec 16 15:20:45 2004 @@ -38,8 +38,6 @@ class GenC: MODNAMES = {} - # XXX - I don't know how to make a macro do this.. so.. - USE_CALL_TRACE = True def __init__(self, f, translator, modname=None, f2=None, f2name=None): self.f = f @@ -454,8 +452,6 @@ 'entrypoint': self.nameof(self.translator.functions[0]), } # header - if self.USE_CALL_TRACE: - print >> f, '#define USE_CALL_TRACE' print >> f, self.C_HEADER # function implementations @@ -510,9 +506,9 @@ self.gen_global_declarations() # print header - name = self.nameof(func) - assert name.startswith('gfunc_') - f_name = 'f_' + name[6:] + cname = self.nameof(func) + assert cname.startswith('gfunc_') + f_name = 'f_' + cname[6:] # collect all the local variables graph = self.translator.getflowgraph(func) @@ -540,22 +536,31 @@ fast_set = dict(zip(fast_args, fast_args)) declare_fast_args = [('PyObject *' + a) for a in fast_args] - if self.USE_CALL_TRACE: - declare_fast_args[:0] = ['PyFrameObject *__f', 'PyThreadState *__tstate'] + if declare_fast_args: + declare_fast_args = 'TRACE_ARGS ' + ', '.join(declare_fast_args) + else: + declare_fast_args = 'TRACE_ARGS_VOID' + fast_function_header = ('static PyObject *\n' + '%s(%s)' % (fast_name, declare_fast_args)) - print >> f, 'static PyObject *' - print >> f, '%s(%s);' % (fast_name, ', '.join(declare_fast_args)) + print >> f, fast_function_header + ';' # forward print >> f print >> f, 'static PyObject *' - print >> f, '%s(PyObject* self, PyObject* args)' % (f_name,) + print >> f, '%s(PyObject* self, PyObject* args, PyObject* kwds)' % ( + f_name,) print >> f, '{' print >> f, '\tFUNCTION_HEAD(%s, %s, args, %s, __FILE__, __LINE__ - 2)' % ( - c_string('%s(%s)' % (name, ', '.join(name_of_defaults))), - name, + c_string('%s(%s)' % (cname, ', '.join(name_of_defaults))), + cname, '(%s)' % (', '.join(map(c_string, name_of_defaults) + ['NULL']),), ) + kwlist = ['"%s"' % name for name in + func.func_code.co_varnames[:func.func_code.co_argcount]] + kwlist.append('0') + print >> f, '\tstatic char* kwlist[] = {%s};' % (', '.join(kwlist),) + if fast_args: print >> f, '\tPyObject *%s;' % (', *'.join(fast_args)) print >> f @@ -586,24 +591,27 @@ print >> f, '\t%s = %s;' % ( positional_args[min_number_of_args+i], name_of_defaults[i]) - lst = ['args', - '"%s"' % func.__name__, - '%d' % min_number_of_args, - '%d' % len(positional_args), + fmt = 'O'*min_number_of_args + if min_number_of_args < len(positional_args): + fmt += '|' + 'O'*(len(positional_args)-min_number_of_args) + lst = ['args', 'kwds', + '"%s:%s"' % (fmt, func.__name__), + 'kwlist', ] lst += ['&' + a.name for a in positional_args] - print >> f, '\tif (!PyArg_UnpackTuple(%s))' % ', '.join(lst), + print >> f, '\tif (!PyArg_ParseTupleAndKeywords(%s))' % ', '.join(lst), print >> f, tail call_fast_args = list(fast_args) - if self.USE_CALL_TRACE: - call_fast_args[:0] = ['__f', '__tstate'] - print >> f, '\treturn %s(%s);' % (fast_name, ', '.join(call_fast_args)) + if call_fast_args: + call_fast_args = 'TRACE_CALL ' + ', '.join(call_fast_args) + else: + call_fast_args = 'TRACE_CALL_VOID' + print >> f, '\treturn %s(%s);' % (fast_name, call_fast_args) print >> f, '}' print >> f - print >> f, 'static PyObject *' - print >> f, '%s(%s)' % (fast_name, ', '.join(declare_fast_args)) + print >> f, fast_function_header print >> f, '{' fast_locals = [arg for arg in localnames if arg not in fast_set] @@ -630,8 +638,9 @@ print >> f, '}' # print the PyMethodDef - print >> f, 'static PyMethodDef ml_%s = { "%s", %s, METH_VARARGS };' % ( - name, func.__name__, f_name) + print >> f, ('static PyMethodDef ml_%s = {\n' + ' "%s", (PyCFunction)%s, METH_VARARGS|METH_KEYWORDS };' % ( + cname, func.__name__, f_name)) print >> f if not self.translator.frozen: Modified: pypy/trunk/src/pypy/translator/test/test_ctrans.py ============================================================================== --- pypy/trunk/src/pypy/translator/test/test_ctrans.py (original) +++ pypy/trunk/src/pypy/translator/test/test_ctrans.py Thu Dec 16 15:20:45 2004 @@ -152,7 +152,7 @@ self.assertRaises(TypeError, call_with_star, [4,7,12,63]) self.assertRaises(TypeError, call_with_star, 521) - def XXX_test_call_with_keyword(self): + def test_call_with_keyword(self): call_with_keyword = self.build_cfunc(snippet.call_with_keyword) self.assertEquals(call_with_keyword(100), 82) From arigo at codespeak.net Thu Dec 16 18:05:44 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Dec 2004 18:05:44 +0100 (MET) Subject: [pypy-svn] r7891 - pypy/trunk/src/pypy/tool Message-ID: <20041216170544.66F325B1AA@thoth.codespeak.net> Author: arigo Date: Thu Dec 16 18:05:43 2004 New Revision: 7891 Modified: pypy/trunk/src/pypy/tool/hack.py Log: buggy! Modified: pypy/trunk/src/pypy/tool/hack.py ============================================================================== --- pypy/trunk/src/pypy/tool/hack.py (original) +++ pypy/trunk/src/pypy/tool/hack.py Thu Dec 16 18:05:43 2004 @@ -2,7 +2,7 @@ import new, sys -if sys.version_info > (2, 2): +if sys.version_info >= (2, 3): def func_with_new_name(func, newname): f = new.function(func.func_code, func.func_globals, From hpk at codespeak.net Thu Dec 16 18:54:17 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 16 Dec 2004 18:54:17 +0100 (MET) Subject: [pypy-svn] r7892 - in pypy/branch/src-pytest/pypy: . interpreter/test Message-ID: <20041216175417.EAADA5B1AA@thoth.codespeak.net> Author: hpk Date: Thu Dec 16 18:54:16 2004 New Revision: 7892 Added: pypy/branch/src-pytest/pypy/conftest.py Modified: pypy/branch/src-pytest/pypy/interpreter/test/test_class.py pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py Log: a first experiment with itnerpreter/test_interpreter integrated into py.test (it works) Added: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- (empty file) +++ pypy/branch/src-pytest/pypy/conftest.py Thu Dec 16 18:54:16 2004 @@ -0,0 +1,37 @@ +import py +from pypy.interpreter.gateway import app2interp_temp +from pypy.objspace.std import StdObjSpace +#def getoptions(): +# return [....] +# +space = StdObjSpace() + +class IntTestMethod(py.test.Item): + def run(self, driver): + cls = self.extpy.resolve().im_class + cls.space = space + return super(IntTestMethod, self).run(driver) + +class AppTestMethod(py.test.Item): + def execute(self, target, *args): + func = app2interp_temp(target.im_func, target.__name__) + func(space, space.w_None) + +class AppClassCollector(py.test.collect.Class): + Item = AppTestMethod + +class IntClassCollector(py.test.collect.Class): + Item = IntTestMethod + +class Module(py.test.collect.Module): + def collect_class(self, extpy): + if extpy.check(class_=1, basestarts="Test"): + yield IntClassCollector(extpy) + def collect_appclass(self, extpy): + if extpy.check(class_=1, basestarts="AppTest"): + yield AppClassCollector(extpy) + + + + + Modified: pypy/branch/src-pytest/pypy/interpreter/test/test_class.py ============================================================================== --- pypy/branch/src-pytest/pypy/interpreter/test/test_class.py (original) +++ pypy/branch/src-pytest/pypy/interpreter/test/test_class.py Thu Dec 16 18:54:16 2004 @@ -2,9 +2,10 @@ from pypy.tool import testit -class TestClassApp(testit.AppTestCase): - +class AppTestClass: + def test_class(self): + self.test_metaclass_explicit() class C: pass self.assertEquals(C.__class__, type) Modified: pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py Thu Dec 16 18:54:16 2004 @@ -1,9 +1,7 @@ import autopath import textwrap -from pypy.tool import testit - -class TestInterpreter(testit.TestCase): +class TestInterpreter: def codetest(self, source, functionname, args): """Compile and run the given code string, and then call its function named by 'functionname' with arguments 'args'.""" @@ -34,8 +32,11 @@ else: return space.unwrap(w_output) - def setUp(self): - self.space = testit.objspace() + #def setup_class(cls): + # cls.space = testit.objspace() + + #def teardown_class(cls): + # del cls.space def test_exception_trivial(self): x = self.codetest(''' @@ -46,7 +47,7 @@ return 1 return 2 ''', 'f', []) - self.assertEquals(x, 1) + assert x == 1 def test_exception(self): x = self.codetest(''' @@ -56,7 +57,7 @@ except Exception, e: return e.args[0] ''', 'f', []) - self.assertEquals(x, 1) + assert x == 1 def test_finally(self): code = ''' @@ -68,8 +69,8 @@ finally: return a ''' - self.assertEquals(self.codetest(code, 'f', [0]), -12) - self.assertEquals(self.codetest(code, 'f', [1]), 1) + assert self.codetest(code, 'f', [0]) == -12 + assert self.codetest(code, 'f', [1]) == 1 ## def test_raise(self): ## x = self.codetest(''' @@ -91,7 +92,7 @@ except TypeError: return z ''', 'f', []) - self.assertEquals(x, 5) + assert x == 5 def test_except3(self): code = ''' @@ -103,11 +104,11 @@ z = "infinite result" return z ''' - self.assertEquals(self.codetest(code, 'f', [2]), 0) - self.assertEquals(self.codetest(code, 'f', [0]), "infinite result") + assert self.codetest(code, 'f', [2]) == 0 + assert self.codetest(code, 'f', [0]) == "infinite result" ess = "TypeError: unsupported operand type" res = self.codetest(code, 'f', ['x']) - self.failUnless(res.find(ess) >= 0) + assert res.find(ess) >= 0 # the following (original) test was a bit too strict...: # self.assertEquals(self.codetest(code, 'f', ['x']), "<<>>") @@ -123,8 +124,8 @@ total += i return total ''' - self.assertEquals(self.codetest(code, 'f', [4]), 1+2+3) - self.assertEquals(self.codetest(code, 'f', [9]), 1+2+3+4) + assert self.codetest(code, 'f', [4]) == 1+2+3 + assert self.codetest(code, 'f', [9]) == 1+2+3+4 def test_continue(self): code = ''' @@ -139,8 +140,8 @@ total += i return total ''' - self.assertEquals(self.codetest(code, 'f', [4]), 1+2+3+400) - self.assertEquals(self.codetest(code, 'f', [9]), + assert self.codetest(code, 'f', [4]) == 1+2+3+400 + assert self.codetest(code, 'f', [9]) == ( 1+2+3 + 5+6+7+8+900) def test_import(self): @@ -178,7 +179,7 @@ x -= 1 # EXTENDED_ARG is for the JUMP_ABSOLUTE at the end of the loop return x ''' % ((longexpr,)*10) - self.assertEquals(self.codetest(code, 'f', [3]), 0) + assert self.codetest(code, 'f', [3]) == 0 def test_call_star_starstar(self): code = ''' @@ -209,7 +210,7 @@ ] return r ''' - self.assertEquals(self.codetest(code, 'f38', [117]), [234]*19) + assert self.codetest(code, 'f38', [117]) == [234]*19 def test_star_arg(self): code = textwrap.dedent(''' @@ -218,25 +219,25 @@ def g(u, v): return f(u, *v) ''') - self.assertEquals(self.codetest(code, 'g', [12, ()]), ()) - self.assertEquals(self.codetest(code, 'g', [12, (3,4)]), (3,4)) - self.assertEquals(self.codetest(code, 'g', [12, []]), ()) - self.assertEquals(self.codetest(code, 'g', [12, [3,4]]), (3,4)) - self.assertEquals(self.codetest(code, 'g', [12, {}]), ()) - self.assertEquals(self.codetest(code, 'g', [12, {3:1}]), (3,)) + assert self.codetest(code, 'g', [12, ()]) == () + assert self.codetest(code, 'g', [12, (3,4)]) == (3,4) + assert self.codetest(code, 'g', [12, []]) == () + assert self.codetest(code, 'g', [12, [3,4]]) == (3,4) + assert self.codetest(code, 'g', [12, {}]) == () + assert self.codetest(code, 'g', [12, {3:1}]) == (3,) -class AppTestInterpreter(testit.AppTestCase): +class AppTestInterpreter: def test_trivial(self): x = 42 - self.assertEquals(x, 42) + assert x == 42 def test_trivial_call(self): def f(): return 42 - self.assertEquals(f(), 42) + assert f() == 42 def test_trivial_call2(self): def f(): return 1 + 1 - self.assertEquals(f(), 2) + assert f() == 2 def test_print(self): import sys @@ -250,14 +251,10 @@ try: sys.stdout = out print 10 - self.assertEquals(out.args, ['10','\n']) + assert out.args == ['10','\n'] finally: sys.stdout = save def test_identity(self): def f(x): return x - self.assertEquals(f(666), 666) - - -if __name__ == '__main__': - testit.main() + assert f(666) == 666 From arigo at codespeak.net Fri Dec 17 10:18:03 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Dec 2004 10:18:03 +0100 (MET) Subject: [pypy-svn] r7896 - in pypy/trunk/src/pypy/translator/java: . test Message-ID: <20041217091803.6FCB45B187@thoth.codespeak.net> Author: arigo Date: Fri Dec 17 10:18:02 2004 New Revision: 7896 Added: pypy/trunk/src/pypy/translator/java/ (props changed) pypy/trunk/src/pypy/translator/java/PyBool.java (contents, props changed) pypy/trunk/src/pypy/translator/java/PyInt.java (contents, props changed) pypy/trunk/src/pypy/translator/java/PyList.java (contents, props changed) pypy/trunk/src/pypy/translator/java/PyObject.java (contents, props changed) pypy/trunk/src/pypy/translator/java/PySequence.java (contents, props changed) pypy/trunk/src/pypy/translator/java/PyTuple.java (contents, props changed) pypy/trunk/src/pypy/translator/java/TypeError.java (contents, props changed) pypy/trunk/src/pypy/translator/java/__init__.py - copied unchanged from r7804, pypy/trunk/src/pypy/translator/__init__.py pypy/trunk/src/pypy/translator/java/autopath.py - copied unchanged from r7804, pypy/trunk/src/pypy/translator/autopath.py pypy/trunk/src/pypy/translator/java/genjava.py - copied, changed from r7804, pypy/trunk/src/pypy/translator/genrpy.py pypy/trunk/src/pypy/translator/java/test/ (props changed) pypy/trunk/src/pypy/translator/java/test/autopath.py - copied unchanged from r7804, pypy/trunk/src/pypy/translator/autopath.py pypy/trunk/src/pypy/translator/java/test/test_javatrans.py (contents, props changed) Log: Another possible direction: generating Java code. The advantage of this would be that the R-Python semantics can very easily be described as a few Java classes "PyXxx". Added: pypy/trunk/src/pypy/translator/java/PyBool.java ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/java/PyBool.java Fri Dec 17 10:18:02 2004 @@ -0,0 +1,9 @@ + + +class PyBool extends PyInt { + + PyBool(boolean x) { + super(x ? 1 : 0); + } + +}; Added: pypy/trunk/src/pypy/translator/java/PyInt.java ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/java/PyInt.java Fri Dec 17 10:18:02 2004 @@ -0,0 +1,47 @@ + + +class PyInt extends PyObject { + + int intval; + + PyInt(int x) { + intval = x; + } + + boolean is_true() { + return intval != 0; + } + + boolean eq(PyObject other) { + if (other instanceof PyInt) + return intval == ((PyInt) other).intval; + else + return false; + } + + boolean lt(PyObject other) { + if (other instanceof PyInt) + return intval < ((PyInt) other).intval; + else + throw new TypeError(); + } + + PyObject op_neg() { + return new PyInt(-intval); + } + + PyObject op_add(PyObject other) { + if (other instanceof PyInt) + return new PyInt(intval + ((PyInt) other).intval); + else + throw new TypeError(); + } + + PyObject op_sub(PyObject other) { + if (other instanceof PyInt) + return new PyInt(intval - ((PyInt) other).intval); + else + throw new TypeError(); + } + +}; Added: pypy/trunk/src/pypy/translator/java/PyList.java ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/java/PyList.java Fri Dec 17 10:18:02 2004 @@ -0,0 +1,74 @@ + + +class PyList extends PySequence { + + PyList(PyObject[] x) { + super(x); + } + + PyObject op_setitem(PyObject index, PyObject o) { + if (index instanceof PyInt) { + int i = ((PyInt) index).intval; + items[i] = o; + return null; + } + throw new TypeError(); + } + + PyObject op_add(PyObject other) { + if (other instanceof PyList) { + PyObject[] items2 = ((PyList) other).items; + PyObject[] nitems = new PyObject[items.length + items2.length]; + System.arraycopy(items, 0, nitems, 0, items.length); + System.arraycopy(items2, 0, nitems, items.length, items2.length); + return new PyList(nitems); + } + throw new TypeError(); + } + + PyObject op_inplace_add(PyObject other) { + if (other instanceof PySequence) { + PyObject[] items2 = ((PySequence) other).items; + PyObject[] nitems = new PyObject[items.length + items2.length]; + System.arraycopy(items, 0, nitems, 0, items.length); + System.arraycopy(items2, 0, nitems, items.length, items2.length); + items = nitems; + return this; + } + throw new TypeError(); + } + + PyObject op_mul(PyObject other) { + if (items.length == 1 && other instanceof PyInt) { + int i, count = ((PyInt) other).intval; + PyObject item = items[0]; + PyObject[] nitems = new PyObject[count]; + for (i=0; i defaults.length) { + throw new TypeError(); + } + PyObject[] result = new PyObject[expected_length]; + System.arraycopy(items, 0, result, 0, items.length); + System.arraycopy(defaults, defaults.length-missing, + result, items.length, missing); + return result; + } + +}; Added: pypy/trunk/src/pypy/translator/java/PyTuple.java ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/java/PyTuple.java Fri Dec 17 10:18:02 2004 @@ -0,0 +1,20 @@ + + +class PyTuple extends PySequence { + + PyTuple(PyObject[] x) { + super(x); + } + + PyObject op_add(PyObject other) { + if (other instanceof PyTuple) { + PyObject[] items2 = ((PyTuple) other).items; + PyObject[] nitems = new PyObject[items.length + items2.length]; + System.arraycopy(items, 0, nitems, 0, items.length); + System.arraycopy(items2, 0, nitems, items.length, items2.length); + return new PyTuple(nitems); + } + throw new TypeError(); + } + +}; Added: pypy/trunk/src/pypy/translator/java/TypeError.java ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/java/TypeError.java Fri Dec 17 10:18:02 2004 @@ -0,0 +1,5 @@ + + +class TypeError extends RuntimeException { + +}; Copied: pypy/trunk/src/pypy/translator/java/genjava.py (from r7804, pypy/trunk/src/pypy/translator/genrpy.py) ============================================================================== --- pypy/trunk/src/pypy/translator/genrpy.py (original) +++ pypy/trunk/src/pypy/translator/java/genjava.py Fri Dec 17 10:18:02 2004 @@ -1,83 +1,19 @@ """ -Implementation of a translator from application Python to interpreter level RPython. +Generate a Java source file from the flowmodel. -The idea is that we can automatically transform app-space implementations -of methods into some equivalent representation at interpreter level. -Then, the RPython to C translation might hopefully spit out some -more efficient code than always interpreting these methods. - -Note that the appspace functions are treated as rpythonic, in a sense -that globals are constants, for instance. This definition is not -exact and might change. - -This module is very much under construction and not yet usable for much -more than testing. """ +import sys, os from pypy.objspace.flow.model import traverse from pypy.objspace.flow import FlowObjSpace from pypy.objspace.flow.model import FunctionGraph, Block, Link, Variable, Constant -from pypy.objspace.flow.model import last_exception, last_exc_value -from pypy.translator.simplify import simplify_graph +from pypy.objspace.flow.model import last_exception, last_exc_value, checkgraph +from pypy.translator.simplify import remove_direct_loops from pypy.interpreter.error import OperationError from types import FunctionType from pypy.translator.translator import Translator -import sys - -def somefunc(arg): - pass - -def f(a,b): - print "start" - a = [] - a.append(3) - for i in range(3): - print i - if a > b: - try: - if b == 123: - raise ValueError - elif b == 321: - raise IndexError - return 123 - except ValueError: - raise TypeError - else: - dummy = somefunc(23) - return 42 - -def ff(a, b): - try: - raise SystemError, 42 - return a+b - finally: - a = 7 - -glob = 100 -def fff(): - global glob - return 42+glob - -def app_mod__String_ANY(format, values): - import _formatting - if isinstance(values, tuple): - return _formatting.format(format, values, None) - else: - if hasattr(values, 'keys'): - return _formatting.format(format, (values,), values) - else: - return _formatting.format(format, (values,), None) - -def app_str_decode__String_ANY_ANY(str, encoding=None, errors=None): - if encoding is None and errors is None: - return unicode(str) - elif errors is None: - return unicode(str, encoding) - else: - return unicode(str, encoding, errors) - def ordered_blocks(graph): # collect all blocks @@ -102,16 +38,16 @@ return [block for ofs, txt, block in allblocks] -class GenRpy: - def __init__(self, f, translator, modname=None): - self.f = f +class GenJava: + def __init__(self, jdir, translator, modname=None): + self.jdir = jdir self.translator = translator self.modname = (modname or translator.functions[0].__name__) - self.rpynames = {Constant(None).key: 'w(None)', - Constant(False).key: 'w(False)', - Constant(True).key: 'w(True)', - } + self.javanames = {Constant(None).key: 'null', + Constant(False).key: 'Py_False', + Constant(True).key: 'Py_True', + } self.seennames = {} self.initcode = [] # list of lines for the module's initxxx() @@ -121,21 +57,44 @@ self.globaldecl = [] self.globalobjects = [] self.pendingfunctions = [] + self.callpatterns = {} # special constructors: - self.has_listarg = {} - for name in "newtuple newlist newdict newstring".split(): - self.has_listarg[name] = name + self.has_listarg = { + 'newlist': 'PyList', + 'newtuple': 'PyTuple', + 'newdict': 'PyDict', + 'newstring':'PyString', + } + + self.nameof(self.translator.functions[0]) + self.gen_source() - self.gen_source() + def gen_test_class(self, inputargs, expectedresult): + entrypoint = self.nameof(self.translator.functions[0]) + f = self.jdir.join('test.java').open('w') + print >> f, 'class test extends PyObject {' + print >> f, ' static void main(String[] argv) {' + print >> f, ' PyObject result = %s.op_call_%d(%s);' % ( + entrypoint, len(inputargs), + ', '.join([self.nameof(x) for x in inputargs])) + print >> f, ' if (result.eq(%s))' % ( + self.nameof(expectedresult),) + print >> f, ' System.out.println("OK");' + print >> f, ' else' + print >> f, ' System.out.println("FAIL");' + print >> f, ' }' + self.gen_initcode(f) + print >> f, '};' + f.close() def nameof(self, obj): key = Constant(obj).key try: - return self.rpynames[key] + return self.javanames[key] except KeyError: #name = "w(%s)" % str(obj) - #self.rpynames[key] = name + #self.javanames[key] = name #return name if (type(obj).__module__ != '__builtin__' and not isinstance(obj, type)): # skip user-defined metaclasses @@ -151,7 +110,7 @@ else: raise Exception, "nameof(%r) in %r" % (obj, self.current_func) name = meth(obj) - self.rpynames[key] = name + self.javanames[key] = name return name def uniquename(self, basename): @@ -183,7 +142,7 @@ def nameof_int(self, value): - return "w(%d)" % value + return "new PyInt(%d)" % value def nameof_long(self, value): # assume we want them in hex most of the time @@ -224,9 +183,7 @@ print "skipped", printable_name return self.skipped_function(func) name = self.uniquename('gfunc_' + func.__name__) - self.initcode.append('INITCHK(%s = PyCFunction_New(' - '&ml_%s, NULL))' % (name, name)) - self.initcode.append('\t%s->ob_type = &PyGenCFunction_Type;' % name) + self.initcode.append('static PyObject %s = new C_%s();' % (name, name)) self.pendingfunctions.append(func) return name @@ -444,113 +401,140 @@ raise Exception, 'Cannot translate an already-open file: %r' % (fil,) def gen_source(self): - f = self.f - info = { - 'modname': self.modname, - 'entrypointname': self.translator.functions[0].__name__, - 'entrypoint': self.nameof(self.translator.functions[0]), - } +## info = { +## 'modname': self.modname, +## 'entrypointname': self.translator.functions[0].__name__, +## 'entrypoint': self.nameof(self.translator.functions[0]), +## } # function implementations while self.pendingfunctions: func = self.current_func = self.pendingfunctions.pop() - print "#######", func.__name__ - self.gen_rpyfunction(func) + self.gen_javafunction(func) # collect more of the latercode after each function - while self.latercode: - #gen, self.debugstack = self.latercode.pop() - gen = self.latercode.pop() - #self.initcode.extend(gen) -- eats TypeError! bad CPython! - for line in gen: - self.initcode.append(line) - self.debugstack = () + self.collect_latercode() #self.gen_global_declarations() - # footer - # maybe not needed - return - print >> f, self.C_INIT_HEADER % info - if self.f2name is not None: - print >> f, '#include "%s"' % self.f2name - for codeline in self.initcode: - print >> f, '\t' + codeline - print >> f, self.C_INIT_FOOTER % info + # copy over the PyXxx classes + mydir = os.path.dirname(__file__) + for fn in os.listdir(mydir): + if fn.lower().endswith('.java'): + g = open(os.path.join(mydir, fn), 'r') + f = self.jdir.join(fn).open('w') + data = g.read() + i = data.find('/* CUT HERE') + if i < 0: + f.write(data) + else: + f.write(data[:i]) + print >> f + print >> f, ' /* call patterns */' + callpatterns = self.callpatterns.items() + callpatterns.sort() + for callpattern, args in callpatterns: + print >> f, (' PyObject %s(%s) { throw new ' + 'TypeError(); }' % (callpattern, args)) + print >> f + self.gen_initcode(f) + print >> f, '};' + f.close() + g.close() + + def collect_latercode(self): + while self.latercode: + gen = self.latercode.pop() + #self.initcode.extend(gen) -- eats TypeError! bad CPython! + for line in gen: + self.initcode.append(line) + + def gen_initcode(self, f): + self.collect_latercode() + print >> f, ' /* init code */' + for line in self.initcode: + print >> f, ' ' + line + print >> f + self.initcode = [] - def gen_rpyfunction(self, func): + def gen_javafunction(self, func): + t = self.translator + #t.simplify(func) + graph = t.getflowgraph(func) + remove_direct_loops(graph) + checkgraph(graph) - local_names = {} + name = self.nameof(func) + f = self.jdir.join('C_%s.java' % name).open('w') + try: + src = graph.source + except AttributeError: + pass + else: + print >> f, '//' + for line in src.rstrip().split('\n'): + print >> f, '// ', line + print >> f, '//' + print >> f + print >> f, 'class C_%s extends PyObject {' % name + print >> f - def expr(v, wrapped = True): + def expr(v): if isinstance(v, Variable): - n = v.name - if n.startswith("v") and n[1:].isdigit(): - ret = local_names.get(v.name) - if not ret: - if wrapped: - local_names[v.name] = ret = "w_%d" % len(local_names) - else: - local_names[v.name] = ret = "v%d" % len(local_names) - return ret return v.name elif isinstance(v, Constant): return self.nameof(v.value) else: - #raise TypeError, "expr(%r)" % (v,) - # XXX how do I resolve these? - return "space.%s" % str(v) + raise TypeError, "expr(%r)" % (v,) - def arglist(args): - res = [expr(arg) for arg in args] + def arglist(args, prefix=''): + res = [prefix + expr(arg) for arg in args] return ", ".join(res) def oper(op): - # specialcase is_true if op.opname in self.has_listarg: - fmt = "%s = %s([%s])" + fmt = "PyObject[] a_%s = {%s}; PyObject %s = new %s(a_%s);" + v = expr(op.result) + return fmt % (v, arglist(op.args), v, + self.has_listarg[op.opname], v) else: - fmt = "%s = %s(%s)" - if op.opname == "is_true": - return fmt % (expr(op.result, False), expr(op.opname), arglist(op.args)) - return fmt % (expr(op.result), expr(op.opname), arglist(op.args)) + fmt = "PyObject %s = %s.op_%s(%s);" + return fmt % (expr(op.result), expr(op.args[0]), + op.opname, arglist(op.args[1:])) - def gen_link(link, linklocalvars=None): + def gen_link(link, linklocalvars={}): "Generate the code to jump across the given Link." - linklocalvars = linklocalvars or {} - left, right = [], [] for a1, a2 in zip(link.args, link.target.inputargs): if a1 in linklocalvars: src = linklocalvars[a1] else: src = expr(a1) - left.append(expr(a2)) - right.append(src) - yield "%s = %s" % (", ".join(left), ", ".join(right)) + yield "%s = %s;" % (expr(a2), src) goto = blocknum[link.target] - yield 'goto = %d' % goto - if goto <= blocknum[block]: - yield 'continue' + if goto == blocknum[block]+1: + yield '// falls through' + else: + yield 'block = %d;' % goto + yield 'continue;' - f = self.f - t = self.translator - #t.simplify(func) - graph = t.getflowgraph(func) - start = graph.startblock blocks = ordered_blocks(graph) nblocks = len(blocks) blocknum = {} + localvars = [] for block in blocks: blocknum[block] = len(blocknum)+1 + if block is not start: + localvars += block.inputargs # create function declaration - name = func.__name__ # change this - args = [expr(var) for var in start.inputargs] - argstr = ", ".join(args) - print >> f, "def %s(space, %s):" % (name, argstr) - print >> f, " w = space.wrap" - print >> f, " goto = %d # startblock" % blocknum[start] - print >> f, " while True:" + callpattern = "op_call_%d" % len(start.inputargs) + args = arglist(start.inputargs, prefix='PyObject ') + self.callpatterns[callpattern] = args + print >> f, " PyObject %s(%s) {" % (callpattern, args) + for v in localvars: + print >> f, " PyObject %s = null;" % v + print >> f, " int block = %d; // startblock" % blocknum[start] + print >> f, " while (true) switch (block) {" def render_block(block): catch_exception = block.exitswitch == Constant(last_exception) @@ -560,7 +544,7 @@ yield "%s" % oper(op) # render the last op if it is exception handled for op in block.operations[regular_op:]: - yield "try:" + yield "try {" yield " %s" % oper(op) if len(block.exits) == 0: @@ -568,11 +552,12 @@ # exceptional return block exc_cls = expr(block.inputargs[0]) exc_val = expr(block.inputargs[1]) + XXX yield "raise OperationError(%s, %s)" % (exc_cls, exc_val) else: # regular return block retval = expr(block.inputargs[0]) - yield "return %s" % retval + yield "return %s;" % retval return elif block.exitswitch is None: # single-exit block @@ -580,6 +565,7 @@ for op in gen_link(block.exits[0]): yield "%s" % op elif catch_exception: + XXX # block catching the exceptions raised by its last operation # we handle the non-exceptional case first link = block.exits[0] @@ -605,48 +591,29 @@ exits.reverse() q = "if" for link in exits[:-1]: - yield "%s %s == %s:" % (q, expr(block.exitswitch), - link.exitcase) + yield "%s (%s.eq(%s)) {" % (q, expr(block.exitswitch), + self.nameof(link.exitcase)) for op in gen_link(link): yield " %s" % op - q = "elif" + yield "}" + q = "else if" link = exits[-1] - yield "else:" - yield " assert %s == %s" % (expr(block.exitswitch), - link.exitcase) + yield "else {" + yield " // assert %s.eq(%s)" % (expr(block.exitswitch), + self.nameof(link.exitcase)) for op in gen_link(exits[-1]): yield " %s" % op + yield "}" for block in blocks: blockno = blocknum[block] print >> f - print " if goto == %d:" % blockno + print >> f, " case %d:" % blockno for line in render_block(block): - print " %s" % line - -def test_md5(): - #import md5 - # how do I avoid the builtin module? - from pypy.appspace import md5 - digest = md5.new("hello") - -entry_point = (f, ff, fff, app_str_decode__String_ANY_ANY, app_mod__String_ANY, test_md5) [-1] - -import os, sys -from pypy.interpreter import autopath -srcdir = os.path.dirname(autopath.pypydir) -appdir = os.path.join(autopath.pypydir, 'appspace') - -try: - hold = sys.path[:] - sys.path.insert(0, appdir) - t = Translator(entry_point, verbose=False, simplifying=True) - gen = GenRpy(sys.stdout, t) -finally: - sys.path[:] = hold -#t.simplify() -#t.view() -# debugging -graph = t.getflowgraph() -ab = ordered_blocks(graph) # use ctrl-b in PyWin with ab + print >> f, " %s" % line + print >> f, " }" + print >> f, " }" + print >> f + print >> f, "};" + f.close() Added: pypy/trunk/src/pypy/translator/java/test/test_javatrans.py ============================================================================== --- (empty file) +++ pypy/trunk/src/pypy/translator/java/test/test_javatrans.py Fri Dec 17 10:18:02 2004 @@ -0,0 +1,54 @@ +import autopath, os +from py.process import cmdexec +from pypy.tool import testit +from pypy.tool.udir import udir +from pypy.translator.java.genjava import GenJava +from pypy.translator.test import snippet +from pypy.translator.translator import Translator + + +class NoTypeCGenTestCase(testit.IntTestCase): + + def setUp(self): + self.space = testit.objspace('flow') + + def build_jfunc(self, func): + try: func = func.im_func + except AttributeError: pass + t = Translator(func) + t.simplify() + name = func.func_name + self.jdir = udir.mkdir(name) + self.gen = GenJava(self.jdir, t) + + def check(self, inputargs, expectedresult): + self.gen.gen_test_class(inputargs, expectedresult) + cwd = os.getcwd() + try: + os.chdir(str(self.jdir)) + cmdexec('javac *.java') + self.assertEquals(cmdexec('java test').strip(), 'OK') + finally: + os.chdir(cwd) + + def test_simple_func(self): + self.build_jfunc(snippet.simple_func) + self.check([123], 124) + + def test_if_then_else(self): + self.build_jfunc(snippet.if_then_else) + self.check([2,3,4], 3) + self.check([0,3,4], 4) + self.check([-1,3,4], 3) + + def test_two_plus_two(self): + self.build_jfunc(snippet.two_plus_two) + self.check([], 4) + + def test_sieve_of_eratosthenes(self): + self.build_jfunc(snippet.sieve_of_eratosthenes) + self.check([], 1028) + + +if __name__ == '__main__': + testit.main() From hpk at codespeak.net Fri Dec 17 13:40:13 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Dec 2004 13:40:13 +0100 (MET) Subject: [pypy-svn] r7900 - pypy/branch/src-pytest/pypy Message-ID: <20041217124013.0CFC85B06B@thoth.codespeak.net> Author: hpk Date: Fri Dec 17 13:40:12 2004 New Revision: 7900 Modified: pypy/branch/src-pytest/pypy/conftest.py Log: integrated the object space option (in a new way) to the py.test tool. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 17 13:40:12 2004 @@ -1,20 +1,60 @@ import py from pypy.interpreter.gateway import app2interp_temp from pypy.objspace.std import StdObjSpace -#def getoptions(): -# return [....] + +# +# PyPy's command line extra options (these are added +# to py.test's standard options) +# +Option = py.test.Option +options = ('pypy options', [ + Option('-o', '--objspace', action="store", default=None, + type="string", dest="objspacename", + help="object space to run tests on."), +]) + + +def getobjspace(name=None, _spacecache={}): + """ helper for instantiating and caching space's for testing. + """ + if name is None: + name = py.test.config.option.objspacename + if name is None: + name = os.environ.get('OBJSPACE', 'std') + try: + return _spacecache[name] + except KeyError: + module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) + Space = module.Space + return _spacecache.setdefault(name, Space()) + +# +# Interfacing/Integrating with py.test's collection process # -space = StdObjSpace() + +class Module(py.test.collect.Module): + """ we take care of collecting classes both at app level + and at interp-level (because we need to stick a space + at the class) ourselves. + """ + def collect_class(self, extpy): + if extpy.check(class_=1, basestarts="Test"): + yield IntClassCollector(extpy) + def collect_appclass(self, extpy): + if extpy.check(class_=1, basestarts="AppTest"): + yield AppClassCollector(extpy) class IntTestMethod(py.test.Item): def run(self, driver): cls = self.extpy.resolve().im_class + space = getobjspace() cls.space = space return super(IntTestMethod, self).run(driver) class AppTestMethod(py.test.Item): def execute(self, target, *args): func = app2interp_temp(target.im_func, target.__name__) + space = getobjspace() func(space, space.w_None) class AppClassCollector(py.test.collect.Class): @@ -23,15 +63,3 @@ class IntClassCollector(py.test.collect.Class): Item = IntTestMethod -class Module(py.test.collect.Module): - def collect_class(self, extpy): - if extpy.check(class_=1, basestarts="Test"): - yield IntClassCollector(extpy) - def collect_appclass(self, extpy): - if extpy.check(class_=1, basestarts="AppTest"): - yield AppClassCollector(extpy) - - - - - From hpk at codespeak.net Fri Dec 17 14:49:57 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Dec 2004 14:49:57 +0100 (MET) Subject: [pypy-svn] r7901 - pypy/branch/src-pytest/pypy Message-ID: <20041217134957.DCC195B06B@thoth.codespeak.net> Author: hpk Date: Fri Dec 17 14:49:57 2004 New Revision: 7901 Modified: pypy/branch/src-pytest/pypy/conftest.py Log: small import fix Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 17 14:49:57 2004 @@ -20,7 +20,7 @@ if name is None: name = py.test.config.option.objspacename if name is None: - name = os.environ.get('OBJSPACE', 'std') + name = py.std.os.environ.get('OBJSPACE', 'std') try: return _spacecache[name] except KeyError: From jacob at codespeak.net Fri Dec 17 16:35:20 2004 From: jacob at codespeak.net (jacob at codespeak.net) Date: Fri, 17 Dec 2004 16:35:20 +0100 (MET) Subject: [pypy-svn] r7903 - pypy/trunk/doc/funding/negotiations Message-ID: <20041217153520.BAC915B187@thoth.codespeak.net> Author: jacob Date: Fri Dec 17 16:35:20 2004 New Revision: 7903 Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw Log: Fixed references. Made appearance changes. No changes to actual content. Modified: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf ============================================================================== --- pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf (original) +++ pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.cpf Fri Dec 17 16:35:20 2004 @@ -1487,9 +1487,9 @@ PYPY 3 AB STRAKT - Per-?ke - - Olsson + Olsson + 19-08-2004 + Per-?ke Y Modified: pypy/trunk/doc/funding/negotiations/pypy-consortium-contract.sxw ============================================================================== Binary files. No diff available. From hpk at codespeak.net Fri Dec 17 19:07:12 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Dec 2004 19:07:12 +0100 (MET) Subject: [pypy-svn] r7904 - pypy/trunk/doc/funding/negotiations Message-ID: <20041217180712.07A765A919@thoth.codespeak.net> Author: hpk Date: Fri Dec 17 19:07:00 2004 New Revision: 7904 Modified: pypy/trunk/doc/funding/negotiations/part_b_2004_12_11.sxw Log: modified the Annex I which we are to send to the EU along with the Accession forms. Please, review the document in general but especially with respect to the changes i describe below: Changes: - Front page doesn't mention Southhampton anymore - i adapted B.4.2 (Contract Amendments) and following to reflect the new situation, properly following up on our previous version. - B.5.7 Consortium Agreement now describes our result of negotiations. (could be extended but i just wanted to advance the previous decription which talked more about things in the future tense). Modified: pypy/trunk/doc/funding/negotiations/part_b_2004_12_11.sxw ============================================================================== Binary files. No diff available. From arigo at codespeak.net Fri Dec 17 19:21:53 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Dec 2004 19:21:53 +0100 (MET) Subject: [pypy-svn] r7905 - pypy/branch/src-pytest/pypy Message-ID: <20041217182153.7C6215A919@thoth.codespeak.net> Author: arigo Date: Fri Dec 17 19:21:46 2004 New Revision: 7905 Modified: pypy/branch/src-pytest/pypy/conftest.py Log: - store 'space' on the instance instead of the class test. - skip tests that say they require a specific space if it doesn't match. the way to write this down is with a 'objspacename' class attribute. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 17 19:21:46 2004 @@ -21,6 +21,10 @@ name = py.test.config.option.objspacename if name is None: name = py.std.os.environ.get('OBJSPACE', 'std') + else: + optionname = py.test.config.option.objspacename + if optionname is not None and optionname != name: + return None try: return _spacecache[name] except KeyError: @@ -44,17 +48,24 @@ if extpy.check(class_=1, basestarts="AppTest"): yield AppClassCollector(extpy) +def gettestobjspace(name=None): + space = getobjspace(name) + if space is None: + py.test.skip('test requires object space %r' % (name,)) + return space + class IntTestMethod(py.test.Item): - def run(self, driver): - cls = self.extpy.resolve().im_class - space = getobjspace() - cls.space = space - return super(IntTestMethod, self).run(driver) + def execute(self, target, *args): + name = getattr(target.im_class, 'objspacename', None) + instance = target.im_self + instance.space = gettestobjspace(name) + return target(*args) class AppTestMethod(py.test.Item): def execute(self, target, *args): + name = getattr(target.im_class, 'objspacename', None) + space = gettestobjspace(name) func = app2interp_temp(target.im_func, target.__name__) - space = getobjspace() func(space, space.w_None) class AppClassCollector(py.test.collect.Class): From hpk at codespeak.net Fri Dec 17 19:46:05 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Dec 2004 19:46:05 +0100 (MET) Subject: [pypy-svn] r7906 - pypy/branch/src-pytest/pypy Message-ID: <20041217184605.356045A919@thoth.codespeak.net> Author: hpk Date: Fri Dec 17 19:46:04 2004 New Revision: 7906 Modified: pypy/branch/src-pytest/pypy/conftest.py Log: added collection/execution of global test functions both at app and at interp level. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 17 19:46:04 2004 @@ -41,9 +41,22 @@ and at interp-level (because we need to stick a space at the class) ourselves. """ + def collect_function(self, extpy): + if extpy.check(func=1, basestarts='test_'): + if extpy.check(genfunc=1): + yield IntTestGenerator(extpy) + else: + yield IntTestFunction(extpy) + + def collect_app_function(self, extpy): + if extpy.check(func=1, basestarts='app_test_'): + assert not extpy.check(genfunc=1), "you must be joking" + yield AppTestFunction(extpy) + def collect_class(self, extpy): if extpy.check(class_=1, basestarts="Test"): yield IntClassCollector(extpy) + def collect_appclass(self, extpy): if extpy.check(class_=1, basestarts="AppTest"): yield AppClassCollector(extpy) @@ -54,16 +67,35 @@ py.test.skip('test requires object space %r' % (name,)) return space +class IntTestFunction(py.test.Item): + def execute(self, target, *args): + name = target.func_globals.get('objspacename', None) + space = gettestobjspace(name) + return target(space, *args) + +class AppTestFunction(py.test.Item): + def execute(self, target, *args): + assert not args + name = target.func_globals.get('objspacename', None) + space = gettestobjspace(name) + func = app2interp_temp(target, target.__name__) + func(space) + class IntTestMethod(py.test.Item): def execute(self, target, *args): - name = getattr(target.im_class, 'objspacename', None) + name = target.func_globals.get('objspacename', None) + if name is None: + name = getattr(target.im_class, 'objspacename', None) instance = target.im_self instance.space = gettestobjspace(name) return target(*args) class AppTestMethod(py.test.Item): def execute(self, target, *args): - name = getattr(target.im_class, 'objspacename', None) + assert not args + name = target.func_globals.get('objspacename', None) + if name is None: + name = getattr(target.im_class, 'objspacename', None) space = gettestobjspace(name) func = app2interp_temp(target.im_func, target.__name__) func(space, space.w_None) From hpk at codespeak.net Fri Dec 17 20:00:51 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Dec 2004 20:00:51 +0100 (MET) Subject: [pypy-svn] r7907 - pypy/branch/src-pytest/pypy/tool/test Message-ID: <20041217190051.99C0E5A919@thoth.codespeak.net> Author: hpk Date: Fri Dec 17 20:00:51 2004 New Revision: 7907 Added: pypy/branch/src-pytest/pypy/tool/test/test_conftest1.py Log: added a test for our pypy/conftest.py hacks Added: pypy/branch/src-pytest/pypy/tool/test/test_conftest1.py ============================================================================== --- (empty file) +++ pypy/branch/src-pytest/pypy/tool/test/test_conftest1.py Fri Dec 17 20:00:51 2004 @@ -0,0 +1,15 @@ + +def test_something(space): + assert space.w_None is space.w_None + +def app_test_something(): + assert 42 == 42 + +class AppTestSomething: + def test_method(self): + assert 23 == 23 + +class TestSomething: + def test_method(self): + assert self.space + From arigo at codespeak.net Fri Dec 17 20:01:54 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Dec 2004 20:01:54 +0100 (MET) Subject: [pypy-svn] r7908 - pypy/branch/src-pytest/pypy Message-ID: <20041217190154.DAF205A919@thoth.codespeak.net> Author: arigo Date: Fri Dec 17 20:01:54 2004 New Revision: 7908 Modified: pypy/branch/src-pytest/pypy/conftest.py Log: Allow interp-level global tests that don't care about a 'space' argument. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 17 20:01:54 2004 @@ -69,9 +69,13 @@ class IntTestFunction(py.test.Item): def execute(self, target, *args): - name = target.func_globals.get('objspacename', None) - space = gettestobjspace(name) - return target(space, *args) + co = target.func_code + if 'space' in co.co_varnames[:co.co_argcount]: + name = target.func_globals.get('objspacename', None) + space = gettestobjspace(name) + return target(space, *args) + else: + return target(*args) class AppTestFunction(py.test.Item): def execute(self, target, *args): From arigo at codespeak.net Sat Dec 18 18:08:16 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Dec 2004 18:08:16 +0100 (MET) Subject: [pypy-svn] r7920 - in pypy/branch/src-pytest/pypy/interpreter: . test Message-ID: <20041218170816.5B71F5B344@thoth.codespeak.net> Author: arigo Date: Sat Dec 18 18:08:15 2004 New Revision: 7920 Modified: pypy/branch/src-pytest/pypy/interpreter/pyframe.py pypy/branch/src-pytest/pypy/interpreter/test/test_pyframe.py pypy/branch/src-pytest/pypy/interpreter/typedef.py Log: - the f_lineno attribute of frames. Modified: pypy/branch/src-pytest/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/src-pytest/pypy/interpreter/pyframe.py (original) +++ pypy/branch/src-pytest/pypy/interpreter/pyframe.py Sat Dec 18 18:08:15 2004 @@ -81,7 +81,23 @@ if valuestackdepth <= self.valuestack.depth(): break self.exceptionstack.pop() - + + ### line numbers ### + + def fget_f_lineno(space, w_self): + "Returns the line number of the instruction currently being executed." + self = space.unwrap_builtin(w_self) + return space.wrap(self.get_last_lineno()) + + def get_last_lineno(self): + "Returns the line number of the instruction currently being executed." + return pytraceback.offset2lineno(self.code, self.next_instr-1) + + def get_next_lineno(self): + "Returns the line number of the next instruction to execute." + return pytraceback.offset2lineno(self.code, self.next_instr) + + ### Frame Blocks ### class FrameBlock: Modified: pypy/branch/src-pytest/pypy/interpreter/test/test_pyframe.py ============================================================================== --- pypy/branch/src-pytest/pypy/interpreter/test/test_pyframe.py (original) +++ pypy/branch/src-pytest/pypy/interpreter/test/test_pyframe.py Sat Dec 18 18:08:15 2004 @@ -28,6 +28,17 @@ return f.f_code self.failUnless(g() is g.func_code) + def test_f_lineno(self): + def g(): + import sys + f = sys._getframe() + x = f.f_lineno + y = f.f_lineno + z = f.f_lineno + return [x, y, z] + origin = g.func_code.co_firstlineno + self.assertEquals(g(), [origin+3, origin+4, origin+5]) + if __name__ == '__main__': testit.main() Modified: pypy/branch/src-pytest/pypy/interpreter/typedef.py ============================================================================== --- pypy/branch/src-pytest/pypy/interpreter/typedef.py (original) +++ pypy/branch/src-pytest/pypy/interpreter/typedef.py Sat Dec 18 18:08:15 2004 @@ -212,6 +212,7 @@ PyFrame.typedef = TypeDef('frame', f_builtins = attrproperty_w('w_builtins'), + f_lineno = GetSetProperty(PyFrame.fget_f_lineno.im_func), **Frame.typedef.rawdict) Module.typedef = TypeDef("module", From arigo at codespeak.net Sun Dec 19 22:59:39 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Dec 2004 22:59:39 +0100 (MET) Subject: [pypy-svn] r7940 - pypy/branch/src-pytest/pypy/tool/pytest Message-ID: <20041219215939.85E375B344@thoth.codespeak.net> Author: arigo Date: Sun Dec 19 22:59:38 2004 New Revision: 7940 Added: pypy/branch/src-pytest/pypy/tool/pytest/autopath.py - copied unchanged from r7938, pypy/branch/src-pytest/pypy/tool/autopath.py Modified: pypy/branch/src-pytest/pypy/tool/pytest/support.py Log: Finished a replacement AssertionError for the app-level of PyPy. Comes with a few tests (in the file, so you have to run them explicitely as "py.test support.py"). Modified: pypy/branch/src-pytest/pypy/tool/pytest/support.py ============================================================================== --- pypy/branch/src-pytest/pypy/tool/pytest/support.py (original) +++ pypy/branch/src-pytest/pypy/tool/pytest/support.py Sun Dec 19 22:59:38 2004 @@ -1,16 +1,20 @@ -from py.__impl__.magic import exprinfo +import autopath import py -py.magic.autopath() +from py.__impl__.magic import exprinfo +from py.code import InspectableFrame from pypy.objspace.std import StdObjSpace from pypy.interpreter.gateway import app2interp, interp2app from pypy.interpreter.argument import Arguments +from pypy.interpreter.error import OperationError -class AppRunnerFrame: +class AppRunnerFrame(InspectableFrame): - def __init__(self, space, w_globals, w_locals): - self.space = space - self.w_globals = w_globals - self.w_locals = w_locals + def __init__(self, pyframe): + lineno = pyframe.get_last_lineno() + super(AppRunnerFrame, self).__init__(pyframe.code, lineno) + self.space = pyframe.space + self.w_globals = pyframe.w_globals + self.w_locals = pyframe.getdictscope() def eval(self, code, **vars): space = self.space @@ -30,45 +34,72 @@ def is_true(self, w_value): return self.space.is_true(w_value) -def build_pytest_assertion(space): - def app_getmyassertion(): - class MyAssertionError(AssertionError): - def __init__(self, *args): - AssertionError.__init__(self, *args) - self.inspect_assertion() - return MyAssertionError - getmyassertion = app2interp(app_getmyassertion) - w_myassertion = getmyassertion(space) - - def inspect_assertion(space, w_self): - pass - #print w_self - #print "got to interp-level inspect_assertion" - - w_inspect_assertion = space.wrap(interp2app(inspect_assertion)) - space.setattr(w_myassertion, - space.wrap('inspect_assertion'), - w_inspect_assertion) - return w_myassertion +def build_pytest_assertion(space): + def my_init(space, w_self, __args__): + "Our new AssertionError.__init__()." + w_parent_init = space.getattr(w_BuiltinAssertionError, + space.wrap('__init__')) + space.call_args(w_parent_init, __args__.prepend(w_self)) + framestack = space.getexecutioncontext().framestack + frame = framestack.top(0) + # Argh! we see app-level helpers in the frame stack! + # that's very probably very bad... + assert frame.code.co_name == 'app_normalize_exception' + frame = framestack.top(1) + + runner = AppRunnerFrame(frame) + # XXX what if the source is not available? + msg = exprinfo.interpret(str(runner.statement.deindent()), runner) + if msg is None: + msg = "(inconsistenty failed then succeeded)" + elif msg.startswith('AssertionError: '): + msg = msg[16:] + space.setattr(w_self, space.wrap('args'), + space.newtuple([space.wrap(msg)])) + + # build a new AssertionError class to replace the original one. + w_BuiltinAssertionError = space.getitem(space.w_builtins, + space.wrap('AssertionError')) + w_metaclass = space.type(w_BuiltinAssertionError) + w_init = space.wrap(interp2app(my_init)) + w_dict = space.newdict([]) + space.setitem(w_dict, space.wrap('__init__'), w_init) + return space.call_function(w_metaclass, + space.wrap('AssertionError'), + space.newtuple([w_BuiltinAssertionError]), + w_dict) def setup_module(mod): mod.space = StdObjSpace() +def somefunc(x): + print x + def test_AppRunnerFrame(): - w_glob = space.newdict([]) - w_loc = space.newdict([]) - runner = AppRunnerFrame(space, w_glob, w_loc) + from pypy.interpreter.pycode import PyCode + from pypy.interpreter.pyframe import PyFrame + import sys + co = PyCode()._from_code(somefunc.func_code) + pyframe = PyFrame(space, co, space.newdict([]), None) + runner = AppRunnerFrame(pyframe) exprinfo.run("f = lambda x: x+1", runner) - exprinfo.check("isinstance(f(2), float)", runner) + msg = exprinfo.interpret("assert isinstance(f(2), float)", runner) + assert msg.startswith("AssertionError: assert isinstance(3, float)\n" + " + where 3 = ") + def test_myexception(): def app_test_func(): - assert 42 == 43 + x = 6*7 + assert x == 43 t = app2interp(app_test_func) f = t.get_function(space) - #space.setitem(space.w_builtins, space.wrap('AssertionError'), - # build_pytest_assertion(space)) - f.call_args(Arguments([])) - -if __name__ == '__main__': - test() + space.setitem(space.w_builtins, space.wrap('AssertionError'), + build_pytest_assertion(space)) + try: + f.call_args(Arguments([])) + except OperationError, e: + assert e.match(space, space.w_AssertionError) + assert space.unwrap(space.str(e.w_value)) == 'assert 42 == 43' + else: + assert False, "got no exception!" From tismer at codespeak.net Mon Dec 20 13:02:53 2004 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 20 Dec 2004 13:02:53 +0100 (MET) Subject: [pypy-svn] r7943 - pypy/trunk/doc/funding/negotiations Message-ID: <20041220120253.5C62E5AF07@thoth.codespeak.net> Author: tismer Date: Mon Dec 20 13:02:52 2004 New Revision: 7943 Added: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.pdf (contents, props changed) Log: added PDF version of the CPF Added: pypy/trunk/doc/funding/negotiations/IST-2-004779-STP.pdf ============================================================================== Binary file. No diff available. From arigo at codespeak.net Mon Dec 20 16:00:02 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Dec 2004 16:00:02 +0100 (MET) Subject: [pypy-svn] r7945 - pypy/branch/src-pytest/pypy/tool/pytest Message-ID: <20041220150002.407525AF07@thoth.codespeak.net> Author: arigo Date: Mon Dec 20 16:00:01 2004 New Revision: 7945 Modified: pypy/branch/src-pytest/pypy/tool/pytest/support.py Log: clean-up Modified: pypy/branch/src-pytest/pypy/tool/pytest/support.py ============================================================================== --- pypy/branch/src-pytest/pypy/tool/pytest/support.py (original) +++ pypy/branch/src-pytest/pypy/tool/pytest/support.py Mon Dec 20 16:00:01 2004 @@ -3,7 +3,7 @@ from py.__impl__.magic import exprinfo from py.code import InspectableFrame from pypy.objspace.std import StdObjSpace -from pypy.interpreter.gateway import app2interp, interp2app +from pypy.interpreter.gateway import app2interp_temp, interp2app_temp from pypy.interpreter.argument import Arguments from pypy.interpreter.error import OperationError @@ -61,7 +61,7 @@ w_BuiltinAssertionError = space.getitem(space.w_builtins, space.wrap('AssertionError')) w_metaclass = space.type(w_BuiltinAssertionError) - w_init = space.wrap(interp2app(my_init)) + w_init = space.wrap(interp2app_temp(my_init)) w_dict = space.newdict([]) space.setitem(w_dict, space.wrap('__init__'), w_init) return space.call_function(w_metaclass, @@ -92,7 +92,7 @@ def app_test_func(): x = 6*7 assert x == 43 - t = app2interp(app_test_func) + t = app2interp_temp(app_test_func) f = t.get_function(space) space.setitem(space.w_builtins, space.wrap('AssertionError'), build_pytest_assertion(space)) From lene at codespeak.net Tue Dec 21 00:12:36 2004 From: lene at codespeak.net (lene at codespeak.net) Date: Tue, 21 Dec 2004 00:12:36 +0100 (MET) Subject: [pypy-svn] r7949 - pypy/trunk/doc/funding/negotiations/amendment Message-ID: <20041220231236.01C955A964@thoth.codespeak.net> Author: lene Date: Tue Dec 21 00:12:35 2004 New Revision: 7949 Modified: pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b hhud (blanko).doc Log: removed two needless "s" Modified: pypy/trunk/doc/funding/negotiations/amendment/LOA-form-b hhud (blanko).doc ============================================================================== Binary files. No diff available. From arigo at codespeak.net Wed Dec 22 18:49:31 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 22 Dec 2004 18:49:31 +0100 (MET) Subject: [pypy-svn] r7972 - in pypy/branch/src-pytest/pypy: . tool/pytest Message-ID: <20041222174931.4672D5ACE5@thoth.codespeak.net> Author: arigo Date: Wed Dec 22 18:49:30 2004 New Revision: 7972 Modified: pypy/branch/src-pytest/pypy/conftest.py pypy/branch/src-pytest/pypy/tool/pytest/support.py Log: A pile of hacks that more or less allow nice app-level tracebacks to be displayed. For some reason it more or less works with magic already, but in case of trouble, you'll need to use --nomagic. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Wed Dec 22 18:49:30 2004 @@ -1,5 +1,6 @@ import py from pypy.interpreter.gateway import app2interp_temp +from pypy.interpreter.error import OperationError from pypy.objspace.std import StdObjSpace # @@ -67,34 +68,105 @@ py.test.skip('test requires object space %r' % (name,)) return space -class IntTestFunction(py.test.Item): + +class AppRunnerFrame(py.code.InspectableFrame): + + def __init__(self, pyframe): + lineno = pyframe.get_last_lineno() - 1 + super(AppRunnerFrame, self).__init__(pyframe.code, lineno) + self.space = pyframe.space + self.w_globals = pyframe.w_globals + self.w_locals = pyframe.getdictscope() + + def eval(self, code, **vars): + space = self.space + for key, w_value in vars.items(): + space.setitem(self.w_locals, space.wrap(key), w_value) + return space.eval(code, self.w_globals, self.w_locals) + + def exec_(self, code, **vars): + space = self.space + for key, w_value in vars.items(): + space.setitem(self.w_locals, space.wrap(key), w_value) + space.exec_(code, self.w_globals, self.w_locals) + + def repr(self, w_value): + return self.space.unwrap(self.space.repr(w_value)) + + def is_true(self, w_value): + return self.space.is_true(w_value) + + +class AppExceptionInfo(py.code.ExceptionInfo): + """An ExceptionInfo object representing an app-level exception.""" + + def __init__(self, space, operr): + self.space = space + self.operr = operr + # XXX this is all a hackish forced integration with the not-yet- + # finished API of py.code.ExceptionInfo. + w_type, w_value = operr.w_type, operr.w_value + if not space.is_true(space.isinstance(w_type, space.w_str)): + w_type = space.getattr(w_type, space.wrap('__name__')) + t = space.unwrap(space.str(w_type)) + v = space.unwrap(space.str(w_value)) + if v: + operrtext = '(app-level) %s: %s' % (t, v) + else: + operrtext = '(app-level) %s' % (t,) + tup = (operr.__class__, operrtext, operr.application_traceback) + super(AppExceptionInfo, self).__init__(tup) + + def __iter__(self): + tb = self.tb + while tb is not None: + iframe = AppRunnerFrame(tb.frame) + iframe.f_locals = {} # XXX remove me + yield AppTracebackEntry(iframe, tb.lineno - 1) + tb = tb.next + +class AppTracebackEntry(py.__impl__.code.excinfo.TracebackEntry): + def __init__(self, frame, lineno): + self.frame = frame + self.lineno = lineno + + +class PyPyItem(py.test.Item): + # All PyPy test items catch and display OperationErrors specially. + def execute_in_space(self, space, target, *args): + try: + target(*args) + except OperationError, e: + raise self.Failed(excinfo=AppExceptionInfo(space, e)) + +class IntTestFunction(PyPyItem): def execute(self, target, *args): co = target.func_code - if 'space' in co.co_varnames[:co.co_argcount]: + if 'space' in co.co_varnames[:co.co_argcount]: name = target.func_globals.get('objspacename', None) space = gettestobjspace(name) - return target(space, *args) + self.execute_in_space(space, target, space, *args) else: - return target(*args) + target(*args) -class AppTestFunction(py.test.Item): - def execute(self, target, *args): +class AppTestFunction(PyPyItem): + def execute(self, target, *args): assert not args name = target.func_globals.get('objspacename', None) space = gettestobjspace(name) - func = app2interp_temp(target, target.__name__) - func(space) + func = app2interp_temp(target, target.__name__) + self.execute_in_space(space, target, space) -class IntTestMethod(py.test.Item): +class IntTestMethod(PyPyItem): def execute(self, target, *args): name = target.func_globals.get('objspacename', None) if name is None: name = getattr(target.im_class, 'objspacename', None) instance = target.im_self - instance.space = gettestobjspace(name) - return target(*args) + instance.space = space = gettestobjspace(name) + self.execute_in_space(space, target, *args) -class AppTestMethod(py.test.Item): +class AppTestMethod(PyPyItem): def execute(self, target, *args): assert not args name = target.func_globals.get('objspacename', None) @@ -102,7 +174,7 @@ name = getattr(target.im_class, 'objspacename', None) space = gettestobjspace(name) func = app2interp_temp(target.im_func, target.__name__) - func(space, space.w_None) + self.execute_in_space(space, func, space, space.w_None) class AppClassCollector(py.test.collect.Class): Item = AppTestMethod Modified: pypy/branch/src-pytest/pypy/tool/pytest/support.py ============================================================================== --- pypy/branch/src-pytest/pypy/tool/pytest/support.py (original) +++ pypy/branch/src-pytest/pypy/tool/pytest/support.py Wed Dec 22 18:49:30 2004 @@ -10,7 +10,7 @@ class AppRunnerFrame(InspectableFrame): def __init__(self, pyframe): - lineno = pyframe.get_last_lineno() + lineno = pyframe.get_last_lineno() - 1 super(AppRunnerFrame, self).__init__(pyframe.code, lineno) self.space = pyframe.space self.w_globals = pyframe.w_globals From lac at codespeak.net Thu Dec 23 15:30:22 2004 From: lac at codespeak.net (lac at codespeak.net) Date: Thu, 23 Dec 2004 15:30:22 +0100 (MET) Subject: [pypy-svn] r7975 - pypy/trunk/doc/sprintinfo Message-ID: <20041223143022.A7DE25A2EB@thoth.codespeak.net> Author: lac Date: Thu Dec 23 15:30:22 2004 New Revision: 7975 Modified: pypy/trunk/doc/sprintinfo/checklist.txt Log: Fix unmatched parenthesis. While I was there found one typo and decided to bump the 'Sprint attendants expected' from 10 to 12. Is the 'clear the list of Sprint attendents now obsolete?' I did not remove it, but .... Modified: pypy/trunk/doc/sprintinfo/checklist.txt ============================================================================== --- pypy/trunk/doc/sprintinfo/checklist.txt (original) +++ pypy/trunk/doc/sprintinfo/checklist.txt Thu Dec 23 15:30:22 2004 @@ -13,7 +13,7 @@ - find someone who can organize locally a good place with (at least) these characteristics: - - for at least 10 people + - for at least 12 people - with an permananent internet connection @@ -49,13 +49,13 @@ - try to help people to find accomodation (it's usually a lot easier for a local to judge/recommend (or organize in the best case) accomodation - than for all the people from abroad + than for all the people from abroad) - if neccessary recommend a week-ticket and some public transport plan so that people know how to move in that city. -technical advise for sprinters +technical advice for sprinters ------------------------------ - subscribe to pypy-dev From arigo at codespeak.net Fri Dec 24 17:41:34 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Dec 2004 17:41:34 +0100 (MET) Subject: [pypy-svn] r7987 - pypy/branch/src-pytest/pypy Message-ID: <20041224164134.0A10D5B552@thoth.codespeak.net> Author: arigo Date: Fri Dec 24 17:41:33 2004 New Revision: 7987 Modified: pypy/branch/src-pytest/pypy/conftest.py Log: Trying to update PyPy's conftest.py for the py refactoring... With --nomagic it works just fine. With magic, however, the reinterpretation hides the original nicely formatted entry; for example, instead of: (app-level) AttributeError: object X has no attribute Y the line is much longer: OperationError: << [: W_StringObject("object X... The former is generated by AppExceptionInfo. The latter is produced by exprinfo.py. This points to a much more important problem: what if the reinterpretation raises a different exception? Arbitrary code may fail for completely different reasons if it's blindly run a second time... Displaying the second exception only in py.test's traceback is a very bad idea :-( Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 24 17:41:33 2004 @@ -69,14 +69,15 @@ return space -class AppRunnerFrame(py.code.InspectableFrame): +class AppFrame(py.code.Frame): def __init__(self, pyframe): - lineno = pyframe.get_last_lineno() - 1 - super(AppRunnerFrame, self).__init__(pyframe.code, lineno) + self.code = py.code.Code(pyframe.code) + self.lineno = pyframe.get_last_lineno() - 1 self.space = pyframe.space self.w_globals = pyframe.w_globals self.w_locals = pyframe.getdictscope() + self.f_locals = self.w_locals # for py.test's recursion detection def eval(self, code, **vars): space = self.space @@ -99,36 +100,25 @@ class AppExceptionInfo(py.code.ExceptionInfo): """An ExceptionInfo object representing an app-level exception.""" + exprinfo = None def __init__(self, space, operr): self.space = space self.operr = operr - # XXX this is all a hackish forced integration with the not-yet- - # finished API of py.code.ExceptionInfo. - w_type, w_value = operr.w_type, operr.w_value - if not space.is_true(space.isinstance(w_type, space.w_str)): - w_type = space.getattr(w_type, space.wrap('__name__')) - t = space.unwrap(space.str(w_type)) - v = space.unwrap(space.str(w_value)) - if v: - operrtext = '(app-level) %s: %s' % (t, v) - else: - operrtext = '(app-level) %s' % (t,) - tup = (operr.__class__, operrtext, operr.application_traceback) - super(AppExceptionInfo, self).__init__(tup) + + def __str__(self): + return '(app-level) ' + self.operr.errorstr(self.space) def __iter__(self): - tb = self.tb + tb = self.operr.application_traceback while tb is not None: - iframe = AppRunnerFrame(tb.frame) - iframe.f_locals = {} # XXX remove me - yield AppTracebackEntry(iframe, tb.lineno - 1) + yield AppTracebackEntry(tb) tb = tb.next -class AppTracebackEntry(py.__impl__.code.excinfo.TracebackEntry): - def __init__(self, frame, lineno): - self.frame = frame - self.lineno = lineno +class AppTracebackEntry(py.code.TracebackEntry): + def __init__(self, tb): + self.frame = AppFrame(tb.frame) + self.lineno = tb.lineno - 1 class PyPyItem(py.test.Item): From arigo at codespeak.net Fri Dec 24 18:14:27 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Dec 2004 18:14:27 +0100 (MET) Subject: [pypy-svn] r7988 - in pypy/branch/src-pytest/pypy: . tool tool/pytest tool/test Message-ID: <20041224171427.26AC95B552@thoth.codespeak.net> Author: arigo Date: Fri Dec 24 18:14:26 2004 New Revision: 7988 Added: pypy/branch/src-pytest/pypy/tool/pytestsupport.py - copied, changed from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py pypy/branch/src-pytest/pypy/tool/test/test_pytestsupport.py - copied, changed from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py Removed: pypy/branch/src-pytest/pypy/tool/pytest/ Modified: pypy/branch/src-pytest/pypy/conftest.py Log: D tool/pytest M conftest.py Moved some content of the above files into a new module: A tool/pytestsupport.py A tool/test/test_pytestsupport.py This (finally) allows app-level assertions to be displayed with full exprinfo explanations. For other app-level exceptions, reinterpretation is entierely disabled for now. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 24 18:14:26 2004 @@ -1,7 +1,8 @@ import py from pypy.interpreter.gateway import app2interp_temp from pypy.interpreter.error import OperationError -from pypy.objspace.std import StdObjSpace +from pypy.objspace.std import StdObjSpace +from pypy.tool import pytestsupport # # PyPy's command line extra options (these are added @@ -30,8 +31,11 @@ return _spacecache[name] except KeyError: module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) - Space = module.Space - return _spacecache.setdefault(name, Space()) + space = module.Space() + _spacecache[name] = space + space.setitem(space.w_builtins, space.wrap('AssertionError'), + pytestsupport.build_pytest_assertion(space)) + return space # # Interfacing/Integrating with py.test's collection process @@ -69,65 +73,13 @@ return space -class AppFrame(py.code.Frame): - - def __init__(self, pyframe): - self.code = py.code.Code(pyframe.code) - self.lineno = pyframe.get_last_lineno() - 1 - self.space = pyframe.space - self.w_globals = pyframe.w_globals - self.w_locals = pyframe.getdictscope() - self.f_locals = self.w_locals # for py.test's recursion detection - - def eval(self, code, **vars): - space = self.space - for key, w_value in vars.items(): - space.setitem(self.w_locals, space.wrap(key), w_value) - return space.eval(code, self.w_globals, self.w_locals) - - def exec_(self, code, **vars): - space = self.space - for key, w_value in vars.items(): - space.setitem(self.w_locals, space.wrap(key), w_value) - space.exec_(code, self.w_globals, self.w_locals) - - def repr(self, w_value): - return self.space.unwrap(self.space.repr(w_value)) - - def is_true(self, w_value): - return self.space.is_true(w_value) - - -class AppExceptionInfo(py.code.ExceptionInfo): - """An ExceptionInfo object representing an app-level exception.""" - exprinfo = None - - def __init__(self, space, operr): - self.space = space - self.operr = operr - - def __str__(self): - return '(app-level) ' + self.operr.errorstr(self.space) - - def __iter__(self): - tb = self.operr.application_traceback - while tb is not None: - yield AppTracebackEntry(tb) - tb = tb.next - -class AppTracebackEntry(py.code.TracebackEntry): - def __init__(self, tb): - self.frame = AppFrame(tb.frame) - self.lineno = tb.lineno - 1 - - class PyPyItem(py.test.Item): # All PyPy test items catch and display OperationErrors specially. def execute_in_space(self, space, target, *args): try: target(*args) except OperationError, e: - raise self.Failed(excinfo=AppExceptionInfo(space, e)) + raise self.Failed(excinfo=pytestsupport.AppExceptionInfo(space, e)) class IntTestFunction(PyPyItem): def execute(self, target, *args): Copied: pypy/branch/src-pytest/pypy/tool/pytestsupport.py (from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py) ============================================================================== --- pypy/branch/src-pytest/pypy/tool/pytest/support.py (original) +++ pypy/branch/src-pytest/pypy/tool/pytestsupport.py Fri Dec 24 18:14:26 2004 @@ -1,20 +1,19 @@ import autopath import py from py.__impl__.magic import exprinfo -from py.code import InspectableFrame -from pypy.objspace.std import StdObjSpace -from pypy.interpreter.gateway import app2interp_temp, interp2app_temp -from pypy.interpreter.argument import Arguments -from pypy.interpreter.error import OperationError +from pypy.interpreter.gateway import interp2app_temp -class AppRunnerFrame(InspectableFrame): +# ____________________________________________________________ + +class AppFrame(py.code.Frame): def __init__(self, pyframe): - lineno = pyframe.get_last_lineno() - 1 - super(AppRunnerFrame, self).__init__(pyframe.code, lineno) + self.code = py.code.Code(pyframe.code) + self.lineno = pyframe.get_last_lineno() - 1 self.space = pyframe.space self.w_globals = pyframe.w_globals self.w_locals = pyframe.getdictscope() + self.f_locals = self.w_locals # for py.test's recursion detection def eval(self, code, **vars): space = self.space @@ -34,6 +33,41 @@ def is_true(self, w_value): return self.space.is_true(w_value) + +class AppExceptionInfo(py.code.ExceptionInfo): + """An ExceptionInfo object representing an app-level exception.""" + + def __init__(self, space, operr): + self.space = space + self.operr = operr + self.exprinfo = None + + def __str__(self): + return '(app-level) ' + self.operr.errorstr(self.space) + + def reinterpret(self): + # XXX we need to solve a general problem: how to prevent + # reinterpretation from generating a different exception? + # This problem includes the fact that exprinfo will generate + # its own long message that looks like + # OperationError: << [: W_StringObj... + # which is much less nice than the one produced by str(self). + # XXX this reinterpret() is only here to prevent reinterpretation. + return self.exprinfo + + def __iter__(self): + tb = self.operr.application_traceback + while tb is not None: + yield AppTracebackEntry(tb) + tb = tb.next + +class AppTracebackEntry(py.code.TracebackEntry): + def __init__(self, tb): + self.frame = AppFrame(tb.frame) + self.lineno = tb.lineno - 1 + +# ____________________________________________________________ + def build_pytest_assertion(space): def my_init(space, w_self, __args__): "Our new AssertionError.__init__()." @@ -47,15 +81,20 @@ assert frame.code.co_name == 'app_normalize_exception' frame = framestack.top(1) - runner = AppRunnerFrame(frame) - # XXX what if the source is not available? - msg = exprinfo.interpret(str(runner.statement.deindent()), runner) - if msg is None: - msg = "(inconsistenty failed then succeeded)" - elif msg.startswith('AssertionError: '): - msg = msg[16:] - space.setattr(w_self, space.wrap('args'), - space.newtuple([space.wrap(msg)])) + runner = AppFrame(frame) + try: + source = runner.statement + source = str(source).strip() + except py.path.NotFound: + source = None + if source: + msg = exprinfo.interpret(source, runner, should_fail=True) + space.setattr(w_self, space.wrap('args'), + space.newtuple([space.wrap(msg)])) + w_msg = space.wrap(msg) + else: + w_msg = space.w_None + space.setattr(w_self, space.wrap('msg'), w_msg) # build a new AssertionError class to replace the original one. w_BuiltinAssertionError = space.getitem(space.w_builtins, @@ -68,38 +107,3 @@ space.wrap('AssertionError'), space.newtuple([w_BuiltinAssertionError]), w_dict) - -def setup_module(mod): - mod.space = StdObjSpace() - -def somefunc(x): - print x - -def test_AppRunnerFrame(): - from pypy.interpreter.pycode import PyCode - from pypy.interpreter.pyframe import PyFrame - import sys - co = PyCode()._from_code(somefunc.func_code) - pyframe = PyFrame(space, co, space.newdict([]), None) - runner = AppRunnerFrame(pyframe) - exprinfo.run("f = lambda x: x+1", runner) - msg = exprinfo.interpret("assert isinstance(f(2), float)", runner) - assert msg.startswith("AssertionError: assert isinstance(3, float)\n" - " + where 3 = ") - - -def test_myexception(): - def app_test_func(): - x = 6*7 - assert x == 43 - t = app2interp_temp(app_test_func) - f = t.get_function(space) - space.setitem(space.w_builtins, space.wrap('AssertionError'), - build_pytest_assertion(space)) - try: - f.call_args(Arguments([])) - except OperationError, e: - assert e.match(space, space.w_AssertionError) - assert space.unwrap(space.str(e.w_value)) == 'assert 42 == 43' - else: - assert False, "got no exception!" Copied: pypy/branch/src-pytest/pypy/tool/test/test_pytestsupport.py (from r7980, pypy/branch/src-pytest/pypy/tool/pytest/support.py) ============================================================================== --- pypy/branch/src-pytest/pypy/tool/pytest/support.py (original) +++ pypy/branch/src-pytest/pypy/tool/test/test_pytestsupport.py Fri Dec 24 18:14:26 2004 @@ -1,94 +1,28 @@ import autopath -import py from py.__impl__.magic import exprinfo -from py.code import InspectableFrame -from pypy.objspace.std import StdObjSpace -from pypy.interpreter.gateway import app2interp_temp, interp2app_temp -from pypy.interpreter.argument import Arguments from pypy.interpreter.error import OperationError +from pypy.interpreter.gateway import app2interp_temp +from pypy.interpreter.argument import Arguments +from pypy.interpreter.pycode import PyCode +from pypy.interpreter.pyframe import PyFrame +from pypy.tool.pytestsupport import AppFrame, build_pytest_assertion -class AppRunnerFrame(InspectableFrame): - - def __init__(self, pyframe): - lineno = pyframe.get_last_lineno() - 1 - super(AppRunnerFrame, self).__init__(pyframe.code, lineno) - self.space = pyframe.space - self.w_globals = pyframe.w_globals - self.w_locals = pyframe.getdictscope() - - def eval(self, code, **vars): - space = self.space - for key, w_value in vars.items(): - space.setitem(self.w_locals, space.wrap(key), w_value) - return space.eval(code, self.w_globals, self.w_locals) - - def exec_(self, code, **vars): - space = self.space - for key, w_value in vars.items(): - space.setitem(self.w_locals, space.wrap(key), w_value) - space.exec_(code, self.w_globals, self.w_locals) - - def repr(self, w_value): - return self.space.unwrap(self.space.repr(w_value)) - - def is_true(self, w_value): - return self.space.is_true(w_value) - -def build_pytest_assertion(space): - def my_init(space, w_self, __args__): - "Our new AssertionError.__init__()." - w_parent_init = space.getattr(w_BuiltinAssertionError, - space.wrap('__init__')) - space.call_args(w_parent_init, __args__.prepend(w_self)) - framestack = space.getexecutioncontext().framestack - frame = framestack.top(0) - # Argh! we see app-level helpers in the frame stack! - # that's very probably very bad... - assert frame.code.co_name == 'app_normalize_exception' - frame = framestack.top(1) - - runner = AppRunnerFrame(frame) - # XXX what if the source is not available? - msg = exprinfo.interpret(str(runner.statement.deindent()), runner) - if msg is None: - msg = "(inconsistenty failed then succeeded)" - elif msg.startswith('AssertionError: '): - msg = msg[16:] - space.setattr(w_self, space.wrap('args'), - space.newtuple([space.wrap(msg)])) - - # build a new AssertionError class to replace the original one. - w_BuiltinAssertionError = space.getitem(space.w_builtins, - space.wrap('AssertionError')) - w_metaclass = space.type(w_BuiltinAssertionError) - w_init = space.wrap(interp2app_temp(my_init)) - w_dict = space.newdict([]) - space.setitem(w_dict, space.wrap('__init__'), w_init) - return space.call_function(w_metaclass, - space.wrap('AssertionError'), - space.newtuple([w_BuiltinAssertionError]), - w_dict) - -def setup_module(mod): - mod.space = StdObjSpace() def somefunc(x): print x -def test_AppRunnerFrame(): - from pypy.interpreter.pycode import PyCode - from pypy.interpreter.pyframe import PyFrame +def test_AppFrame(space): import sys co = PyCode()._from_code(somefunc.func_code) pyframe = PyFrame(space, co, space.newdict([]), None) - runner = AppRunnerFrame(pyframe) + runner = AppFrame(pyframe) exprinfo.run("f = lambda x: x+1", runner) msg = exprinfo.interpret("assert isinstance(f(2), float)", runner) - assert msg.startswith("AssertionError: assert isinstance(3, float)\n" + assert msg.startswith("assert isinstance(3, float)\n" " + where 3 = ") -def test_myexception(): +def test_myexception(space): def app_test_func(): x = 6*7 assert x == 43 From hpk at codespeak.net Fri Dec 24 19:51:58 2004 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Dec 2004 19:51:58 +0100 (MET) Subject: [pypy-svn] r7989 - in pypy/branch/src-pytest/pypy: . interpreter/test Message-ID: <20041224185158.EBD4F5AA04@thoth.codespeak.net> Author: hpk Date: Fri Dec 24 19:51:56 2004 New Revision: 7989 Added: pypy/branch/src-pytest/pypy/example_pytest.py Modified: pypy/branch/src-pytest/pypy/conftest.py pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py Log: small fix, an example_pytest containing the four so-far test variants and a fully converted test_interpreter.py Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Fri Dec 24 19:51:56 2004 @@ -97,7 +97,7 @@ name = target.func_globals.get('objspacename', None) space = gettestobjspace(name) func = app2interp_temp(target, target.__name__) - self.execute_in_space(space, target, space) + self.execute_in_space(space, target) class IntTestMethod(PyPyItem): def execute(self, target, *args): Added: pypy/branch/src-pytest/pypy/example_pytest.py ============================================================================== --- (empty file) +++ pypy/branch/src-pytest/pypy/example_pytest.py Fri Dec 24 19:51:56 2004 @@ -0,0 +1,14 @@ +class AppTestTest: + def test_app_method(self): + assert 42 == 41 + +def app_test_app_func(): + assert 41 == 42 + +def test_interp_func(space): + assert space.is_true(space.w_None) + +class TestInterpTest: + def test_interp_method(self): + assert self.space.is_true(self.space.w_False) + Modified: pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py Fri Dec 24 19:51:56 2004 @@ -255,6 +255,3 @@ finally: sys.stdout = save - def test_identity(self): - def f(x): return x - assert f(666) == 666 From arigo at codespeak.net Mon Dec 27 16:31:52 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 27 Dec 2004 16:31:52 +0100 (MET) Subject: [pypy-svn] r8001 - in pypy/branch/src-pytest/pypy: . tool Message-ID: <20041227153152.A62EC5A1D3@thoth.codespeak.net> Author: arigo Date: Mon Dec 27 16:31:52 2004 New Revision: 8001 Modified: pypy/branch/src-pytest/pypy/conftest.py pypy/branch/src-pytest/pypy/tool/pytestsupport.py Log: The PyPy version of raises(), which is pushed into the space's builtins for use by application-level tests. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Mon Dec 27 16:31:52 2004 @@ -35,6 +35,8 @@ _spacecache[name] = space space.setitem(space.w_builtins, space.wrap('AssertionError'), pytestsupport.build_pytest_assertion(space)) + space.setitem(space.w_builtins, space.wrap('raises'), + space.wrap(pytestsupport.app_raises)) return space # Modified: pypy/branch/src-pytest/pypy/tool/pytestsupport.py ============================================================================== --- pypy/branch/src-pytest/pypy/tool/pytestsupport.py (original) +++ pypy/branch/src-pytest/pypy/tool/pytestsupport.py Mon Dec 27 16:31:52 2004 @@ -2,6 +2,7 @@ import py from py.__impl__.magic import exprinfo from pypy.interpreter.gateway import interp2app_temp +from pypy.interpreter.error import OperationError # ____________________________________________________________ @@ -107,3 +108,39 @@ space.wrap('AssertionError'), space.newtuple([w_BuiltinAssertionError]), w_dict) + +def pypyraises(space, w_ExpectedException, w_expr, __args__): + """A built-in function providing the equivalent of py.test.raises().""" + args_w, kwds_w = __args__.unpack() + if space.is_true(space.isinstance(w_expr, space.w_str)): + if args_w: + raise OperationError(space.w_TypeError, + space.wrap("raises() takes no argument " + "after a string expression")) + expr = space.unwrap(w_expr) + source = py.code.Source(expr) + frame = space.executioncontext.framestack.top() + w_locals = frame.getdictscope() + w_locals = space.call_method(w_locals, 'copy') + for key, w_value in kwds_w.items(): + space.setitem(w_locals, space.wrap(key), w_value) + try: + space.call_method(space.w_builtin, 'eval', + space.wrap(str(source)), + frame.w_globals, + w_locals) + except OperationError, e: + if e.match(space, w_ExpectedException): + return space.sys.exc_info() + raise + else: + try: + space.call_args(w_expr, __args__) + except OperationError, e: + if e.match(space, w_ExpectedException): + return space.sys.exc_info() + raise + raise OperationError(space.w_AssertionError, + space.wrap("DID NOT RAISE")) + +app_raises = interp2app_temp(pypyraises) From arigo at codespeak.net Mon Dec 27 16:52:10 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 27 Dec 2004 16:52:10 +0100 (MET) Subject: [pypy-svn] r8002 - in pypy/branch/src-pytest/pypy: . objspace/std/test tool Message-ID: <20041227155210.DA3A55A1D3@thoth.codespeak.net> Author: arigo Date: Mon Dec 27 16:52:10 2004 New Revision: 8002 Modified: pypy/branch/src-pytest/pypy/conftest.py pypy/branch/src-pytest/pypy/objspace/std/test/test_intobject.py pypy/branch/src-pytest/pypy/tool/pytestsupport.py Log: A replacement for self.assertEquals_w(): self.space.raises_w(). This check-in includes the translated version of test_intobject.py. Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Mon Dec 27 16:52:10 2004 @@ -37,6 +37,7 @@ pytestsupport.build_pytest_assertion(space)) space.setitem(space.w_builtins, space.wrap('raises'), space.wrap(pytestsupport.app_raises)) + space.raises_w = pytestsupport.raises_w.__get__(space) return space # Modified: pypy/branch/src-pytest/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/branch/src-pytest/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/branch/src-pytest/pypy/objspace/std/test/test_intobject.py Mon Dec 27 16:52:10 2004 @@ -2,15 +2,10 @@ import autopath from pypy.objspace.std import intobject as iobj from pypy.objspace.std.objspace import FailedToImplement -from pypy.tool import testit -class TestW_IntObject(testit.TestCase): +objspacename = 'std' - def setUp(self): - self.space = testit.objspace('std') - - def tearDown(self): - pass +class TestW_IntObject: def _longshiftresult(self, x): """ calculate an overflowing shift """ @@ -35,19 +30,19 @@ x = 1 f1 = iobj.W_IntObject(self.space, x) result = iobj.repr__Int(self.space, f1) - self.assertEquals(self.space.unwrap(result), repr(x)) + assert self.space.unwrap(result) == repr(x) def test_str(self): x = 12345 f1 = iobj.W_IntObject(self.space, x) result = iobj.str__Int(self.space, f1) - self.assertEquals(self.space.unwrap(result), str(x)) + assert self.space.unwrap(result) == str(x) def test_hash(self): x = 42 f1 = iobj.W_IntObject(self.space, x) result = iobj.hash__Int(self.space, f1) - self.assertEquals(result.intval, hash(x)) + assert result.intval == hash(x) def test_compare(self): import operator @@ -60,7 +55,7 @@ res = getattr(operator, op)(x, y) method = getattr(iobj, '%s__Int_Int' % op) myres = method(self.space, wx, wy) - self.assertEquals(self.space.unwrap(myres), res) + assert self.space.unwrap(myres) == res def test_add(self): x = 1 @@ -68,12 +63,12 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) result = iobj.add__Int_Int(self.space, f1, f2) - self.assertEquals(result.intval, x+y) + assert result.intval == x+y x = sys.maxint y = 1 f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.add__Int_Int, self.space, f1, f2)) def test_sub(self): @@ -82,12 +77,12 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) result = iobj.sub__Int_Int(self.space, f1, f2) - self.assertEquals(result.intval, x-y) + assert result.intval == x-y x = sys.maxint y = -1 f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.sub__Int_Int, self.space, f1, f2)) def test_mul(self): @@ -96,12 +91,12 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) result = iobj.mul__Int_Int(self.space, f1, f2) - self.assertEquals(result.intval, x*y) + assert result.intval == x*y x = -sys.maxint-1 y = -1 f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.mul__Int_Int, self.space, f1, f2)) def test_div(self): @@ -110,12 +105,12 @@ f1 = iobj.W_IntObject(self.space, i) f2 = iobj.W_IntObject(self.space, 3) result = iobj.div__Int_Int(self.space, f1, f2) - self.assertEquals(result.intval, res) + assert result.intval == res x = -sys.maxint-1 y = -1 f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.div__Int_Int, self.space, f1, f2)) def test_mod(self): @@ -124,7 +119,7 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) v = iobj.mod__Int_Int(self.space, f1, f2) - self.assertEquals(v.intval, x % y) + assert v.intval == x % y # not that mod cannot overflow def test_divmod(self): @@ -134,12 +129,12 @@ f2 = iobj.W_IntObject(self.space, y) ret = iobj.divmod__Int_Int(self.space, f1, f2) v, w = self.space.unwrap(ret) - self.assertEquals((v, w), divmod(x, y)) + assert (v, w) == divmod(x, y) x = -sys.maxint-1 y = -1 f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.divmod__Int_Int, self.space, f1, f2)) def test_pow_iii(self): @@ -150,13 +145,13 @@ f2 = iobj.W_IntObject(self.space, y) f3 = iobj.W_IntObject(self.space, z) v = iobj.pow__Int_Int_Int(self.space, f1, f2, f3) - self.assertEquals(v.intval, pow(x, y, z)) + assert v.intval == pow(x, y, z) f1, f2, f3 = [iobj.W_IntObject(self.space, i) for i in (10, -1, 42)] - self.assertRaises_w(self.space.w_TypeError, + self.space.raises_w(self.space.w_TypeError, iobj.pow__Int_Int_Int, self.space, f1, f2, f3) f1, f2, f3 = [iobj.W_IntObject(self.space, i) for i in (10, 5, 0)] - self.assertRaises_w(self.space.w_ValueError, + self.space.raises_w(self.space.w_ValueError, iobj.pow__Int_Int_Int, self.space, f1, f2, f3) @@ -166,50 +161,50 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) v = iobj.pow__Int_Int_None(self.space, f1, f2, self.space.w_None) - self.assertEquals(v.intval, x ** y) + assert v.intval == x ** y f1, f2 = [iobj.W_IntObject(self.space, i) for i in (10, 20)] - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.pow__Int_Int_None, self.space, f1, f2, self.space.w_None)) def test_neg(self): x = 42 f1 = iobj.W_IntObject(self.space, x) v = iobj.neg__Int(self.space, f1) - self.assertEquals(v.intval, -x) + assert v.intval == -x x = -sys.maxint-1 f1 = iobj.W_IntObject(self.space, x) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.neg__Int, self.space, f1)) def test_pos(self): x = 42 f1 = iobj.W_IntObject(self.space, x) v = iobj.pos__Int(self.space, f1) - self.assertEquals(v.intval, +x) + assert v.intval == +x x = -42 f1 = iobj.W_IntObject(self.space, x) v = iobj.pos__Int(self.space, f1) - self.assertEquals(v.intval, +x) + assert v.intval == +x def test_abs(self): x = 42 f1 = iobj.W_IntObject(self.space, x) v = iobj.abs__Int(self.space, f1) - self.assertEquals(v.intval, abs(x)) + assert v.intval == abs(x) x = -42 f1 = iobj.W_IntObject(self.space, x) v = iobj.abs__Int(self.space, f1) - self.assertEquals(v.intval, abs(x)) + assert v.intval == abs(x) x = -sys.maxint-1 f1 = iobj.W_IntObject(self.space, x) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.abs__Int, self.space, f1)) def test_invert(self): x = 42 f1 = iobj.W_IntObject(self.space, x) v = iobj.invert__Int(self.space, f1) - self.assertEquals(v.intval, ~x) + assert v.intval == ~x def test_lshift(self): x = 12345678 @@ -217,11 +212,11 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) v = iobj.lshift__Int_Int(self.space, f1, f2) - self.assertEquals(v.intval, x << y) + assert v.intval == x << y y = self._longshiftresult(x) f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) - self.assertEquals(self.space.w_OverflowError, + assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.lshift__Int_Int, self.space, f1, f2)) def test_rshift(self): @@ -230,7 +225,7 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) v = iobj.rshift__Int_Int(self.space, f1, f2) - self.assertEquals(v.intval, x >> y) + assert v.intval == x >> y def test_and(self): x = 12345678 @@ -238,7 +233,7 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) v = iobj.and__Int_Int(self.space, f1, f2) - self.assertEquals(v.intval, x & y) + assert v.intval == x & y def test_xor(self): x = 12345678 @@ -246,7 +241,7 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) v = iobj.xor__Int_Int(self.space, f1, f2) - self.assertEquals(v.intval, x ^ y) + assert v.intval == x ^ y def test_or(self): x = 12345678 @@ -254,12 +249,12 @@ f1 = iobj.W_IntObject(self.space, x) f2 = iobj.W_IntObject(self.space, y) v = iobj.or__Int_Int(self.space, f1, f2) - self.assertEquals(v.intval, x | y) + assert v.intval == x | y def test_int(self): f1 = iobj.W_IntObject(self.space, 1) result = iobj.int__Int(self.space, f1) - self.assertEquals(result, f1) + assert result == f1 ## def test_long(self): ## x = 1 @@ -277,38 +272,36 @@ x = 012345 f1 = iobj.W_IntObject(self.space, x) result = iobj.oct__Int(self.space, f1) - self.assertEquals(self.space.unwrap(result), oct(x)) + assert self.space.unwrap(result) == oct(x) def test_hex(self): x = 0x12345 f1 = iobj.W_IntObject(self.space, x) result = iobj.hex__Int(self.space, f1) - self.assertEquals(self.space.unwrap(result), hex(x)) + assert self.space.unwrap(result) == hex(x) -class AppIntTest(testit.AppTestCase): - def setUp(self): - self.space = testit.objspace('std') +class AppTestInt: def test_int_callable(self): - self.assertEquals(42, int(42)) + assert 43 == int(43) def test_int_string(self): - self.assertEquals(42, int("42")) - self.assertEquals(10000000000, long("10000000000")) + assert 42 == int("42") + assert 10000000000 == long("10000000000") def test_int_float(self): - self.assertEquals(4, int(4.2)) + assert 4 == int(4.2) def test_int_str_repr(self): - self.assertEquals("42", str(42)) - self.assertEquals("42", repr(42)) - self.assertRaises(ValueError, int, '0x2A') + assert "42" == str(42) + assert "42" == repr(42) + raises(ValueError, int, '0x2A') def test_int_two_param(self): - self.assertEquals(42, int('0x2A', 0)) - self.assertEquals(42, int('2A', 16)) - self.assertEquals(42, int('42', 10)) - self.assertRaises(TypeError, int, 1, 10) + assert 42 == int('0x2A', 0) + assert 42 == int('2A', 16) + assert 42 == int('42', 10) + raises(TypeError, int, 1, 10) def test_shift_zeros(self): assert (1 << 0) == 1 @@ -317,10 +310,7 @@ def test_overflow(self): import sys n = sys.maxint + 1 - self.assert_(isinstance(n, long)) + assert isinstance(n, long) def test_pow(self): - self.assertEquals(pow(2, -10), 1/1024.) - -if __name__ == '__main__': - testit.main() + assert pow(2, -10) == 1/1024. Modified: pypy/branch/src-pytest/pypy/tool/pytestsupport.py ============================================================================== --- pypy/branch/src-pytest/pypy/tool/pytestsupport.py (original) +++ pypy/branch/src-pytest/pypy/tool/pytestsupport.py Mon Dec 27 16:52:10 2004 @@ -144,3 +144,14 @@ space.wrap("DID NOT RAISE")) app_raises = interp2app_temp(pypyraises) + +def raises_w(space, w_ExpectedException, *args, **kwds): + try: + excinfo = py.test.raises(OperationError, *args, **kwds) + type, value, tb = excinfo._excinfo + if not value.match(space, w_ExpectedException): + raise type, value, tb + return excinfo + except py.test.Item.ExceptionFailure, e: + e.tbindex = getattr(e, 'tbindex', -1) - 1 + raise From alastair at codespeak.net Thu Dec 30 05:46:17 2004 From: alastair at codespeak.net (alastair at codespeak.net) Date: Thu, 30 Dec 2004 05:46:17 +0100 (MET) Subject: [pypy-svn] r8006 - pypy/trunk/doc/funding/negotiations/amendment Message-ID: <20041230044617.A5C245AACF@thoth.codespeak.net> Author: alastair Date: Thu Dec 30 05:46:16 2004 New Revision: 8006 Added: pypy/trunk/doc/funding/negotiations/amendment/Amendment Cover Letter.sxw (contents, props changed) pypy/trunk/doc/funding/negotiations/amendment/Amendment Explanation.sxw (contents, props changed) Log: Added letters to be sent with the amendment. Added: pypy/trunk/doc/funding/negotiations/amendment/Amendment Cover Letter.sxw ============================================================================== Binary file. No diff available. Added: pypy/trunk/doc/funding/negotiations/amendment/Amendment Explanation.sxw ============================================================================== Binary file. No diff available. From arigo at codespeak.net Thu Dec 30 09:53:54 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 30 Dec 2004 09:53:54 +0100 (MET) Subject: [pypy-svn] r8007 - pypy/branch/src-pytest/pypy/interpreter/test Message-ID: <20041230085354.A0D0B5AA08@thoth.codespeak.net> Author: arigo Date: Thu Dec 30 09:53:53 2004 New Revision: 8007 Modified: pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py Log: Reverted the previous check-in, which looked accidental (?). Modified: pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/branch/src-pytest/pypy/interpreter/test/test_interpreter.py Thu Dec 30 09:53:53 2004 @@ -255,3 +255,6 @@ finally: sys.stdout = save + def test_identity(self): + def f(x): return x + assert f(666) == 666 From arigo at codespeak.net Thu Dec 30 09:54:59 2004 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 30 Dec 2004 09:54:59 +0100 (MET) Subject: [pypy-svn] r8008 - pypy/branch/src-pytest/pypy Message-ID: <20041230085459.62DF95AA08@thoth.codespeak.net> Author: arigo Date: Thu Dec 30 09:54:58 2004 New Revision: 8008 Modified: pypy/branch/src-pytest/pypy/conftest.py Log: Ouack! Buggy line, wrong fix in the previous revision. The app_xxx() global functions were accidentally run at inter-level! Modified: pypy/branch/src-pytest/pypy/conftest.py ============================================================================== --- pypy/branch/src-pytest/pypy/conftest.py (original) +++ pypy/branch/src-pytest/pypy/conftest.py Thu Dec 30 09:54:58 2004 @@ -100,7 +100,7 @@ name = target.func_globals.get('objspacename', None) space = gettestobjspace(name) func = app2interp_temp(target, target.__name__) - self.execute_in_space(space, target) + self.execute_in_space(space, func, space) class IntTestMethod(PyPyItem): def execute(self, target, *args): From lac at codespeak.net Thu Dec 30 19:35:39 2004 From: lac at codespeak.net (lac at codespeak.net) Date: Thu, 30 Dec 2004 19:35:39 +0100 (MET) Subject: [pypy-svn] r8011 - pypy/trunk/doc Message-ID: <20041230183539.027E15B184@thoth.codespeak.net> Author: lac Date: Thu Dec 30 19:35:34 2004 New Revision: 8011 Added: pypy/trunk/doc/to_edu_sig.txt Log: Ok, made it a doc so that other people can edit as well. Remember it is an email reply, and don't worry about formatting gorp that makes it look stupid on the website. If we want to make a website version, we can do that then. Laura Added: pypy/trunk/doc/to_edu_sig.txt ============================================================================== --- (empty file) +++ pypy/trunk/doc/to_edu_sig.txt Thu Dec 30 19:35:34 2004 @@ -0,0 +1,79 @@ +Happy New Year, Dethe! Thank you for your interest. You write: + +>PyPy uses a similar approach to Pyrex, called Psyco, which compiles +>directly to 80x86 machine code (Pyrex compiles to cross-platform C +>code). This allows PyPy to attempt to be faster than C-Python by +>creating compiler optimizations. Not sure what the PyPy story is for +>non-x86 platforms. There is also a project to recreate Python on top +>of Smalltalk, by L. Peter Deutch, which he expects to be faster than +>C-Python (and if anyone can do it, he could). +> +>Nice to see y'all again. Happy New Year (or Gnu Year?). +> +>--Dethe +> + +I'd like to clarify a few misunderstandings I think you have. Psyco +is not a technique, but rather a specialising compiler available as a +Python extension module. It compiles directly to 386 machine +code. PyPy, on the other hand, currently emits C code. Our previous +version emitted Pyrex code. Some people in Korea are making a version +that emits Lisp code. PyPy doesn't use Psyco, though many ideas are +common to both. + +What's more there is nothing magic about machine code that makes it +automatically fast -- an inefficiently-coded algorithm in assembler is +still a turtle. The win in using PyPy is not about 'saving the time +it takes to have a conversation with your C compiler', but instead +about making such conversations more productive and useful. The more +information you can tell your C compiler about your data, the better +code it is prepared to generate. This is the tradeoff between +flexibility and speed. + +When your Python system sees x = a + b it has no clue as to what types +a and b are. They could be anything. This 'being ready to handle +everything' has a large performance penalty. The runtime system has +to do be prepared to do a _lot_, so it has to be fairly intelligent. +All this intelligence is in the form of code instructions, and there +are a lot of them that the runtime system has to execute, every time +it wants to do anything at all. On the other hand, at code _reading_ +time, the Python interpreter is purposefully stupid-but-straightforward. +It doesn't have much to do, and so can be relatively quick about not doing it. + +A statically-typed compiled language works in precisely the other way. +When the runtime system of a statically typed language sees x = a + b, +it already knows all about x, a and b and their types. All the hard +work was done in the compiling phase. There is very little left to +worry about -- you might get an overflow exception or something -- but +as an oversimplification, all the runtime system of a statically typed +langauge has to know how to do is how to load and run. That's fast. + +So, one way you could speed up Python is to add type declarations, +thus simplifying the life of the runtime system. This proposed +solution is more than a little drastic for those of us who like duck +typing, signature based polymorphism, and the particular way coding in +Python makes you think and feel. + +The PyPy alternative is to make the interpreter even smarter, and a +whole lot better at remembering what it is doing. For instance, when +it sees x = a + b instead of just adding this particular int to this +particular int, it could generate some general purpose code for adding +ints to ints. This code could be thus used for all ints that you wish +to add this way. So while the first time is slow, the _next_ time +will be a lot faster. And that is where the performance speedup +happens -- in code where the same lines get run again, and again, and +again. If all you have is a mainline where each line of code gets +executed once, then we won't help you at all. + +Psyco is about as far as you can get with this approach and be left +with a module you can import and use with regular python 2.2 or +better. See: http://psyco.sourceforge.net/ PyPy is what you get when +you pitch the old interpreter and write your own. See: +http://codespeak.net/pypy/ + +And we should probably move further disussion to pypy-dev, here: +http://codespeak.net/mailman/listinfo/pypy-dev + +Thanks for your interest, and thanks for writing, +Laura Creighton (for PyPy) + From lac at codespeak.net Thu Dec 30 19:42:51 2004 From: lac at codespeak.net (lac at codespeak.net) Date: Thu, 30 Dec 2004 19:42:51 +0100 (MET) Subject: [pypy-svn] r8012 - pypy/trunk/doc Message-ID: <20041230184251.25DFD5A6D9@thoth.codespeak.net> Author: lac Date: Thu Dec 30 19:42:47 2004 New Revision: 8012 Modified: pypy/trunk/doc/to_edu_sig.txt Log: See if this makes the original quoted mail less ugly to read. Modified: pypy/trunk/doc/to_edu_sig.txt ============================================================================== --- pypy/trunk/doc/to_edu_sig.txt (original) +++ pypy/trunk/doc/to_edu_sig.txt Thu Dec 30 19:42:47 2004 @@ -1,17 +1,17 @@ Happy New Year, Dethe! Thank you for your interest. You write: ->PyPy uses a similar approach to Pyrex, called Psyco, which compiles ->directly to 80x86 machine code (Pyrex compiles to cross-platform C ->code). This allows PyPy to attempt to be faster than C-Python by ->creating compiler optimizations. Not sure what the PyPy story is for ->non-x86 platforms. There is also a project to recreate Python on top ->of Smalltalk, by L. Peter Deutch, which he expects to be faster than ->C-Python (and if anyone can do it, he could). -> ->Nice to see y'all again. Happy New Year (or Gnu Year?). -> ->--Dethe -> + >PyPy uses a similar approach to Pyrex, called Psyco, which compiles + >directly to 80x86 machine code (Pyrex compiles to cross-platform C + >code). This allows PyPy to attempt to be faster than C-Python by + >creating compiler optimizations. Not sure what the PyPy story is for + >non-x86 platforms. There is also a project to recreate Python on top + >of Smalltalk, by L. Peter Deutch, which he expects to be faster than + >C-Python (and if anyone can do it, he could). + > + >Nice to see y'all again. Happy New Year (or Gnu Year?). + > + >--Dethe + > I'd like to clarify a few misunderstandings I think you have. Psyco is not a technique, but rather a specialising compiler available as a From lac at codespeak.net Thu Dec 30 19:46:11 2004 From: lac at codespeak.net (lac at codespeak.net) Date: Thu, 30 Dec 2004 19:46:11 +0100 (MET) Subject: [pypy-svn] r8013 - pypy/trunk/doc Message-ID: <20041230184611.879A15A6D9@thoth.codespeak.net> Author: lac Date: Thu Dec 30 19:46:08 2004 New Revision: 8013 Modified: pypy/trunk/doc/to_edu_sig.txt Log: more beautification. I need the 'do not format this' directive, and forget what this is. Modified: pypy/trunk/doc/to_edu_sig.txt ============================================================================== --- pypy/trunk/doc/to_edu_sig.txt (original) +++ pypy/trunk/doc/to_edu_sig.txt Thu Dec 30 19:46:08 2004 @@ -1,17 +1,17 @@ Happy New Year, Dethe! Thank you for your interest. You write: - >PyPy uses a similar approach to Pyrex, called Psyco, which compiles - >directly to 80x86 machine code (Pyrex compiles to cross-platform C - >code). This allows PyPy to attempt to be faster than C-Python by - >creating compiler optimizations. Not sure what the PyPy story is for - >non-x86 platforms. There is also a project to recreate Python on top - >of Smalltalk, by L. Peter Deutch, which he expects to be faster than - >C-Python (and if anyone can do it, he could). - > - >Nice to see y'all again. Happy New Year (or Gnu Year?). - > - >--Dethe - > + >PyPy uses a similar approach to Pyrex, called Psyco, which compiles + >directly to 80x86 machine code (Pyrex compiles to cross-platform C + >code). This allows PyPy to attempt to be faster than C-Python by + >creating compiler optimizations. Not sure what the PyPy story is for + >non-x86 platforms. There is also a project to recreate Python on top + >of Smalltalk, by L. Peter Deutch, which he expects to be faster than + >C-Python (and if anyone can do it, he could). + + >Nice to see y'all again. Happy New Year (or Gnu Year?). + + x>--Dethe + I'd like to clarify a few misunderstandings I think you have. Psyco is not a technique, but rather a specialising compiler available as a