From: <zy...@us...> - 2007-08-23 04:57:10
|
Revision: 3447 http://jython.svn.sourceforge.net/jython/?rev=3447&view=rev Author: zyasoft Date: 2007-08-22 21:57:07 -0700 (Wed, 22 Aug 2007) Log Message: ----------- Added relational algebra test, based on Jim's cookbook recipe, to test generator expressions Modified Paths: -------------- branches/newcompiler/PyASM/test/with.py Added Paths: ----------- branches/newcompiler/PyASM/new_itertools.py branches/newcompiler/PyASM/new_operator.py branches/newcompiler/PyASM/test/relalg.py Added: branches/newcompiler/PyASM/new_itertools.py =================================================================== --- branches/newcompiler/PyASM/new_itertools.py (rev 0) +++ branches/newcompiler/PyASM/new_itertools.py 2007-08-23 04:57:07 UTC (rev 3447) @@ -0,0 +1,57 @@ +import itertools as base_it + +count = base_it.count +cycle = base_it.cycle +dropwhile = base_it.dropwhile +ifilter = base_it.ifilter +ifilterfalse = base_it.ifilterfalse +imap = base_it.imap +islice = base_it.islice +izip = base_it.izip +repeat = base_it.repeat +starmap = base_it.starmap +takewhile = base_it.takewhile + +def chain(*iterables): + for it in iterables: + for element in it: + yield element + +class groupby(object): + def __init__(self, iterable, key=None): + if key is None: + key = lambda x: x + self.keyfunc = key + self.it = iter(iterable) + self.tgtkey = self.currkey = self.currvalue = xrange(0) + def __iter__(self): + return self + def next(self): + while self.currkey == self.tgtkey: + self.currvalue = self.it.next() # Exit on StopIteration + self.currkey = self.keyfunc(self.currvalue) + self.tgtkey = self.currkey + return (self.currkey, self._grouper(self.tgtkey)) + def _grouper(self, tgtkey): + while self.currkey == tgtkey: + yield self.currvalue + self.currvalue = self.it.next() # Exit on StopIteration + self.currkey = self.keyfunc(self.currvalue) + +def izip(*iterables): + iterables = map(iter, iterables) + while iterables: + result = [it.next() for it in iterables] + yield tuple(result) + +def tee(iterable): + def gen(next, data={}, cnt=[0]): + for i in count(): + if i == cnt[0]: + item = data[i] = next() + cnt[0] += 1 + else: + item = data.pop(i) + yield item + it = iter(iterable) + return (gen(it.next), gen(it.next)) Added: branches/newcompiler/PyASM/new_operator.py =================================================================== --- branches/newcompiler/PyASM/new_operator.py (rev 0) +++ branches/newcompiler/PyASM/new_operator.py 2007-08-23 04:57:07 UTC (rev 3447) @@ -0,0 +1,9 @@ +import operator as base_op + +concat = base_op.concat +eq = base_op.eq + +def itemgetter(*args): + def f(item): + return item[args[0]] + Added: branches/newcompiler/PyASM/test/relalg.py =================================================================== --- branches/newcompiler/PyASM/test/relalg.py (rev 0) +++ branches/newcompiler/PyASM/test/relalg.py 2007-08-23 04:57:07 UTC (rev 3447) @@ -0,0 +1,241 @@ +""" +Iterator algebra implementations of join algorithms: hash join, merge +join, and nested loops join, as well as a variant I dub "bisect join". + +Requires Python 2.4. + +Author: Jim Baker, jb...@zy... + +Define some relations to join: +>>> accounts = [ +... ('spender', 'Big', 'Spender', '123-456-7890'), +... ('saver', 'Thrifty', 'Saver', '234-567-8901'), +... ('nobody', 'A', 'Nobody', '999-999-9999')] +>>> transactions = [ +... ('spender', 'deposited', 100), +... ('spender', 'withdraw', 40), +... ('spender', 'withdraw', 15), +... ('spender', 'withdraw', 25), +... ('saver', 'deposited', 30)] + +Given the above data, a useful join predicate is the first element of +each tuple. This will give us a usable equijoin: +>>> def first(x): return x[0] + +Test that the implemented join methods are equivalent: +>>> nj = set(nested_loops_join(accounts, transactions, first)) +>>> hj = set(hash_join(accounts, transactions, first)) +>>> bj = set(bisect_join(accounts, transactions, first)) +>>> nj == hj +True +>>> bj == hj +True + +Perform a Cartesian join. In this case, we need a predicate that +returns the same value for every tuple, so in this case returning True +is arbitrary: +>>> def always(x): return True + +With 5 tuples in transactions and 3 tuples in accounts, we should get +15 tuples: +>>> len(list(hash_join(accounts, transactions, always))) +15 + +With semijoins and outer joins, we now see the power of the +iterator approach. A left join will return a tuple even if there is +not a match on the predicate: +>>> lj = set(hash_join(accounts, transactions, first, +... join=lambda X: left(X, when_empty=tuple([None]*3)))) +>>> len(lj) +6 + +A full outer join is simply the union of a left join and a right +join. Let's make a right join by reversing the order of the join. We +will also to need to reverse how we combine the tuples: +>>> rj = set(nested_loops_join(transactions, accounts, first, +... combine=lambda r, s: s + r, +... join=lambda X: left(X, when_empty=tuple([None]*2)))) +>>> len(rj) +5 + +Note that we have no activity in this example without an accompanying +account, so it's the same as an inner join. Now let's compute the full +outer join: +>>> foj = lj | rj +>>> len(foj) +6 + +A semijoin will return only the first matching tuple: +>>> len(list(hash_join(accounts, transactions, first, semi))) +2 + + +Semijoins are useful, especially in conjunction with hierarchical +queries. In SQL, if supported, they are the efficient alternative to +writing 'select distinct', although they make one's code difficult to +understand by the unversed. Hopefully showing this with procedural +code can make this useful feature less mysterious. + +""" + +import new_operator as operator +import sets.Set as set + +def sorted(X): + temp = list(X) + temp.sort() + return temp + +def identity(x): + """x -> x + + As a predicate, this function is useless, but it provides a + useful/correct default. + + >>> identity(('apple', 'banana', 'cherry')) + ('apple', 'banana', 'cherry') + """ + return x + +def inner(X): + """ + >>> X = [1, 2, 3, 4, 5] + >>> list(inner(X)) + [1, 2, 3, 4, 5] + """ + for x in X: + yield x + +def semi(X): + """Returns X[0] if X is not empty + + >>> X = [1, 2, 3, 4, 5] + >>> list(semi(X)) + [1] + """ + + for x in X: + yield x + break + +def left(X, when_empty=()): + empty = True + for x in X: + yield x + empty = False + if empty: + yield when_empty + + +# Xp can mean X-prime or X-with-predicate; we use both meanings +# interchangeably here in the shorthand of this code. +# Xp -> (p(x0), x0), (p(x1), x1), ... + +# throughout, we assume S is the smaller relation of R and S. + +def hash_join(R, S, predicate=identity, join=inner, combine=operator.concat): + hashed = {} + for s in S: + hashed.setdefault(predicate(s),[]).append(s) + for r in R: + for s in join(hashed.get(predicate(r),())): + yield combine(r, s) + +def nested_loops_join(R, S, predicate=identity, join=inner, + combine=operator.concat, theta=operator.eq): + Sp = [(predicate(s), s) for s in S] + for r in R: + rp = predicate(r) + for s in join(s for sp, s in Sp if theta(rp, sp)): + yield combine(r, s) + +def bisect_join(R, S, predicate=identity, join=inner, combine=operator.concat): + """ + I have not found discussion of this variant on the sort-merge join anywhere. + """ + + from bisect import bisect_left + + def consume(Sp, si, rp): + """This needs a better name...""" + length = len(S) + while si < length: + sp, s = Sp[si] + if rp == sp: + yield s + else: + break + si += 1 + + Rp = sorted((predicate(r), r) for r in R) + Sp = sorted((predicate(s), s) for s in S) + + for rp, r in Rp: + si = bisect_left(Sp, (rp,)) + for s in join(consume(Sp, si, rp)): + yield combine(r, s) + + +def merge_join(R, S, predicate=identity, join=inner, combine=operator.concat): + """ + For obvious reasons, we depend on the predicate providing a + sortable relation. + + Compare this presentation using iterator algebra with the much + more difficult to follow presentation (IMHO) in + http://en.wikipedia.org/wiki/Sort-Merge_Join + """ + + from new_itertools import groupby + + def advancer(Xp): + """A simple wrapper of itertools.groupby, we simply need + to follow our convention that Xp -> (xp0, x0), (xp1, x1), ... + """ + + for k, g in groupby(Xp, key=operator.itemgetter(0)): + yield k, list(g) + + R_grouped = advancer(sorted((predicate(r), r) for r in R)) + S_grouped = advancer(sorted((predicate(s), s) for s in S)) + + # in the join we need to distinguish rp from rk in the unpack, so + # just use rk, sk + rk, R_matched = R_grouped.next() + sk, S_matched = S_grouped.next() + + while R_grouped and S_grouped: + comparison = cmp(rk, sk) + if comparison == 0: + # standard Cartesian join here on the matched tuples, as + # subsetted by the join method + for rp, r in R_matched: + for sp, s in join(S_matched): + yield combine(r, s) + rk, R_matched = R_grouped.next() + sk, S_matched = S_grouped.next() + elif comparison > 0: + sk, S_matched = S_grouped.next() + else: + rk, R_matched = R_grouped.next() + + +if __name__ == "__main__": + accounts = [ + ('spender', 'Big', 'Spender', '123-456-7890'), + ('saver', 'Thrifty', 'Saver', '234-567-8901'), + ('nobody', 'A', 'Nobody', '999-999-9999')] + transactions = [ + ('spender', 'deposited', 100), + ('spender', 'withdraw', 40), + ('spender', 'withdraw', 15), + ('spender', 'withdraw', 25), + ('saver', 'deposited', 30)] + + def first(x): return x[0] + + print 'NJ', set(nested_loops_join(accounts, transactions, first)) + print 'HJ', set(hash_join(accounts, transactions, first)) + print 'BJ', set(bisect_join(accounts, transactions, first)) + print 'MJ', set(merge_join(accounts, transactions, first)) + Modified: branches/newcompiler/PyASM/test/with.py =================================================================== --- branches/newcompiler/PyASM/test/with.py 2007-08-22 22:10:51 UTC (rev 3446) +++ branches/newcompiler/PyASM/test/with.py 2007-08-23 04:57:07 UTC (rev 3447) @@ -1,6 +1,6 @@ from __future__ import with_statement -print "with_statement:", with_statement +#print "with_statement:", with_statement class ContextGuard(object): def __init__(self, name, ret): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2007-08-23 08:45:03
|
Revision: 3449 http://jython.svn.sourceforge.net/jython/?rev=3449&view=rev Author: thobes Date: 2007-08-23 01:45:01 -0700 (Thu, 23 Aug 2007) Log Message: ----------- fixed a bug for calling functions with keyword-parameters. Modified Paths: -------------- branches/newcompiler/PyASM/pyasm.py branches/newcompiler/PyASM/test/call.py Modified: branches/newcompiler/PyASM/pyasm.py =================================================================== --- branches/newcompiler/PyASM/pyasm.py 2007-08-23 08:29:05 UTC (rev 3448) +++ branches/newcompiler/PyASM/pyasm.py 2007-08-23 08:45:01 UTC (rev 3449) @@ -134,7 +134,7 @@ ) self.cv = self.__cw #self.cv = InlineingClassVisitor(self.cv) - #self.cv = asm.util.TraceClassVisitor(self.cv, stdout) + self.cv = asm.util.TraceClassVisitor(self.cv, stdout) #self.cv = OffsetTracer(self.cv, stdout) self.cv = asm.util.CheckClassAdapter(self.cv) self.cv.visit(Op.V1_4, Op.ACC_PUBLIC, name, None, @@ -888,6 +888,8 @@ self.push(num_pos + i) self.asm.swap() self.asm.arrayStore(pyObjectType) + self.asm.invokeVirtual(pyObjectType, Method.getMethod( + "String toString ()")) keywords.load() self.asm.swap() self.push(i) Modified: branches/newcompiler/PyASM/test/call.py =================================================================== --- branches/newcompiler/PyASM/test/call.py 2007-08-23 08:29:05 UTC (rev 3448) +++ branches/newcompiler/PyASM/test/call.py 2007-08-23 08:45:01 UTC (rev 3449) @@ -1,4 +1,10 @@ def a(b,c): None -a(1,2) +a(1,c=2) +a(*[1,2]) +a(**dict(b=1,c=2)) +a(*[1],**dict(c=2)) +a(c=1,*[2]) +a(b=1,**dict(c=2)) +a(1,2,*[],**dict()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2007-08-24 10:03:14
|
Revision: 3454 http://jython.svn.sourceforge.net/jython/?rev=3454&view=rev Author: thobes Date: 2007-08-24 03:03:10 -0700 (Fri, 24 Aug 2007) Log Message: ----------- fixed an error in a test case Modified Paths: -------------- branches/newcompiler/PyASM/new_operator.py branches/newcompiler/PyASM/test/relalg.py Modified: branches/newcompiler/PyASM/new_operator.py =================================================================== --- branches/newcompiler/PyASM/new_operator.py 2007-08-24 07:02:54 UTC (rev 3453) +++ branches/newcompiler/PyASM/new_operator.py 2007-08-24 10:03:10 UTC (rev 3454) @@ -6,4 +6,5 @@ def itemgetter(*args): def f(item): return item[args[0]] + return f Modified: branches/newcompiler/PyASM/test/relalg.py =================================================================== --- branches/newcompiler/PyASM/test/relalg.py 2007-08-24 07:02:54 UTC (rev 3453) +++ branches/newcompiler/PyASM/test/relalg.py 2007-08-24 10:03:10 UTC (rev 3454) @@ -78,8 +78,11 @@ """ -import new_operator as operator -import sets.Set as set +import os +if os.name == 'java': + import new_operator as operator +else: + import operator def sorted(X): temp = list(X) @@ -186,7 +189,10 @@ http://en.wikipedia.org/wiki/Sort-Merge_Join """ - from new_itertools import groupby + if os.name == 'java': + from new_itertools import groupby + else: + from itertools import groupby def advancer(Xp): """A simple wrapper of itertools.groupby, we simply need @@ -204,7 +210,7 @@ rk, R_matched = R_grouped.next() sk, S_matched = S_grouped.next() - while R_grouped and S_grouped: + while True: comparison = cmp(rk, sk) if comparison == 0: # standard Cartesian join here on the matched tuples, as This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2007-10-16 21:40:58
|
Revision: 3608 http://jython.svn.sourceforge.net/jython/?rev=3608&view=rev Author: thobes Date: 2007-10-16 14:40:56 -0700 (Tue, 16 Oct 2007) Log Message: ----------- Created a wrapper for jython that enables importing of pyc-files. Modified Paths: -------------- branches/newcompiler/PyASM/pyasm.py Added Paths: ----------- branches/newcompiler/PyASM/pycimport.py Modified: branches/newcompiler/PyASM/pyasm.py =================================================================== --- branches/newcompiler/PyASM/pyasm.py 2007-10-15 23:58:22 UTC (rev 3607) +++ branches/newcompiler/PyASM/pyasm.py 2007-10-16 21:40:56 UTC (rev 3608) @@ -161,6 +161,13 @@ self.init.loadThis() self.init.invokeConstructor(Type.getType(core.PyFunctionTable), Method.getMethod("void <init> ()")) + #self.cv.visitField(Op.ACC_PUBLIC + Op.ACC_FINAL, '__file__', + # Type.getType(java.lang.String).getDescriptor(), + # None, None) + #self.init.loadThis() + #self.init.loadArg(0) + #self.init.putField(self.asType, '__file__', + # Type.getType(java.lang.String)) def isCodeConstant(self, name): Added: branches/newcompiler/PyASM/pycimport.py =================================================================== --- branches/newcompiler/PyASM/pycimport.py (rev 0) +++ branches/newcompiler/PyASM/pycimport.py 2007-10-16 21:40:56 UTC (rev 3608) @@ -0,0 +1,74 @@ +_debugging = False + +def readPycHeader(file): + def read(): + return ord(file.read(1)) + magic = read() | (read()<<8) + if not ( file.read(1) == '\r' and file.read(1) == '\n' ): + raise TypeError("not valid pyc-file") + mtime = read() | (read()<<8) | (read()<<16) | (read()<<24) + return magic, mtime + +def makeModule(name, code, path): + module = _imp.addModule(name) + frame = _Frame(code, module.__dict__, module.__dict__, None) + code.call(frame) # execute module code + module.__file__ = path + return module + +class Importer(object): + started = False # wait until dependancies are in place before useing this + def __init__(self, path): + if _debugging: print "Importer invoked" + self.__path = path + def find_module(self, fullname, path=None): + if not self.started: + return None + if _debugging: print "Importer.find_module(fullname=%s, path=%s)" % ( + repr(fullname),repr(path)) + path = fullname.split('.') + filename = path[-1] + path = path[:-1] + pycfile = os.path.join(self.__path, *(path + [filename + '.pyc'])) + pyfile = os.path.join(self.__path, *(path + [filename + '.py'])) + if os.path.exists(pycfile): + f = open(pycfile, 'rb') + try: + magic, mtime = readPycHeader(f) + except: + return None # abort! not a valid pyc-file + f.close() + if os.path.exists(pyfile): + pytime = os.stat(pyfile).st_mtime + if pytime > mtime: + return None # abort! py-file was newer + return self + else: + return None # abort! pyc-file does not exist + def load_module(self, fullname): + path = fullname.split('.') + path[-1] += '.pyc' + filename = os.path.join(self.__path, *path) + f = open(filename, 'rb') + magic, mtime = readPycHeader(f) + code = Unmarshaller(f, magic=magic).load() + return makeModule( fullname, code, filename ) + +import sys + +sys.path_hooks.append(Importer) +# Defere all the imports so that the import hooks will still be valid +import os + +if os.name == 'java': + from org.python.core import imp as _imp, PyFrame as _Frame + from marshal import Unmarshaller + +if __name__ == '__main__': + # Start Jython within Jython... with pyc-importing enabled + from org.python.util import jython + from java.lang import String + from jarray import array + Importer.started = True # Start the import hook mechanism + print "Python bytecode importing enabled" + jython.main(array(sys.argv[1:], String)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2007-10-17 11:17:06
|
Revision: 3610 http://jython.svn.sourceforge.net/jython/?rev=3610&view=rev Author: thobes Date: 2007-10-17 04:17:03 -0700 (Wed, 17 Oct 2007) Log Message: ----------- Fixed a bug in the pyc-importing subsystem that prevented it from importing modules from the module being imported. Modified Paths: -------------- branches/newcompiler/PyASM/marshal.py branches/newcompiler/PyASM/pycimport.py Modified: branches/newcompiler/PyASM/marshal.py =================================================================== --- branches/newcompiler/PyASM/marshal.py 2007-10-17 09:05:07 UTC (rev 3609) +++ branches/newcompiler/PyASM/marshal.py 2007-10-17 11:17:03 UTC (rev 3610) @@ -351,7 +351,7 @@ def load_code(self): lastVisitor = self.__visitor visitor= _visitor= self.__visitor= CodeVisitor(self.magic, lastVisitor) - #visitor = PythonDis(visitor, stdout, False) + #visitor = PythonDis(visitor, stdout, True) try: argcount = self.read_long() nlocals = self.read_long() Modified: branches/newcompiler/PyASM/pycimport.py =================================================================== --- branches/newcompiler/PyASM/pycimport.py 2007-10-17 09:05:07 UTC (rev 3609) +++ branches/newcompiler/PyASM/pycimport.py 2007-10-17 11:17:03 UTC (rev 3610) @@ -1,12 +1,9 @@ import sys import os -from org.python.core import imp as _imp, PyFrame as _Frame +from org.python.core import imp as _imp, PyFrame as _Frame, Py as _Py from marshal import Unmarshaller -# Known issues: -# * Circular import (a module that imports itself) does not work - __debugging__ = False def __readPycHeader(file): @@ -20,7 +17,8 @@ def __makeModule(name, code, path): module = _imp.addModule(name) - frame = _Frame(code, module.__dict__, module.__dict__, None) + builtins = _Py.getSystemState().builtins + frame = _Frame(code, module.__dict__, module.__dict__, builtins) module.__file__ = path code.call(frame) # execute module code return module @@ -65,6 +63,8 @@ def __init__(self): self.__importers = {} def find_module(self, fullname, path): + if __debugging__: print "MetaImporter.find_module(%s, %s)" % ( + repr(fullname), repr(path)) for _path in sys.path: if _path not in self.__importers: try: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2007-12-17 10:43:37
|
Revision: 3831 http://jython.svn.sourceforge.net/jython/?rev=3831&view=rev Author: thobes Date: 2007-12-17 02:43:20 -0800 (Mon, 17 Dec 2007) Log Message: ----------- Added a fix for optimized loops (where the test is a constant). Plus an old test case that I found wasn't in svn. Modified Paths: -------------- branches/newcompiler/PyASM/pyasm.py Added Paths: ----------- branches/newcompiler/PyASM/test/generator_close.py branches/newcompiler/PyASM/test/loops.py Modified: branches/newcompiler/PyASM/pyasm.py =================================================================== --- branches/newcompiler/PyASM/pyasm.py 2007-12-17 07:55:21 UTC (rev 3830) +++ branches/newcompiler/PyASM/pyasm.py 2007-12-17 10:43:20 UTC (rev 3831) @@ -1095,11 +1095,12 @@ def visitForIteration(self, end): """iter -- iter value | """ self.__blocks.append(ForBlock(self.asm)) + #@self.scheduleCode(end) def code(): block = self.__blocks.pop() if not isinstance(block, ForBlock): - TypeError("Illegal block state, expected ForBlock, not %s" - % type(block)) + raise TypeError("Illegal block state, expected ForBlock, not %s" + % type(block)) block.end() self.scheduleCode(end, code) body = self.label() @@ -1545,6 +1546,14 @@ def visitSetupLoop(self, loopEnd): """ -- """ block = LoopBlock(self.asm, self.label(loopEnd)) + #@self.scheduleCode(loopEnd) + def code(): + # check for optimized loop block (with constant test expr) + if block in self.__blocks: + top = self.__blocks.pop() + if not block is top: + raise TypeError("Encountered badly terminated loop block") + self.scheduleCode(loopEnd, code) self.__blocks.append(block) def visitPopBlock(self): Added: branches/newcompiler/PyASM/test/generator_close.py =================================================================== --- branches/newcompiler/PyASM/test/generator_close.py (rev 0) +++ branches/newcompiler/PyASM/test/generator_close.py 2007-12-17 10:43:20 UTC (rev 3831) @@ -0,0 +1,17 @@ +from java.lang import System + +def gen(): + try: + yield None + except Exception, e: + print "Caught", e + raise + +it = gen() +it.next() +it.close() +it = gen() +it.next() +del it + +System.gc() Added: branches/newcompiler/PyASM/test/loops.py =================================================================== --- branches/newcompiler/PyASM/test/loops.py (rev 0) +++ branches/newcompiler/PyASM/test/loops.py 2007-12-17 10:43:20 UTC (rev 3831) @@ -0,0 +1,4 @@ +for e in xrange(5): + while 1: + break + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2007-12-17 18:05:41
|
Revision: 3834 http://jython.svn.sourceforge.net/jython/?rev=3834&view=rev Author: thobes Date: 2007-12-17 10:05:33 -0800 (Mon, 17 Dec 2007) Log Message: ----------- Renamed the test directory tests and made it a package to simplify testing with pycimport while avoiding conflict with the command line test runner. Modified Paths: -------------- branches/newcompiler/PyASM/marshal.py branches/newcompiler/PyASM/pyasm.py branches/newcompiler/PyASM/pycimport.py Added Paths: ----------- branches/newcompiler/PyASM/tests/ branches/newcompiler/PyASM/tests/__init__.py branches/newcompiler/PyASM/tests/assign.py branches/newcompiler/PyASM/tests/async_obj.py branches/newcompiler/PyASM/tests/builtins.py branches/newcompiler/PyASM/tests/call.py branches/newcompiler/PyASM/tests/call_return.py branches/newcompiler/PyASM/tests/class_simple.py branches/newcompiler/PyASM/tests/constants.py branches/newcompiler/PyASM/tests/coroutine.py branches/newcompiler/PyASM/tests/exception.py branches/newcompiler/PyASM/tests/for.py branches/newcompiler/PyASM/tests/generator.py branches/newcompiler/PyASM/tests/generator_close.py branches/newcompiler/PyASM/tests/generator_comprehension.py branches/newcompiler/PyASM/tests/generator_finally.py branches/newcompiler/PyASM/tests/generator_state.py branches/newcompiler/PyASM/tests/generator_state2.py branches/newcompiler/PyASM/tests/global.py branches/newcompiler/PyASM/tests/import.py branches/newcompiler/PyASM/tests/import_from.py branches/newcompiler/PyASM/tests/import_star.py branches/newcompiler/PyASM/tests/list.py branches/newcompiler/PyASM/tests/list_comprehension.py branches/newcompiler/PyASM/tests/loops.py branches/newcompiler/PyASM/tests/observer.py branches/newcompiler/PyASM/tests/print.py branches/newcompiler/PyASM/tests/print_chevron.py branches/newcompiler/PyASM/tests/relalg.py branches/newcompiler/PyASM/tests/return.py branches/newcompiler/PyASM/tests/scoped_exceptions.py branches/newcompiler/PyASM/tests/simple_decorator.py branches/newcompiler/PyASM/tests/simple_decorator2.py branches/newcompiler/PyASM/tests/simple_decorator_scopes.py branches/newcompiler/PyASM/tests/simple_decorator_scopes1.py branches/newcompiler/PyASM/tests/simple_decorator_scopes2.py branches/newcompiler/PyASM/tests/simple_func.py branches/newcompiler/PyASM/tests/strings.py branches/newcompiler/PyASM/tests/try.py branches/newcompiler/PyASM/tests/try_except.py branches/newcompiler/PyASM/tests/try_finally.py branches/newcompiler/PyASM/tests/try_finally_function.py branches/newcompiler/PyASM/tests/varargs.py branches/newcompiler/PyASM/tests/while.py branches/newcompiler/PyASM/tests/with.py branches/newcompiler/PyASM/tests/with_generator.py Removed Paths: ------------- branches/newcompiler/PyASM/test/ branches/newcompiler/PyASM/tests/assign.py branches/newcompiler/PyASM/tests/builtins.py branches/newcompiler/PyASM/tests/call.py branches/newcompiler/PyASM/tests/call_return.py branches/newcompiler/PyASM/tests/class_simple.py branches/newcompiler/PyASM/tests/constants.py branches/newcompiler/PyASM/tests/coroutine.py branches/newcompiler/PyASM/tests/exception.py branches/newcompiler/PyASM/tests/for.py branches/newcompiler/PyASM/tests/generator.py branches/newcompiler/PyASM/tests/generator_comprehension.py branches/newcompiler/PyASM/tests/generator_finally.py branches/newcompiler/PyASM/tests/generator_state.py branches/newcompiler/PyASM/tests/generator_state2.py branches/newcompiler/PyASM/tests/import.py branches/newcompiler/PyASM/tests/import_from.py branches/newcompiler/PyASM/tests/import_star.py branches/newcompiler/PyASM/tests/list.py branches/newcompiler/PyASM/tests/list_comprehension.py branches/newcompiler/PyASM/tests/observer.py branches/newcompiler/PyASM/tests/print.py branches/newcompiler/PyASM/tests/relalg.py branches/newcompiler/PyASM/tests/return.py branches/newcompiler/PyASM/tests/scoped_exceptions.py branches/newcompiler/PyASM/tests/simple_decorator.py branches/newcompiler/PyASM/tests/simple_decorator2.py branches/newcompiler/PyASM/tests/simple_decorator_scopes.py branches/newcompiler/PyASM/tests/simple_decorator_scopes1.py branches/newcompiler/PyASM/tests/simple_decorator_scopes2.py branches/newcompiler/PyASM/tests/simple_func.py branches/newcompiler/PyASM/tests/strings.py branches/newcompiler/PyASM/tests/try.py branches/newcompiler/PyASM/tests/try_except.py branches/newcompiler/PyASM/tests/try_finally.py branches/newcompiler/PyASM/tests/try_finally_function.py branches/newcompiler/PyASM/tests/varargs.py branches/newcompiler/PyASM/tests/while.py branches/newcompiler/PyASM/tests/with.py branches/newcompiler/PyASM/tests/with_generator.py Modified: branches/newcompiler/PyASM/marshal.py =================================================================== --- branches/newcompiler/PyASM/marshal.py 2007-12-17 17:57:34 UTC (rev 3833) +++ branches/newcompiler/PyASM/marshal.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -25,6 +25,8 @@ def byteArray(string): return array(list(string),'c') +__debugging__ = False + # marshal types mappings = dict( TYPE_NULL = ('0', 0), @@ -351,7 +353,7 @@ def load_code(self): lastVisitor = self.__visitor visitor= _visitor= self.__visitor= CodeVisitor(self.magic, lastVisitor) - #visitor = PythonDis(visitor, stdout, True) + if __debugging__: visitor = PythonDis(visitor, stdout, True) try: argcount = self.read_long() nlocals = self.read_long() Modified: branches/newcompiler/PyASM/pyasm.py =================================================================== --- branches/newcompiler/PyASM/pyasm.py 2007-12-17 17:57:34 UTC (rev 3833) +++ branches/newcompiler/PyASM/pyasm.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -18,6 +18,8 @@ from java.lang.System import out stdout = PrintWriter(out) +__debugging__ = False + def reallyContains(dct, item): if item in dct: keys = list(dct.keys()) @@ -106,6 +108,7 @@ asType = property(lambda self: Type.getType( "L%s;" % self.__name.replace('.','/'))) def __init__(self, name): + print "CLASSNAME:", name self.__name = name self.__cw = asm.ClassWriter(asm.ClassWriter.COMPUTE_MAXS # Frames need to be computed for @@ -113,12 +116,13 @@ #+ asm.ClassWriter.COMPUTE_FRAMES ) self.cv = self.__cw - ## add this line to get a printout of the generated java bytecode - #self.cv = asm.util.TraceClassVisitor(self.cv, stdout) - ## add this line to get a printout of the java bytecode with offsets - #self.cv = OffsetTracer(self.cv, stdout) - ## add this line to verify that the code generation is well behaved - #self.cv = asm.util.CheckClassAdapter(self.cv) + if __debugging__: + ## add this line to get a printout of the generated java bytecode + self.cv = asm.util.TraceClassVisitor(self.cv, stdout) + ## add this line to get a printout of the java bytecode with offsets + #self.cv = OffsetTracer(self.cv, stdout) + ## add this line to verify that the code generation is well behaved + #self.cv = asm.util.CheckClassAdapter(self.cv) self.cv.visit(Op.V1_4, Op.ACC_PUBLIC, name, None, "org/python/core/PyFunctionTable", stringArray("org/python/core/PyRunnable")) Modified: branches/newcompiler/PyASM/pycimport.py =================================================================== --- branches/newcompiler/PyASM/pycimport.py 2007-12-17 17:57:34 UTC (rev 3833) +++ branches/newcompiler/PyASM/pycimport.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -57,6 +57,7 @@ f = open(filename, 'rb') magic, mtime = __readPycHeader(f) code = Unmarshaller(f, magic=magic).load() + if __debugging__: print "Successfully loaded:", fullname return __makeModule( fullname, code, filename ) class __MetaImporter(object): Copied: branches/newcompiler/PyASM/tests (from rev 3777, branches/newcompiler/PyASM/test) Added: branches/newcompiler/PyASM/tests/__init__.py =================================================================== Deleted: branches/newcompiler/PyASM/tests/assign.py =================================================================== --- branches/newcompiler/PyASM/test/assign.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/assign.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,4 +0,0 @@ -a = 5 -b,c,d = 6,7,8 -f,g,h = a,9,b -i,(j,k),l = 1,(2,3),4 Copied: branches/newcompiler/PyASM/tests/assign.py (from rev 3833, branches/newcompiler/PyASM/test/assign.py) =================================================================== --- branches/newcompiler/PyASM/tests/assign.py (rev 0) +++ branches/newcompiler/PyASM/tests/assign.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,4 @@ +a = 5 +b,c,d = 6,7,8 +f,g,h = a,9,b +i,(j,k),l = 1,(2,3),4 Copied: branches/newcompiler/PyASM/tests/async_obj.py (from rev 3833, branches/newcompiler/PyASM/test/async_obj.py) =================================================================== --- branches/newcompiler/PyASM/tests/async_obj.py (rev 0) +++ branches/newcompiler/PyASM/tests/async_obj.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,117 @@ +from __future__ import with_statement +import new +import threading +from types import MethodType +from contextlib import contextmanager +from Queue import Queue + +# proxy support inspired by this recipe http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/519639/ + +class Future(object): + """Creates a Future on a method call, that can be used later. + + Until a client uses the reference, not just keeps it around, it + can be in an unresolved state. The use of a threading.Event + ensures that it has (atomically) been resolved. + + If the user throws away the future ;), we no longer worry + about getting the result. + """ + + def __init__(self): + self.target = None + self.event = threading.Event() + + # can I avoid this via __getattribute__ ? that would be yes, just + # a little more bookkeeping + def __str__(self): + self.event.wait() + target = self.target + return self.target.__str__() + + def __getattr__(self, aname): + self.event.wait() + target = self.target + + f = getattr(target, aname) + if isinstance(f, MethodType): + # Rebind the method to the target. + return new.instancemethod(f.im_func, self, target.__class__) + else: + return f + + +@contextmanager +def async(obj): + """Returns a context such that `obj` runs asynchronously as an actor. + + Adapts a generic object such that it runs asynchronously in a + thread as aa actor. Objects must be a newclass instance. All + interaction is queued up via a standard Queue, with instances of + the Future class returned. Unless the Future is instantiated, no + waiting occurs. + + TBD: would it be possible to turn this into a class decorator such that + any newly constructed objects are automatically actors? That would + be an interesting twist! + """ + + class TerminateCls(object): pass + TerminateReceiver = TerminateCls() + incoming = Queue() + + def receiver(): + """Runs `obj` within new thread, adapting via incoming queue""" + while True: + msg, future = incoming.get(True) + if msg == TerminateReceiver: + break + else: + method, args, kw = msg + future.target = getattr(obj, method)(*args, **kw) + future.event.set() + + class Proxy(object): + def __init__(self, target, incoming): + self._target = target + self._incoming = incoming + + def __getattr__(self, aname): + def send(*args, **kw): + future = Future() + self._incoming.put(((aname, args, kw), future)) + return future + return send + + t = threading.Thread(target=receiver).start() + yield Proxy(obj, incoming) + incoming.put((TerminateReceiver, None)) + + +def test(): + class X(object): + def __init__(self, x, y): + self.x = x + self.y = y + def write(self): + print self.x, self.y + def mult(self, n): + self.x = n*2 + self.y = n*2 + def get_x(self): + return self.x + + with async(X(1,2)) as x: + x.write() + x.mult(10) + x.write() + foo = x.get_x() + x.mult(5) + y = x.get_x() + print "Future %r" % (y,) + x.write() + print y + +if __name__ == '__main__': + test() + Deleted: branches/newcompiler/PyASM/tests/builtins.py =================================================================== --- branches/newcompiler/PyASM/test/builtins.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/builtins.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,133 +0,0 @@ -print ArithmeticError -print AssertionError -print AttributeError -#print BaseException -print DeprecationWarning -print EOFError -print Ellipsis -print EnvironmentError -print Exception -print False -print FloatingPointError -print FutureWarning -print GeneratorExit -print IOError -print ImportError -#print ImportWarning -print IndentationError -print IndexError -print KeyError -print KeyboardInterrupt -print LookupError -print MemoryError -print NameError -print None -print NotImplemented -print NotImplementedError -print OSError -print OverflowError -print PendingDeprecationWarning -print ReferenceError -print RuntimeError -print RuntimeWarning -print StandardError -print StopIteration -print SyntaxError -print SyntaxWarning -print SystemError -print SystemExit -print TabError -print True -print TypeError -print UnboundLocalError -print UnicodeDecodeError -print UnicodeEncodeError -print UnicodeError -print UnicodeTranslateError -#print UnicodeWarning -print UserWarning -print ValueError -print Warning -print ZeroDivisionError -print __debug__ -print __doc__ -print __import__ -print __name__ -print abs -#print all -#print any -print apply -print basestring -print bool -#print buffer -print callable -print chr -print classmethod -print cmp -print coerce -print compile -print complex -print copyright -print credits -print delattr -print dict -print dir -print divmod -print enumerate -print eval -print execfile -print exit -print file -print filter -print float -print frozenset -print getattr -print globals -print hasattr -print hash -#print help -print hex -print id -print input -print int -print intern -print isinstance -print issubclass -print iter -print len -print license -print list -print locals -print long -print map -print max -print min -print object -print oct -print open -print ord -print pow -print property -print quit -print range -print raw_input -print reduce -print reload -print repr -#print reversed -print round -print set -print setattr -print slice -#print sorted -print staticmethod -print str -print sum -print super -print tuple -print type -print unichr -print unicode -print vars -print xrange -print zip Copied: branches/newcompiler/PyASM/tests/builtins.py (from rev 3833, branches/newcompiler/PyASM/test/builtins.py) =================================================================== --- branches/newcompiler/PyASM/tests/builtins.py (rev 0) +++ branches/newcompiler/PyASM/tests/builtins.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,133 @@ +print ArithmeticError +print AssertionError +print AttributeError +#print BaseException +print DeprecationWarning +print EOFError +print Ellipsis +print EnvironmentError +print Exception +print False +print FloatingPointError +print FutureWarning +print GeneratorExit +print IOError +print ImportError +#print ImportWarning +print IndentationError +print IndexError +print KeyError +print KeyboardInterrupt +print LookupError +print MemoryError +print NameError +print None +print NotImplemented +print NotImplementedError +print OSError +print OverflowError +print PendingDeprecationWarning +print ReferenceError +print RuntimeError +print RuntimeWarning +print StandardError +print StopIteration +print SyntaxError +print SyntaxWarning +print SystemError +print SystemExit +print TabError +print True +print TypeError +print UnboundLocalError +print UnicodeDecodeError +print UnicodeEncodeError +print UnicodeError +print UnicodeTranslateError +#print UnicodeWarning +print UserWarning +print ValueError +print Warning +print ZeroDivisionError +print __debug__ +print __doc__ +print __import__ +print __name__ +print abs +#print all +#print any +print apply +print basestring +print bool +#print buffer +print callable +print chr +print classmethod +print cmp +print coerce +print compile +print complex +print copyright +print credits +print delattr +print dict +print dir +print divmod +print enumerate +print eval +print execfile +print exit +print file +print filter +print float +print frozenset +print getattr +print globals +print hasattr +print hash +#print help +print hex +print id +print input +print int +print intern +print isinstance +print issubclass +print iter +print len +print license +print list +print locals +print long +print map +print max +print min +print object +print oct +print open +print ord +print pow +print property +print quit +print range +print raw_input +print reduce +print reload +print repr +#print reversed +print round +print set +print setattr +print slice +#print sorted +print staticmethod +print str +print sum +print super +print tuple +print type +print unichr +print unicode +print vars +print xrange +print zip Deleted: branches/newcompiler/PyASM/tests/call.py =================================================================== --- branches/newcompiler/PyASM/test/call.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/call.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,10 +0,0 @@ -def a(b,c): - None - -a(1,c=2) -a(*[1,2]) -a(**dict(b=1,c=2)) -a(*[1],**dict(c=2)) -a(c=1,*[2]) -a(b=1,**dict(c=2)) -a(1,2,*[],**dict()) Copied: branches/newcompiler/PyASM/tests/call.py (from rev 3833, branches/newcompiler/PyASM/test/call.py) =================================================================== --- branches/newcompiler/PyASM/tests/call.py (rev 0) +++ branches/newcompiler/PyASM/tests/call.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,10 @@ +def a(b,c): + None + +a(1,c=2) +a(*[1,2]) +a(**dict(b=1,c=2)) +a(*[1],**dict(c=2)) +a(c=1,*[2]) +a(b=1,**dict(c=2)) +a(1,2,*[],**dict()) Deleted: branches/newcompiler/PyASM/tests/call_return.py =================================================================== --- branches/newcompiler/PyASM/test/call_return.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/call_return.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,4 +0,0 @@ -def a(b,c): - return c - -print a(1,2) Copied: branches/newcompiler/PyASM/tests/call_return.py (from rev 3833, branches/newcompiler/PyASM/test/call_return.py) =================================================================== --- branches/newcompiler/PyASM/tests/call_return.py (rev 0) +++ branches/newcompiler/PyASM/tests/call_return.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,4 @@ +def a(b,c): + return c + +print a(1,2) Deleted: branches/newcompiler/PyASM/tests/class_simple.py =================================================================== --- branches/newcompiler/PyASM/test/class_simple.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/class_simple.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,8 +0,0 @@ -class Test(object): - def __init__(self, arg): - self.arg = arg - - def __str__(self): - return "Test(%s)" % repr(self.arg) - -print Test('hej') Copied: branches/newcompiler/PyASM/tests/class_simple.py (from rev 3833, branches/newcompiler/PyASM/test/class_simple.py) =================================================================== --- branches/newcompiler/PyASM/tests/class_simple.py (rev 0) +++ branches/newcompiler/PyASM/tests/class_simple.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,8 @@ +class Test(object): + def __init__(self, arg): + self.arg = arg + + def __str__(self): + return "Test(%s)" % repr(self.arg) + +print Test('hej') Deleted: branches/newcompiler/PyASM/tests/constants.py =================================================================== --- branches/newcompiler/PyASM/test/constants.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/constants.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,9 +0,0 @@ -print 1 -print 2 -print True # name lookup... -print None # name lookup... -print "" -print "hej" -print () -print (1,2) -print 3.14 Copied: branches/newcompiler/PyASM/tests/constants.py (from rev 3833, branches/newcompiler/PyASM/test/constants.py) =================================================================== --- branches/newcompiler/PyASM/tests/constants.py (rev 0) +++ branches/newcompiler/PyASM/tests/constants.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,9 @@ +print 1 +print 2 +print True # name lookup... +print None # name lookup... +print "" +print "hej" +print () +print (1,2) +print 3.14 Deleted: branches/newcompiler/PyASM/tests/coroutine.py =================================================================== --- branches/newcompiler/PyASM/test/coroutine.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/coroutine.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,18 +0,0 @@ -def consumer(func): - def wrapper(*args,**kw): - gen = func(*args, **kw) - gen.next() - return gen - return wrapper - -@consumer -def make_receiver(n): - while True: - x = (yield) * n - print x - -if __name__ == 'main': - receiver = make_receiver(3) - for i in xrange(20): - receiver.send(i) - Copied: branches/newcompiler/PyASM/tests/coroutine.py (from rev 3833, branches/newcompiler/PyASM/test/coroutine.py) =================================================================== --- branches/newcompiler/PyASM/tests/coroutine.py (rev 0) +++ branches/newcompiler/PyASM/tests/coroutine.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,18 @@ +def consumer(func): + def wrapper(*args,**kw): + gen = func(*args, **kw) + gen.next() + return gen + return wrapper + +@consumer +def make_receiver(n): + while True: + x = (yield) * n + print x + +if __name__ == 'main': + receiver = make_receiver(3) + for i in xrange(20): + receiver.send(i) + Deleted: branches/newcompiler/PyASM/tests/exception.py =================================================================== --- branches/newcompiler/PyASM/test/exception.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/exception.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,10 +0,0 @@ -def a1(): - raise TypeError("probe") - -def a2(): - a1() - -def a3(): - a2() - -a3() Copied: branches/newcompiler/PyASM/tests/exception.py (from rev 3833, branches/newcompiler/PyASM/test/exception.py) =================================================================== --- branches/newcompiler/PyASM/tests/exception.py (rev 0) +++ branches/newcompiler/PyASM/tests/exception.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,10 @@ +def a1(): + raise TypeError("probe") + +def a2(): + a1() + +def a3(): + a2() + +a3() Deleted: branches/newcompiler/PyASM/tests/for.py =================================================================== --- branches/newcompiler/PyASM/test/for.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/for.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,4 +0,0 @@ -for x in xrange(10): - if x == 4: continue - if x == 7: break - print x Copied: branches/newcompiler/PyASM/tests/for.py (from rev 3833, branches/newcompiler/PyASM/test/for.py) =================================================================== --- branches/newcompiler/PyASM/tests/for.py (rev 0) +++ branches/newcompiler/PyASM/tests/for.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,4 @@ +for x in xrange(10): + if x == 4: continue + if x == 7: break + print x Deleted: branches/newcompiler/PyASM/tests/generator.py =================================================================== --- branches/newcompiler/PyASM/test/generator.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/generator.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,43 +0,0 @@ -def gen(x): - while True: - x -= 1 - if x < 0: - break - else: - print (yield x) - -for x in gen(4): - print x - -it = gen(2) -print it.next() -print it.send("hi") - -it = gen(3) -try: - it.throw(SystemError, "ok") -except SystemError, e: - print "Caught exception:", e -try: - print it.next() -except StopIteration: - print "ok" - -it = gen(3) -print it.next() -print it.send('hi') -try: # this works outside of try-block, why not inside? - it.throw(SystemError('ok')) -except SystemError, e: - print "Caught exception:", e -try: - print it.next() -except StopIteration: - print "Caught StopIteration: ok" - -it = gen(1) -it.close() - -it = gen(2) -print it.next() -it.close() Copied: branches/newcompiler/PyASM/tests/generator.py (from rev 3833, branches/newcompiler/PyASM/test/generator.py) =================================================================== --- branches/newcompiler/PyASM/tests/generator.py (rev 0) +++ branches/newcompiler/PyASM/tests/generator.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,43 @@ +def gen(x): + while True: + x -= 1 + if x < 0: + break + else: + print (yield x) + +for x in gen(4): + print x + +it = gen(2) +print it.next() +print it.send("hi") + +it = gen(3) +try: + it.throw(SystemError, "ok") +except SystemError, e: + print "Caught exception:", e +try: + print it.next() +except StopIteration: + print "ok" + +it = gen(3) +print it.next() +print it.send('hi') +try: # this works outside of try-block, why not inside? + it.throw(SystemError('ok')) +except SystemError, e: + print "Caught exception:", e +try: + print it.next() +except StopIteration: + print "Caught StopIteration: ok" + +it = gen(1) +it.close() + +it = gen(2) +print it.next() +it.close() Copied: branches/newcompiler/PyASM/tests/generator_close.py (from rev 3833, branches/newcompiler/PyASM/test/generator_close.py) =================================================================== --- branches/newcompiler/PyASM/tests/generator_close.py (rev 0) +++ branches/newcompiler/PyASM/tests/generator_close.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,17 @@ +from java.lang import System + +def gen(): + try: + yield None + except Exception, e: + print "Caught", e + raise + +it = gen() +it.next() +it.close() +it = gen() +it.next() +del it + +System.gc() Deleted: branches/newcompiler/PyASM/tests/generator_comprehension.py =================================================================== --- branches/newcompiler/PyASM/test/generator_comprehension.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/generator_comprehension.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,3 +0,0 @@ -x = (l for l in xrange(10)) -for w in x: - print w Copied: branches/newcompiler/PyASM/tests/generator_comprehension.py (from rev 3833, branches/newcompiler/PyASM/test/generator_comprehension.py) =================================================================== --- branches/newcompiler/PyASM/tests/generator_comprehension.py (rev 0) +++ branches/newcompiler/PyASM/tests/generator_comprehension.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,3 @@ +x = (l for l in xrange(10)) +for w in x: + print w Deleted: branches/newcompiler/PyASM/tests/generator_finally.py =================================================================== --- branches/newcompiler/PyASM/test/generator_finally.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/generator_finally.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,23 +0,0 @@ -def gen(n): - def make(v): - def result(): - return v - return result - try: - for x in xrange(n): - try: - data = yield make(x) - print data - except GeneratorExit: - raise - except Exception, e: - print "EXCEPTION: ", e - finally: - print "done" - -g = gen(10) -print "g.next():", g.next()() -print "g.send(14):", g.send(14)() -print "g.throw(...):", g.throw(RuntimeError("FEL"))() -print "g.next():", g.next()() -print "g.close():", g.close() Copied: branches/newcompiler/PyASM/tests/generator_finally.py (from rev 3833, branches/newcompiler/PyASM/test/generator_finally.py) =================================================================== --- branches/newcompiler/PyASM/tests/generator_finally.py (rev 0) +++ branches/newcompiler/PyASM/tests/generator_finally.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,23 @@ +def gen(n): + def make(v): + def result(): + return v + return result + try: + for x in xrange(n): + try: + data = yield make(x) + print data + except GeneratorExit: + raise + except Exception, e: + print "EXCEPTION: ", e + finally: + print "done" + +g = gen(10) +print "g.next():", g.next()() +print "g.send(14):", g.send(14)() +print "g.throw(...):", g.throw(RuntimeError("FEL"))() +print "g.next():", g.next()() +print "g.close():", g.close() Deleted: branches/newcompiler/PyASM/tests/generator_state.py =================================================================== --- branches/newcompiler/PyASM/test/generator_state.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/generator_state.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,9 +0,0 @@ -def gen(l): - for x in xrange(l): - try: - yield x - finally: - print "one" - -for x in gen(4): - print "res:", x Copied: branches/newcompiler/PyASM/tests/generator_state.py (from rev 3833, branches/newcompiler/PyASM/test/generator_state.py) =================================================================== --- branches/newcompiler/PyASM/tests/generator_state.py (rev 0) +++ branches/newcompiler/PyASM/tests/generator_state.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,9 @@ +def gen(l): + for x in xrange(l): + try: + yield x + finally: + print "one" + +for x in gen(4): + print "res:", x Deleted: branches/newcompiler/PyASM/tests/generator_state2.py =================================================================== --- branches/newcompiler/PyASM/test/generator_state2.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/generator_state2.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,10 +0,0 @@ -def gen(l): - for x in xrange(l): - try: - yield x - except Exception, e: - print "err:", e - -it = gen(4) -print it.next() -print it.throw(RuntimeError('probe')) Copied: branches/newcompiler/PyASM/tests/generator_state2.py (from rev 3833, branches/newcompiler/PyASM/test/generator_state2.py) =================================================================== --- branches/newcompiler/PyASM/tests/generator_state2.py (rev 0) +++ branches/newcompiler/PyASM/tests/generator_state2.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,10 @@ +def gen(l): + for x in xrange(l): + try: + yield x + except Exception, e: + print "err:", e + +it = gen(4) +print it.next() +print it.throw(RuntimeError('probe')) Copied: branches/newcompiler/PyASM/tests/global.py (from rev 3833, branches/newcompiler/PyASM/test/global.py) =================================================================== --- branches/newcompiler/PyASM/tests/global.py (rev 0) +++ branches/newcompiler/PyASM/tests/global.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,8 @@ +g = 5 +def f(): + global g + g = 7 + +print g +f() +print g Deleted: branches/newcompiler/PyASM/tests/import.py =================================================================== --- branches/newcompiler/PyASM/test/import.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/import.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,7 +0,0 @@ -import sys -import marshal -import java.lang - -print sys -print marshal -print java.lang Copied: branches/newcompiler/PyASM/tests/import.py (from rev 3833, branches/newcompiler/PyASM/test/import.py) =================================================================== --- branches/newcompiler/PyASM/tests/import.py (rev 0) +++ branches/newcompiler/PyASM/tests/import.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,7 @@ +import sys +import marshal +import java.lang + +print sys +print marshal +print java.lang Deleted: branches/newcompiler/PyASM/tests/import_from.py =================================================================== --- branches/newcompiler/PyASM/test/import_from.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/import_from.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,8 +0,0 @@ -from marshal import loads -from sys import argv -from java.lang import Integer, String - -print loads -print argv -print Integer -print String Copied: branches/newcompiler/PyASM/tests/import_from.py (from rev 3833, branches/newcompiler/PyASM/test/import_from.py) =================================================================== --- branches/newcompiler/PyASM/tests/import_from.py (rev 0) +++ branches/newcompiler/PyASM/tests/import_from.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,8 @@ +from marshal import loads +from sys import argv +from java.lang import Integer, String + +print loads +print argv +print Integer +print String Deleted: branches/newcompiler/PyASM/tests/import_star.py =================================================================== --- branches/newcompiler/PyASM/test/import_star.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/import_star.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,3 +0,0 @@ -from sys import * - -print argv Copied: branches/newcompiler/PyASM/tests/import_star.py (from rev 3833, branches/newcompiler/PyASM/test/import_star.py) =================================================================== --- branches/newcompiler/PyASM/tests/import_star.py (rev 0) +++ branches/newcompiler/PyASM/tests/import_star.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,3 @@ +from sys import * + +print argv Deleted: branches/newcompiler/PyASM/tests/list.py =================================================================== --- branches/newcompiler/PyASM/test/list.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/list.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1 +0,0 @@ -print [1,2,3,4,5,6,7] Copied: branches/newcompiler/PyASM/tests/list.py (from rev 3833, branches/newcompiler/PyASM/test/list.py) =================================================================== --- branches/newcompiler/PyASM/tests/list.py (rev 0) +++ branches/newcompiler/PyASM/tests/list.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1 @@ +print [1,2,3,4,5,6,7] Deleted: branches/newcompiler/PyASM/tests/list_comprehension.py =================================================================== --- branches/newcompiler/PyASM/test/list_comprehension.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/list_comprehension.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1 +0,0 @@ -x = [l for l in xrange(10)] Copied: branches/newcompiler/PyASM/tests/list_comprehension.py (from rev 3833, branches/newcompiler/PyASM/test/list_comprehension.py) =================================================================== --- branches/newcompiler/PyASM/tests/list_comprehension.py (rev 0) +++ branches/newcompiler/PyASM/tests/list_comprehension.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1 @@ +x = [l for l in xrange(10)] Copied: branches/newcompiler/PyASM/tests/loops.py (from rev 3833, branches/newcompiler/PyASM/test/loops.py) =================================================================== --- branches/newcompiler/PyASM/tests/loops.py (rev 0) +++ branches/newcompiler/PyASM/tests/loops.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,4 @@ +for e in xrange(5): + while 1: + break + Deleted: branches/newcompiler/PyASM/tests/observer.py =================================================================== --- branches/newcompiler/PyASM/test/observer.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/observer.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1,323 +0,0 @@ -""" -observer module - -Typical usage is as follows: - -from __future__ import with_statement -from observer import consumer, observation - -@consumer -def do_something_with_notification(): - while True: - key, old, new = (yield) - print "%s: %s -> %s" % (key, old, new) - -container = {} - -# Any modification to `container`, now called `observed` in the -# body of the with statement, is sent to the coroutine -# do_something_with_notification() - -with observation(observe=container, - notify=[do_something_with_notification()) as observed: - modify_observed(observed) - -Requires Python 2.5 -Author: Jim Baker (jb...@zy...) -""" - -from __future__ import with_statement -import unittest - -class GeneratorContextManager(object): - """Helper for @contextmanager decorator.""" - - def __init__(self, gen): - self.gen = gen - - def __enter__(self): - try: - return self.gen.next() - except StopIteration: - raise RuntimeError("generator didn't yield") - - def __exit__(self, type, value, traceback): - if type is None: - try: - self.gen.next() - except StopIteration: - return - else: - raise RuntimeError("generator didn't stop") - else: - try: - self.gen.throw(type, value, traceback) - raise RuntimeError("generator didn't stop after throw()") - except StopIteration, exc: - # Suppress the exception *unless* it's the same exception that - # was passed to throw(). This prevents a StopIteration - # raised inside the "with" statement from being suppressed - return exc is not value - except: - # only re-raise if it's *not* the exception that was - # passed to throw(), because __exit__() must not raise - # an exception unless __exit__() itself failed. But throw() - # has to raise the exception to signal propagation, so this - # fixes the impedance mismatch between the throw() protocol - # and the __exit__() protocol. - # - if sys.exc_info()[1] is not value: - raise - - -def contextmanager(func): - """@contextmanager decorator. - - Typical usage: - - @contextmanager - def some_generator(<arguments>): - <setup> - try: - yield <value> - finally: - <cleanup> - - This makes this: - - with some_generator(<arguments>) as <variable>: - <body> - - equivalent to this: - - <setup> - try: - <variable> = <value> - <body> - finally: - <cleanup> - - """ - def helper(*args, **kwds): - return GeneratorContextManager(func(*args, **kwds)) - try: - helper.__name__ = func.__name__ - helper.__doc__ = func.__doc__ - helper.__dict__ = func.__dict__ - except: - pass - return helper - -@contextmanager -def observation(observe, notify): - """Simple boilerplate to link to the 'with' statement. - - Contextlib's contextmanager decorator is a very convenient way to - create simple context managers, specifically the __enter__ and - __exit__ special methods. - """ - - proxy = Observation(observe, notify) - try: - yield proxy - finally: - proxy.close() - - -class NoneSuch(object): - """A useful alternative to None in the case of a key being deleted or inserted.""" - def __new__(cls, *args, **kwargs): - if '_inst' not in vars(cls): - cls._inst = object.__new__(cls, *args, **kwargs) - return cls._inst - def __init__(self, *args, **kwargs): pass - def __repr__(self): return "NoneSuch()" - def __call__(self, *args, **kwargs): return self - def __nonzero__(self): return False - -NoneSuch = NoneSuch() - - -class Observation(object): - """Enables observation of dictionaries. - - Proxies the `observe` dictionary such that any modifications to - it are sent via `send()` to the notifiers in the `notify` - sequence. The sent value is a triple (key, old, new). - Notifications are sent AFTER the change. - - Other mutable containers, such as sets and lists or your custom - container, can be readily added by supporting their interface. - """ - - def __init__(self, observe, notify): - self._obj = observe - self.notify = notify - - def close(self): - self._obj = None - self.notify = None - - def __iter__(self): - if self._obj is None: raise ValueError("Operation on closed observation") - return iter(self._obj) - - # all mutating methods go here, this list should be comprehensive as of 2.5 - def __delitem__(self, K): - if self._obj is None: raise ValueError("Operation on closed observation") - old = self._obj[K] - del self._obj[K] - for notify in self.notify: - notify.send((K, old, NoneSuch)) - - def __setitem__(self, K, V): - if self._obj is None: raise ValueError("Operation on closed observation") - old = self._obj.get(K, NoneSuch) - self._obj[K] = V - for notify in self.notify: - notify.send((K, old, V)) - - def setdefault(self, K, default): - if self._obj is None: raise ValueError("Operation on closed observation") - try: - return self._obj[K] - except KeyError: - self._obj[K] = default - for notify in self.notify: - notify.send((K, NoneSuch, default)) - - def clear(self): - if self._obj is None: raise ValueError("Operation on closed observation") - items = self._obj.items() - self._obj.clear() - for K, old in items: - for notify in self.notify: - notify.send((K, old, NoneSuch)) - - def update(self, *seq_or_map, **kw): - from itertools import chain - - if self._obj is None: raise ValueError("Operation on closed observation") - try: seq = seq_or_map[0].iteritems() - except IndexError: seq = ((K,None) for K in seq_or_map) - for K, V in chain(seq, kw.iteritems()): - old = self._obj.get(K, NoneSuch) - self._obj[K] = V - for notify in self.notify: - notify.send((K, old, V)) - - def pop(self, K, *default): - if self._obj is None: raise ValueError("Operation on closed observation") - - # this may be unexpected to have old be the default - # value. what do you think? - if default: - old = self._obj.pop(K, default[0]) - else: - old = self._obj.pop(K) - for notify in self.notify: - notify.send((K, old, NoneSuch)) - return old - - def popitem(self): - if self._obj is None: raise ValueError("Operation on closed observation") - K,old = self._obj.popitem() - for notify in self.notify: - notify.send((K, old, NoneSuch)) - return old - - def __contains__(self, K): - if self._obj is None: raise ValueError("Operation on closed observation") - return K in self._obj - def __getitem__(self, K): - if self._obj is None: raise ValueError("Operation on closed observation") - return self._obj[K] - def __len__(self): - if self._obj is None: raise ValueError("Operation on closed observation") - return len(self._obj) - - # otherwise, just pass through - def __getattr__(self, attrib): - if self._obj is None: raise ValueError("Operation on closed observation") - return getattr(self._obj, attrib) - - -def consumer(func): - def wrapper(*args,**kw): - gen = func(*args, **kw) - gen.next() - return gen -# wrapper.__name__ = func.__name__ -# wrapper.__dict__ = func.__dict__ -# wrapper.__doc__ = func.__doc__ - return wrapper - - -class ObserverTestCase(unittest.TestCase): - """Tests observer module, special emphasis on dictionary protocol. - - We keep the tests monolithic, just RunTest(), to keep the scope of - the with statement visible and simple. - """ - - def runTest(self): - from collections import deque - changes = deque() - - def consume(X): - def _consume(X): - while X: - yield X.popleft() - return list(_consume(X)) - - @consumer - def observe_changes(): - while True: - change = (yield) - changes.append(change) - - fruits = dict(apple=1, banana=2, cherry=3) - with observation(observe=fruits, notify=[observe_changes()]) as observed_fruits: - # typical mutations - observed_fruits['cherry'] *= 2 - del observed_fruits['apple'] - self.assertEquals(consume(changes), [('cherry', 3, 6), ('apple', 1, NoneSuch)]) - - # .update with keyword args - observed_fruits.update(durian=4, figs=5) - self.assertEquals(fruits['durian'], 4) - - # .clear - observed_fruits.clear() - self.assertEquals(len(observed_fruits), 0) - consume(changes) # keep it simple, just throw away - - # .update with map and keyword args, kw should override - observed_fruits.update({'grapefruit':6, 'jackfruit':7}, jackfruit=8) - self.assertEquals(observed_fruits['jackfruit'], 8) - self.assertEquals(consume(changes), [('jackfruit', NoneSuch, 7), ('grapefruit', NoneSuch, 6), ('jackfruit', 7, 8)]) - - # .pop, default here may be controversial - observed_fruits.pop('durian', None) - self.assertEquals(consume(changes), [('durian', None, NoneSuch)]) - - # .setdefault - observed_fruits.setdefault('jackfruit', -1) - observed_fruits.setdefault('kiwi', 9) - self.assertEquals(consume(changes), [('kiwi', NoneSuch, 9)]) - - # .popitem - while observed_fruits: - observed_fruits.popitem() - self.assertEquals(fruits, dict()) - - # verify that outside of with statement scope, the observation - # is closed - self.assertRaises(ValueError, lambda: observed_fruits.update(foo=0, fum=1)) - - -if __name__ == "__main__": - suite = unittest.TestLoader().loadTestsFromTestCase(ObserverTestCase) - unittest.TextTestRunner(verbosity=2).run(suite) - # unittest.main() - Copied: branches/newcompiler/PyASM/tests/observer.py (from rev 3833, branches/newcompiler/PyASM/test/observer.py) =================================================================== --- branches/newcompiler/PyASM/tests/observer.py (rev 0) +++ branches/newcompiler/PyASM/tests/observer.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1,323 @@ +""" +observer module + +Typical usage is as follows: + +from __future__ import with_statement +from observer import consumer, observation + +@consumer +def do_something_with_notification(): + while True: + key, old, new = (yield) + print "%s: %s -> %s" % (key, old, new) + +container = {} + +# Any modification to `container`, now called `observed` in the +# body of the with statement, is sent to the coroutine +# do_something_with_notification() + +with observation(observe=container, + notify=[do_something_with_notification()) as observed: + modify_observed(observed) + +Requires Python 2.5 +Author: Jim Baker (jb...@zy...) +""" + +from __future__ import with_statement +import unittest + +class GeneratorContextManager(object): + """Helper for @contextmanager decorator.""" + + def __init__(self, gen): + self.gen = gen + + def __enter__(self): + try: + return self.gen.next() + except StopIteration: + raise RuntimeError("generator didn't yield") + + def __exit__(self, type, value, traceback): + if type is None: + try: + self.gen.next() + except StopIteration: + return + else: + raise RuntimeError("generator didn't stop") + else: + try: + self.gen.throw(type, value, traceback) + raise RuntimeError("generator didn't stop after throw()") + except StopIteration, exc: + # Suppress the exception *unless* it's the same exception that + # was passed to throw(). This prevents a StopIteration + # raised inside the "with" statement from being suppressed + return exc is not value + except: + # only re-raise if it's *not* the exception that was + # passed to throw(), because __exit__() must not raise + # an exception unless __exit__() itself failed. But throw() + # has to raise the exception to signal propagation, so this + # fixes the impedance mismatch between the throw() protocol + # and the __exit__() protocol. + # + if sys.exc_info()[1] is not value: + raise + + +def contextmanager(func): + """@contextmanager decorator. + + Typical usage: + + @contextmanager + def some_generator(<arguments>): + <setup> + try: + yield <value> + finally: + <cleanup> + + This makes this: + + with some_generator(<arguments>) as <variable>: + <body> + + equivalent to this: + + <setup> + try: + <variable> = <value> + <body> + finally: + <cleanup> + + """ + def helper(*args, **kwds): + return GeneratorContextManager(func(*args, **kwds)) + try: + helper.__name__ = func.__name__ + helper.__doc__ = func.__doc__ + helper.__dict__ = func.__dict__ + except: + pass + return helper + +@contextmanager +def observation(observe, notify): + """Simple boilerplate to link to the 'with' statement. + + Contextlib's contextmanager decorator is a very convenient way to + create simple context managers, specifically the __enter__ and + __exit__ special methods. + """ + + proxy = Observation(observe, notify) + try: + yield proxy + finally: + proxy.close() + + +class NoneSuch(object): + """A useful alternative to None in the case of a key being deleted or inserted.""" + def __new__(cls, *args, **kwargs): + if '_inst' not in vars(cls): + cls._inst = object.__new__(cls, *args, **kwargs) + return cls._inst + def __init__(self, *args, **kwargs): pass + def __repr__(self): return "NoneSuch()" + def __call__(self, *args, **kwargs): return self + def __nonzero__(self): return False + +NoneSuch = NoneSuch() + + +class Observation(object): + """Enables observation of dictionaries. + + Proxies the `observe` dictionary such that any modifications to + it are sent via `send()` to the notifiers in the `notify` + sequence. The sent value is a triple (key, old, new). + Notifications are sent AFTER the change. + + Other mutable containers, such as sets and lists or your custom + container, can be readily added by supporting their interface. + """ + + def __init__(self, observe, notify): + self._obj = observe + self.notify = notify + + def close(self): + self._obj = None + self.notify = None + + def __iter__(self): + if self._obj is None: raise ValueError("Operation on closed observation") + return iter(self._obj) + + # all mutating methods go here, this list should be comprehensive as of 2.5 + def __delitem__(self, K): + if self._obj is None: raise ValueError("Operation on closed observation") + old = self._obj[K] + del self._obj[K] + for notify in self.notify: + notify.send((K, old, NoneSuch)) + + def __setitem__(self, K, V): + if self._obj is None: raise ValueError("Operation on closed observation") + old = self._obj.get(K, NoneSuch) + self._obj[K] = V + for notify in self.notify: + notify.send((K, old, V)) + + def setdefault(self, K, default): + if self._obj is None: raise ValueError("Operation on closed observation") + try: + return self._obj[K] + except KeyError: + self._obj[K] = default + for notify in self.notify: + notify.send((K, NoneSuch, default)) + + def clear(self): + if self._obj is None: raise ValueError("Operation on closed observation") + items = self._obj.items() + self._obj.clear() + for K, old in items: + for notify in self.notify: + notify.send((K, old, NoneSuch)) + + def update(self, *seq_or_map, **kw): + from itertools import chain + + if self._obj is None: raise ValueError("Operation on closed observation") + try: seq = seq_or_map[0].iteritems() + except IndexError: seq = ((K,None) for K in seq_or_map) + for K, V in chain(seq, kw.iteritems()): + old = self._obj.get(K, NoneSuch) + self._obj[K] = V + for notify in self.notify: + notify.send((K, old, V)) + + def pop(self, K, *default): + if self._obj is None: raise ValueError("Operation on closed observation") + + # this may be unexpected to have old be the default + # value. what do you think? + if default: + old = self._obj.pop(K, default[0]) + else: + old = self._obj.pop(K) + for notify in self.notify: + notify.send((K, old, NoneSuch)) + return old + + def popitem(self): + if self._obj is None: raise ValueError("Operation on closed observation") + K,old = self._obj.popitem() + for notify in self.notify: + notify.send((K, old, NoneSuch)) + return old + + def __contains__(self, K): + if self._obj is None: raise ValueError("Operation on closed observation") + return K in self._obj + def __getitem__(self, K): + if self._obj is None: raise ValueError("Operation on closed observation") + return self._obj[K] + def __len__(self): + if self._obj is None: raise ValueError("Operation on closed observation") + return len(self._obj) + + # otherwise, just pass through + def __getattr__(self, attrib): + if self._obj is None: raise ValueError("Operation on closed observation") + return getattr(self._obj, attrib) + + +def consumer(func): + def wrapper(*args,**kw): + gen = func(*args, **kw) + gen.next() + return gen +# wrapper.__name__ = func.__name__ +# wrapper.__dict__ = func.__dict__ +# wrapper.__doc__ = func.__doc__ + return wrapper + + +class ObserverTestCase(unittest.TestCase): + """Tests observer module, special emphasis on dictionary protocol. + + We keep the tests monolithic, just RunTest(), to keep the scope of + the with statement visible and simple. + """ + + def runTest(self): + from collections import deque + changes = deque() + + def consume(X): + def _consume(X): + while X: + yield X.popleft() + return list(_consume(X)) + + @consumer + def observe_changes(): + while True: + change = (yield) + changes.append(change) + + fruits = dict(apple=1, banana=2, cherry=3) + with observation(observe=fruits, notify=[observe_changes()]) as observed_fruits: + # typical mutations + observed_fruits['cherry'] *= 2 + del observed_fruits['apple'] + self.assertEquals(consume(changes), [('cherry', 3, 6), ('apple', 1, NoneSuch)]) + + # .update with keyword args + observed_fruits.update(durian=4, figs=5) + self.assertEquals(fruits['durian'], 4) + + # .clear + observed_fruits.clear() + self.assertEquals(len(observed_fruits), 0) + consume(changes) # keep it simple, just throw away + + # .update with map and keyword args, kw should override + observed_fruits.update({'grapefruit':6, 'jackfruit':7}, jackfruit=8) + self.assertEquals(observed_fruits['jackfruit'], 8) + self.assertEquals(consume(changes), [('jackfruit', NoneSuch, 7), ('grapefruit', NoneSuch, 6), ('jackfruit', 7, 8)]) + + # .pop, default here may be controversial + observed_fruits.pop('durian', None) + self.assertEquals(consume(changes), [('durian', None, NoneSuch)]) + + # .setdefault + observed_fruits.setdefault('jackfruit', -1) + observed_fruits.setdefault('kiwi', 9) + self.assertEquals(consume(changes), [('kiwi', NoneSuch, 9)]) + + # .popitem + while observed_fruits: + observed_fruits.popitem() + self.assertEquals(fruits, dict()) + + # verify that outside of with statement scope, the observation + # is closed + self.assertRaises(ValueError, lambda: observed_fruits.update(foo=0, fum=1)) + + +if __name__ == "__main__": + suite = unittest.TestLoader().loadTestsFromTestCase(ObserverTestCase) + unittest.TextTestRunner(verbosity=2).run(suite) + # unittest.main() + Deleted: branches/newcompiler/PyASM/tests/print.py =================================================================== --- branches/newcompiler/PyASM/test/print.py 2007-12-08 20:39:48 UTC (rev 3777) +++ branches/newcompiler/PyASM/tests/print.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -1 +0,0 @@ -print "hello world" Copied: branches/newcompiler/PyASM/tests/print.py (from rev 3833, branches/newcompiler/PyASM/test/print.py) =================================================================== --- branches/newcompiler/PyASM/tests/print.py (rev 0) +++ branches/newcompiler/PyASM/tests/print.py 2007-12-17 18:05:33 UTC (rev 3834) @@ -0,0 +1 @@ +print "hello world" Copied: branches/newcompiler/PyASM/tests/print_chevron.py (from rev 3833, branches/newcompiler/PyASM/test/print_chevron.py) =================================================================== --- branches/newcompiler/PyASM/tests/print_chevron.py (rev 0) +++ branches/newcom... [truncated message content] |
From: <th...@us...> - 2007-12-28 12:39:46
|
Revision: 3881 http://jython.svn.sourceforge.net/jython/?rev=3881&view=rev Author: thobes Date: 2007-12-28 04:39:43 -0800 (Fri, 28 Dec 2007) Log Message: ----------- Some great patches by Nicholas Riley that solves some issues with: * try with break in loops * try with return in loops * nested try statements * closure variables * sequence unpacking and lots of improvements on the tests. Modified Paths: -------------- branches/newcompiler/PyASM/pyasm.py branches/newcompiler/PyASM/test.py branches/newcompiler/PyASM/tests/async_obj.py Added Paths: ----------- branches/newcompiler/PyASM/tests/for_try_return.py branches/newcompiler/PyASM/tests/lexical_binding.py branches/newcompiler/PyASM/tests/try_loops.py branches/newcompiler/PyASM/tests/try_nested.py branches/newcompiler/PyASM/tests/unpack.py Modified: branches/newcompiler/PyASM/pyasm.py =================================================================== --- branches/newcompiler/PyASM/pyasm.py 2007-12-28 02:51:45 UTC (rev 3880) +++ branches/newcompiler/PyASM/pyasm.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -108,7 +108,6 @@ asType = property(lambda self: Type.getType( "L%s;" % self.__name.replace('.','/'))) def __init__(self, name): - print "CLASSNAME:", name self.__name = name self.__cw = asm.ClassWriter(asm.ClassWriter.COMPUTE_MAXS # Frames need to be computed for @@ -379,7 +378,8 @@ (type(value), value)) self.clinit.putStatic(self.asType, name, pyObjectType) - +# FIXME: The block objects need to be refactored, se notes in ASMVisitor code. +# FIXME: The contract of the block objects needs to be thoroughly documented. class Block(object): def __init__(self, asm, stackSize=0, *stateVariables): self.asm = asm @@ -471,6 +471,7 @@ class ExceptBlock(HandlerBlock): def __init__(self, asm, sourceBlock): HandlerBlock.__init__(self, asm, sourceBlock, 3) + nestingStackSize = property(lambda self: self.stackSize - 3) def end(self): """stack is: ... exc_traceback exc_value exc_type""" self.asm.dupX2() @@ -615,6 +616,16 @@ self.__class.setFilename(filename) self.asm = self.__class.newFunction(name) + + for variableName in self.__cellvars: + if variableName not in self.__varnames: + continue + self.loadFrame() + self.push(self.__varnames.index(variableName)) + self.derefIndex(variableName) + self.asm.invokeVirtual(pyFrameType, Method.getMethod( + "void to_cell (int, int)")) + self.asm.visitCode() self.__code = self.__class.getCodeReference() @@ -787,27 +798,15 @@ def visitUnpackSequence(self, count): """sequence -- (element, )*count""" - sequenceType = getType(core.PySequenceList) - self.asm.checkCast(sequenceType) # FIXME: could generate better error - self.asm.dup() - self.asm.invokeVirtual(sequenceType, Method.getMethod( - "int size ()")) self.push(count) - ok = self.label() - self.asm.ifICmp(self.asm.EQ, ok) - self.push("Incompatible lengths for unpack") self.asm.invokeStatic(pyType, Method.getMethod( - "org.python.core.PyException ValueError (String)")) - self.asm.throwException() - self.asm.visitLabel(ok) - method = Method.getMethod("org.python.core.PyObject pyget (int)") - sequence = self.newLocal(sequenceType, "sequence") - sequence.store() + "org.python.core.PyObject[] unpackSequence (%s)" % ", ".join( + ['org.python.core.PyObject', 'int']))) for i in range(count -1, -1, -1): - sequence.load() + if i != 0: self.asm.dup() self.push(i) - self.asm.invokeVirtual(sequenceType, method) - sequence.end() + self.asm.arrayLoad(pyObjectType) + if i != 0: self.asm.swap() def buildSequence(self, seqType, size): """helper method for BuildTuple and BuildList""" @@ -956,24 +955,38 @@ def visitBreakLoop(self): """ -- """ + # FIXME: in_try_block is a great patch by Nicholas Riley, but should + # probably be refactored so that it is handeled in the block object. + in_try_block = False for i in xrange(len(self.__blocks) -1,-1,-1): block = self.__blocks[i] - block.exit(False) if isinstance(block, LoopBlock): self.asm.goTo(block.endLabel) break + elif not in_try_block: + block.exit(False) + if isinstance(block, TryExceptBlock): + in_try_block = True else: # No surrounding LoopBlock was found raise SyntaxError("break not properly nested in loop.") def visitContinueLoop(self, loopStart): """ -- """ + # FIXME: in_try_block is a great patch by Nicholas Riley, but should + # probably be refactored so that it is handeled in the block object. + in_try_block = False for i in xrange(len(self.__blocks) -1,-1,-1): block = self.__blocks[i] if isinstance(block, LoopBlock): + self.asm.goTo(self.label(loopStart)) break - else: + elif not in_try_block: block.exit(False) - self.asm.goTo(self.label(loopStart)) + if isinstance(block, TryExceptBlock): + block.loadState() + in_try_block = True + else: # No surrounding LoopBlock was found + raise SyntaxError("continue not properly nested in loop.") def visitDeleteAttribute(self, attributeName): """object -- """ @@ -1233,12 +1246,6 @@ def visitLoadClosure(self, variableName): """ -- cellvar""" - if variableName in self.__varnames: - self.loadFrame() - self.push(self.__varnames.index(variableName)) - self.derefIndex(variableName) - self.asm.invokeVirtual(pyFrameType, Method.getMethod( - "void to_cell (int, int)")) self.loadFrame() self.derefIndex(variableName) self.asm.invokeVirtual(pyFrameType, Method.getMethod( @@ -1416,9 +1423,15 @@ def visitReturnValue(self): """object -- """ jumps = False + # FIXME: in_try_block is a great patch by Nicholas Riley, but should + # probably be refactored so that it is handeled in the block object. + in_try_block = False for i in xrange(len(self.__blocks) -1,-1,-1): block = self.__blocks[i] - jumps = block.exit() or jumps + if not in_try_block: + jumps = block.exit() or jumps + if isinstance(block, TryExceptBlock): + in_try_block = True self.loadFrame() self.push(-1) self.asm.putField(pyFrameType, 'f_lasti', Type.INT_TYPE) Modified: branches/newcompiler/PyASM/test.py =================================================================== --- branches/newcompiler/PyASM/test.py 2007-12-28 02:51:45 UTC (rev 3880) +++ branches/newcompiler/PyASM/test.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -1,13 +1,22 @@ -import os, marshal +import sys, os, marshal if os.name == 'java': # Jython side - def cpythonCompile(string, filename='<stdin>'): # invoke script with CPython to compile and return marshalled code - source, binary = os.popen2('python %s "%s"' % (__file__, filename)) + source, drain, error = os.popen3('python2.5 "%s" "%s"' % + (__file__, filename)) source.write(string) # send source source.close() # mark end of source (eof) - data = "".join([chr(int(x)) for x in binary.read().split(',')]) #decode + binary = drain.read() + if len(binary) == 0: + print >> sys.stderr, error.read() + sys.exit(1) + try: + data = "".join([chr(int(x)) for x in binary.split(',')]) #decode + except: + print >> sys.stderr, "Read from CPython:" + print >> sys.stderr, data + raise code = marshal.loads(data) # read back marshalled code and unmarshal return code # return unmarshalled, compiled code @@ -16,10 +25,10 @@ filename = sys.argv[1] file = open(filename) # open file code = cpythonCompile(file.read(), filename) # compile file - exec code # execute compiled file + vars = dict(__name__='__main__', __file__=filename, __doc__=None) + exec code in vars # execute compiled file elif __name__ == '__main__': # CPython side - import sys filename = sys.argv[1] source = sys.stdin.read() # read source code = compile(source, filename, 'exec') # compile code Modified: branches/newcompiler/PyASM/tests/async_obj.py =================================================================== --- branches/newcompiler/PyASM/tests/async_obj.py 2007-12-28 02:51:45 UTC (rev 3880) +++ branches/newcompiler/PyASM/tests/async_obj.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -94,7 +94,7 @@ self.x = x self.y = y def write(self): - print self.x, self.y + print "x,y", self.x, self.y def mult(self, n): self.x = n*2 self.y = n*2 @@ -110,8 +110,9 @@ y = x.get_x() print "Future %r" % (y,) x.write() - print y + print "y", y +print __name__ if __name__ == '__main__': test() Added: branches/newcompiler/PyASM/tests/for_try_return.py =================================================================== --- branches/newcompiler/PyASM/tests/for_try_return.py (rev 0) +++ branches/newcompiler/PyASM/tests/for_try_return.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -0,0 +1,9 @@ +def f(): + for e in __name__: + try: + return + except: + pass + +if __name__ == '__main__': + f() Added: branches/newcompiler/PyASM/tests/lexical_binding.py =================================================================== --- branches/newcompiler/PyASM/tests/lexical_binding.py (rev 0) +++ branches/newcompiler/PyASM/tests/lexical_binding.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -0,0 +1,14 @@ +def f(x, y, z): + print x + print y + def g(): + print x + print z + g() + +def g(): + x = 1 + lambda: x + +f(3, 4, 5) + Added: branches/newcompiler/PyASM/tests/try_loops.py =================================================================== --- branches/newcompiler/PyASM/tests/try_loops.py (rev 0) +++ branches/newcompiler/PyASM/tests/try_loops.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -0,0 +1,23 @@ +for e in __name__: + try: + break + except: + pass + +for e in __name__: + try: + pass + except: + break + +for e in __name__: + try: + continue + except: + pass + +for e in __name__: + try: + pass + except: + continue Added: branches/newcompiler/PyASM/tests/try_nested.py =================================================================== --- branches/newcompiler/PyASM/tests/try_nested.py (rev 0) +++ branches/newcompiler/PyASM/tests/try_nested.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -0,0 +1,7 @@ +try: + pass +except: + try: + pass + except: + pass Added: branches/newcompiler/PyASM/tests/unpack.py =================================================================== --- branches/newcompiler/PyASM/tests/unpack.py (rev 0) +++ branches/newcompiler/PyASM/tests/unpack.py 2007-12-28 12:39:43 UTC (rev 3881) @@ -0,0 +1,40 @@ +[x] = iter([1]) +print x + +[x] = [1] +print x + +[x, y] = iter([1, 2]) +print x, y + +[x, y] = [1, 2] +print x, y + +try: + [x] = [1,2] +except ValueError: + pass +else: + print 'fail: expected ValueError when sequence too long' + +try: + [x, y] = [1] +except ValueError: + pass +else: + print 'fail: expected ValueError when sequence too short' + + +try: + [x] = iter([1,2]) +except ValueError: + pass +else: + print 'fail: expected ValueError when sequence too long' + +try: + [x, y] = iter([1]) +except ValueError: + pass +else: + print 'fail: expected ValueError when sequence too short' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |