[pypy-svn] r5369 - in pypy/trunk/src/pypy: scripttest scripttest/test tool

rocco at codespeak.net rocco at codespeak.net
Sun Jun 27 22:53:28 CEST 2004


Author: rocco
Date: Sun Jun 27 22:53:28 2004
New Revision: 5369

Added:
   pypy/trunk/src/pypy/scripttest/   (props changed)
   pypy/trunk/src/pypy/scripttest/__init__.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/autopath.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/grammar.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/grammar.txt   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/test/   (props changed)
   pypy/trunk/src/pypy/scripttest/test/__init__.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/test/autopath.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/test/test_grammar.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/test/test_tutorial.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/tutorial.py   (contents, props changed)
   pypy/trunk/src/pypy/scripttest/tutorial.txt   (contents, props changed)
   pypy/trunk/src/pypy/tool/app_level_diff.py   (contents, props changed)
Log:
* tool/app_level_diff.py

I hacked together a little tool for running a script at app level, and checking
its output against an expected output file. (Sort of like regrtest.py) I added 
a feature where the files can be sectioned off into multiple parts, to reduce
disk clutter. 

* scripttest directory

The start of using app_level_diff as a testing tool - I've converted the
CPython regression test test_grammar to it's use. Sectioning is incomplete -
the parts that are sectioned are mainly to isolate failures

I've also started to do a script made from the examples given in Guido's
tutorial. Incomplete as of now.

I've commented out the tests that fail - These have to do with lambdas,
the exec statement, exponentiation, and imaginary numbers. 


Added: pypy/trunk/src/pypy/scripttest/__init__.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/__init__.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1 @@
+#

Added: pypy/trunk/src/pypy/scripttest/autopath.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/autopath.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,80 @@
+"""
+self cloning, automatic path configuration 
+
+copy this into any subdirectory of pypy from which scripts need 
+to be run, typically all of the test subdirs. 
+The idea is that any such script simply issues
+
+    import autopath
+
+and this will make sure that the parent directory containing "pypy"
+is in sys.path. 
+
+If you modify the master "autopath.py" version (in pypy/tool/autopath.py) 
+you can directly run it which will copy itself on all autopath.py files
+it finds under the pypy root directory. 
+
+This module always provides these attributes:
+
+    pypydir    pypy root directory path 
+    this_dir   directory where this autopath.py resides 
+
+"""
+
+
+def __dirinfo(part):
+    """ return (partdir, this_dir) and insert parent of partdir
+    into sys.path. If the parent directories dont have the part
+    an EnvironmentError is raised."""
+
+    import sys, os 
+    try:
+        head = this_dir = os.path.abspath(os.path.dirname(__file__))
+    except NameError:
+        head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+
+    while head:
+        partdir = head
+        head, tail = os.path.split(head)
+        if tail == part:
+            try:
+                sys.path.remove(head)
+            except ValueError:
+                pass
+            sys.path.insert(0, head)
+            return partdir, this_dir
+        
+    raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path)
+
+def __clone():
+    """ clone master version of autopath.py into all subdirs """
+    from os.path import join, walk
+    if not this_dir.endswith(join('pypy','tool')):
+        raise EnvironmentError("can only clone master version "
+                               "'%s'" % join(pypydir, 'tool',_myname))
+
+
+    def sync_walker(arg, dirname, fnames):
+        if _myname in fnames:
+            fn = join(dirname, _myname)
+            f = open(fn, 'rwb+')
+            try:
+                if f.read() == arg:
+                    print "checkok", fn
+                else:
+                    print "syncing", fn
+                    f = open(fn, 'w')
+                    f.write(arg)
+            finally:
+                f.close()
+    s = open(join(pypydir, 'tool', _myname), 'rb').read()
+    walk(pypydir, sync_walker, s)
+
+_myname = 'autopath.py'
+
+# set guaranteed attributes
+
+pypydir, this_dir = __dirinfo('pypy')
+
+if __name__ == '__main__':
+    __clone()

Added: pypy/trunk/src/pypy/scripttest/grammar.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/grammar.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,788 @@
+# Python test set -- part 1, grammar.
+# This just tests whether the parser accepts them all.
+
+# NOTE: When you run this test as a script from the command line, you
+# get warnings about certain hex/oct constants.  Since those are
+# issued by the parser, you can't suppress them by adding a
+# filterwarnings() call to this module.
+
+# This is a modified version of the file found in the CPython Regression tests
+# Not all subsections have been broken apart - only enough to isolate
+# failures. Some sections need to remain combined due to dependancies on
+# definitions in previous sections.
+
+
+import sys
+
+def verify(condition, reason='test failed'):
+    if not condition:
+        print 'TestFailed -', reason
+
+def check_syntax(statement):
+    try:
+        compile(statement, '<string>', 'exec')
+    except SyntaxError:
+        pass
+    else:
+        print 'Missing SyntaxError: "%s"' % statement
+
+##! Section 1.
+        
+print '1. Parser'
+
+print '1.1 Tokens'
+
+print '1.1.1 Backslashes'
+
+# Backslash means line continuation:
+x = 1 \
++ 1
+if x != 2: print 'Test Failed -', 'backslash for line continuation'
+
+# Backslash does not means continuation in comments :\
+x = 0
+if x != 0: print 'Test Failed -', 'backslash ending comment'
+
+print '1.1.2 Numeric literals'
+
+print '1.1.2.1 Plain integers'
+if 0xff != 255: print 'Test Failed -', 'hex int'
+if 0377 != 255: print 'Test Failed -', 'octal int'
+if  2147483647   != 017777777777: print 'Test Failed -', 'large positive int'
+try:
+    from sys import maxint
+except ImportError:
+    maxint = 2147483647
+if maxint == 2147483647:
+    # The following test will start to fail in Python 2.4;
+    # change the 020000000000 to -020000000000
+    if -2147483647-1 != 020000000000: print 'Test Failed -', 'max negative int'
+    # XXX -2147483648
+    if 037777777777 != -1: print 'Test Failed -', 'oct -1'
+    if 0xffffffff != -1: print 'Test Failed -', 'hex -1'
+    for s in '2147483648', '040000000000', '0x100000000':
+        try:
+            x = eval(s)
+        except OverflowError:
+            print "OverflowError on huge integer literal " + `s`
+elif eval('maxint == 9223372036854775807'):
+    if eval('-9223372036854775807-1 != 01000000000000000000000'):
+        print 'Test Failed -', 'max negative int'
+    if eval('01777777777777777777777') != -1: print 'Test Failed -', 'oct -1'
+    if eval('0xffffffffffffffff') != -1: print 'Test Failed -', 'hex -1'
+    for s in '9223372036854775808', '02000000000000000000000', \
+             '0x10000000000000000':
+        try:
+            x = eval(s)
+        except OverflowError:
+            print "OverflowError on huge integer literal " + `s`
+else:
+    print 'Weird maxint value', maxint
+
+print '1.1.2.2 Long integers'
+x = 0L
+x = 0l
+x = 0xffffffffffffffffL
+x = 0xffffffffffffffffl
+x = 077777777777777777L
+x = 077777777777777777l
+x = 123456789012345678901234567890L
+x = 123456789012345678901234567890l
+
+print '1.1.2.3 Floating point'
+x = 3.14
+x = 314.
+x = 0.314
+# XXX x = 000.314
+x = .314
+x = 3e14
+x = 3E14
+x = 3e-14
+x = 3e+14
+x = 3.e14
+x = .3e14
+x = 3.1e4
+
+print '1.1.3 String literals'
+
+x = ''; y = ""; verify(len(x) == 0 and x == y)
+x = '\''; y = "'"; verify(len(x) == 1 and x == y and ord(x) == 39)
+x = '"'; y = "\""; verify(len(x) == 1 and x == y and ord(x) == 34)
+x = "doesn't \"shrink\" does it"
+y = 'doesn\'t "shrink" does it'
+verify(len(x) == 24 and x == y)
+x = "does \"shrink\" doesn't it"
+y = 'does "shrink" doesn\'t it'
+verify(len(x) == 24 and x == y)
+x = """
+The "quick"
+brown fox
+jumps over
+the 'lazy' dog.
+"""
+y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n'
+verify(x == y)
+y = '''
+The "quick"
+brown fox
+jumps over
+the 'lazy' dog.
+'''; verify(x == y)
+y = "\n\
+The \"quick\"\n\
+brown fox\n\
+jumps over\n\
+the 'lazy' dog.\n\
+"; verify(x == y)
+y = '\n\
+The \"quick\"\n\
+brown fox\n\
+jumps over\n\
+the \'lazy\' dog.\n\
+'; verify(x == y)
+
+
+print '1.2 Grammar'
+
+print 'single_input' # NEWLINE | simple_stmt | compound_stmt NEWLINE
+# XXX can't test in a script -- this rule is only used when interactive
+
+print 'file_input' # (NEWLINE | stmt)* ENDMARKER
+# Being tested as this very moment this very module
+
+print 'expr_input' # testlist NEWLINE
+# XXX Hard to test -- used only in calls to input()
+
+print 'eval_input' # testlist ENDMARKER
+x = eval('1, 0 or 1')
+
+print 'funcdef'
+### 'def' NAME parameters ':' suite
+### parameters: '(' [varargslist] ')'
+### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME]
+###            | ('**'|'*' '*') NAME)
+###            | fpdef ['=' test] (',' fpdef ['=' test])* [',']
+### fpdef: NAME | '(' fplist ')'
+### fplist: fpdef (',' fpdef)* [',']
+### arglist: (argument ',')* (argument | *' test [',' '**' test] | '**' test)
+### argument: [test '='] test   # Really [keyword '='] test
+def f1(): pass
+f1()
+f1(*())
+f1(*(), **{})
+def f2(one_argument): pass
+def f3(two, arguments): pass
+def f4(two, (compound, (argument, list))): pass
+def f5((compound, first), two): pass
+verify(f2.func_code.co_varnames == ('one_argument',))
+verify(f3.func_code.co_varnames == ('two', 'arguments'))
+if sys.platform.startswith('java'):
+    verify(f4.func_code.co_varnames ==
+           ('two', '(compound, (argument, list))', 'compound', 'argument',
+                        'list',))
+    verify(f5.func_code.co_varnames ==
+           ('(compound, first)', 'two', 'compound', 'first'))
+else:
+    verify(f4.func_code.co_varnames == ('two', '.2', 'compound',
+                                        'argument',  'list'))
+    verify(f5.func_code.co_varnames == ('.0', 'two', 'compound', 'first'))
+def a1(one_arg,): pass
+def a2(two, args,): pass
+def v0(*rest): pass
+def v1(a, *rest): pass
+def v2(a, b, *rest): pass
+def v3(a, (b, c), *rest): return a, b, c, rest
+if sys.platform.startswith('java'):
+    verify(v3.func_code.co_varnames == ('a', '(b, c)', 'rest', 'b', 'c'))
+else:
+    verify(v3.func_code.co_varnames == ('a', '.2', 'rest', 'b', 'c'))
+verify(v3(1, (2, 3), 4) == (1, 2, 3, (4,)))
+def d01(a=1): pass
+d01()
+d01(1)
+d01(*(1,))
+d01(**{'a':2})
+def d11(a, b=1): pass
+d11(1)
+d11(1, 2)
+d11(1, **{'b':2})
+def d21(a, b, c=1): pass
+d21(1, 2)
+d21(1, 2, 3)
+d21(*(1, 2, 3))
+d21(1, *(2, 3))
+d21(1, 2, *(3,))
+d21(1, 2, **{'c':3})
+def d02(a=1, b=2): pass
+d02()
+d02(1)
+d02(1, 2)
+d02(*(1, 2))
+d02(1, *(2,))
+d02(1, **{'b':2})
+d02(**{'a': 1, 'b': 2})
+def d12(a, b=1, c=2): pass
+d12(1)
+d12(1, 2)
+d12(1, 2, 3)
+def d22(a, b, c=1, d=2): pass
+d22(1, 2)
+d22(1, 2, 3)
+d22(1, 2, 3, 4)
+def d01v(a=1, *rest): pass
+d01v()
+d01v(1)
+d01v(1, 2)
+d01v(*(1, 2, 3, 4))
+d01v(*(1,))
+d01v(**{'a':2})
+def d11v(a, b=1, *rest): pass
+d11v(1)
+d11v(1, 2)
+d11v(1, 2, 3)
+def d21v(a, b, c=1, *rest): pass
+d21v(1, 2)
+d21v(1, 2, 3)
+d21v(1, 2, 3, 4)
+d21v(*(1, 2, 3, 4))
+d21v(1, 2, **{'c': 3})
+def d02v(a=1, b=2, *rest): pass
+d02v()
+d02v(1)
+d02v(1, 2)
+d02v(1, 2, 3)
+d02v(1, *(2, 3, 4))
+d02v(**{'a': 1, 'b': 2})
+def d12v(a, b=1, c=2, *rest): pass
+d12v(1)
+d12v(1, 2)
+d12v(1, 2, 3)
+d12v(1, 2, 3, 4)
+d12v(*(1, 2, 3, 4))
+d12v(1, 2, *(3, 4, 5))
+d12v(1, *(2,), **{'c': 3})
+def d22v(a, b, c=1, d=2, *rest): pass
+d22v(1, 2)
+d22v(1, 2, 3)
+d22v(1, 2, 3, 4)
+d22v(1, 2, 3, 4, 5)
+d22v(*(1, 2, 3, 4))
+d22v(1, 2, *(3, 4, 5))
+d22v(1, *(2, 3), **{'d': 4})
+
+print 'selectors'
+### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
+### subscript: expr | [expr] ':' [expr]
+f1()
+f2(1)
+f2(1,)
+f3(1, 2)
+f3(1, 2,)
+f4(1, (2, (3, 4)))
+v0()
+v0(1)
+v0(1,)
+v0(1,2)
+v0(1,2,3,4,5,6,7,8,9,0)
+v1(1)
+v1(1,)
+v1(1,2)
+v1(1,2,3)
+v1(1,2,3,4,5,6,7,8,9,0)
+v2(1,2)
+v2(1,2,3)
+v2(1,2,3,4)
+v2(1,2,3,4,5,6,7,8,9,0)
+v3(1,(2,3))
+v3(1,(2,3),4)
+v3(1,(2,3),4,5,6,7,8,9,0)
+
+print
+##! Section lambdef
+
+### lambdef: 'lambda' [varargslist] ':' test
+print 'lambdef'
+l1 = lambda : 0
+verify(l1() == 0)
+l2 = lambda : a[d] # XXX just testing the expression
+l3 = lambda : [2 < x for x in [-1, 3, 0L]]
+verify(l3() == [0, 1, 0])
+l4 = lambda x = lambda y = lambda z=1 : z : y() : x()
+verify(l4() == 1)
+l5 = lambda x, y, z=2: x + y + z
+verify(l5(1, 2) == 5)
+verify(l5(1, 2, 3) == 6)
+check_syntax("lambda x: x = 2")
+
+print
+##! Section simple_stmt
+
+### stmt: simple_stmt | compound_stmt
+# Tested below
+
+### simple_stmt: small_stmt (';' small_stmt)* [';']
+print 'simple_stmt'
+x = 1; pass; del x
+
+### small_stmt: expr_stmt | print_stmt  | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt
+# Tested below
+
+print 'expr_stmt' # (exprlist '=')* exprlist
+1
+1, 2, 3
+x = 1
+x = 1, 2, 3
+x = y = z = 1, 2, 3
+x, y, z = 1, 2, 3
+abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4)
+# NB these variables are deleted below
+
+check_syntax("x + 1 = 1")
+check_syntax("a + 1 = b + 2")
+
+print 'del_stmt' # 'del' exprlist
+del abc
+del x, y, (z, xyz)
+
+print 'print_stmt' # 'print' (test ',')* [test]
+print 1, 2, 3
+print 1, 2, 3,
+print
+print 0 or 1, 0 or 1,
+print 0 or 1
+
+
+print
+##! Section extended print_stmt
+
+print 'extended print_stmt' # 'print' '>>' test ','
+import sys
+print >> sys.stdout, 1, 2, 3
+print >> sys.stdout, 1, 2, 3,
+print >> sys.stdout
+print >> sys.stdout, 0 or 1, 0 or 1,
+print >> sys.stdout, 0 or 1
+
+# test printing to an instance
+class Gulp:
+    def write(self, msg): pass
+
+gulp = Gulp()
+print >> gulp, 1, 2, 3
+print >> gulp, 1, 2, 3,
+print >> gulp
+print >> gulp, 0 or 1, 0 or 1,
+print >> gulp, 0 or 1
+
+# test print >> None
+def driver():
+    oldstdout = sys.stdout
+    sys.stdout = Gulp()
+    try:
+        tellme(Gulp())
+        tellme()
+    finally:
+        sys.stdout = oldstdout
+
+# we should see this once
+def tellme(file=sys.stdout):
+    print >> file, 'hello world'
+
+driver()
+
+# we should not see this at all
+def tellme(file=None):
+    print >> file, 'goodbye universe'
+
+driver()
+
+# syntax errors
+check_syntax('print ,')
+check_syntax('print >> x,')
+
+print
+##! Section pass_stmt
+print 'pass_stmt' # 'pass'
+pass
+
+print 'flow_stmt' # break_stmt | continue_stmt | return_stmt | raise_stmt
+# Tested below
+
+print 'break_stmt' # 'break'
+while 1: break
+
+print
+##! Section continue_stmt
+print 'continue_stmt' # 'continue'
+i = 1
+while i: i = 0; continue
+
+msg = ""
+while not msg:
+    msg = "continue + try/except ok"
+    try:
+        continue
+        msg = "continue failed to continue inside try"
+    except:
+        msg = "continue inside try called except block"
+print msg
+
+msg = ""
+while not msg:
+    msg = "finally block not called"
+    try:
+        continue
+    finally:
+        msg = "continue + try/finally ok"
+print msg
+
+
+# This test warrants an explanation. It is a test specifically for SF bugs
+# #463359 and #462937. The bug is that a 'break' statement executed or
+# exception raised inside a try/except inside a loop, *after* a continue
+# statement has been executed in that loop, will cause the wrong number of
+# arguments to be popped off the stack and the instruction pointer reset to
+# a very small number (usually 0.) Because of this, the following test
+# *must* written as a function, and the tracking vars *must* be function
+# arguments with default values. Otherwise, the test will loop and loop.
+
+print "testing continue and break in try/except in loop"
+def test_break_continue_loop(extra_burning_oil = 1, count=0):
+    big_hippo = 2
+    while big_hippo:
+        count += 1
+        try:
+            if extra_burning_oil and big_hippo == 1:
+                extra_burning_oil -= 1
+                break
+            big_hippo -= 1
+            continue
+        except:
+            raise
+    if count > 2 or big_hippo <> 1:
+        print "continue then break in try/except in loop broken!"
+test_break_continue_loop()
+
+print
+##! Section return_stmt
+
+print 'return_stmt' # 'return' [testlist]
+def g1(): return
+def g2(): return 1
+g1()
+x = g2()
+
+print 'raise_stmt' # 'raise' test [',' test]
+try: raise RuntimeError, 'just testing'
+except RuntimeError: pass
+try: raise KeyboardInterrupt
+except KeyboardInterrupt: pass
+
+print 'import_stmt' # 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*)
+import sys
+import time, sys
+from time import time
+from sys import *
+from sys import path, argv
+
+
+print
+##! Section global_stmt
+
+print 'global_stmt' # 'global' NAME (',' NAME)*
+def f():
+    global a
+    global a, b
+    global one, two, three, four, five, six, seven, eight, nine, ten
+
+print
+##! Section exec_stmt
+
+print 'exec_stmt' # 'exec' expr ['in' expr [',' expr]]
+def f():
+    z = None
+    del z
+    exec 'z=1+1\n'
+    if z != 2: print 'Test Failed -', 'exec \'z=1+1\'\\n'
+    del z
+    exec 'z=1+1'
+    if z != 2: print 'Test Failed -', 'exec \'z=1+1\''
+    z = None
+    del z
+    import types
+    if hasattr(types, "UnicodeType"):
+        exec r"""if 1:
+    exec u'z=1+1\n'
+    if z != 2: print 'Test Failed -', 'exec u\'z=1+1\'\\n'
+    del z
+    exec u'z=1+1'
+    if z != 2: print 'Test Failed -', 'exec u\'z=1+1\''
+"""
+f()
+g = {}
+exec 'z = 1' in g
+if g.has_key('__builtins__'): del g['__builtins__']
+if g != {'z': 1}: print 'Test Failed -', 'exec \'z = 1\' in g'
+g = {}
+l = {}
+
+import warnings
+warnings.filterwarnings("ignore", "global statement", module="<string>")
+exec 'global a; a = 1; b = 2' in g, l
+if g.has_key('__builtins__'): del g['__builtins__']
+if l.has_key('__builtins__'): del l['__builtins__']
+if (g, l) != ({'a':1}, {'b':2}): print 'Test Failed -', 'exec ... in g (%s), l (%s)' %(g,l)
+
+print
+##! Section assert_stmt
+
+print "assert_stmt" # assert_stmt: 'assert' test [',' test]
+assert 1
+assert 1, 1
+assert lambda x:x
+assert 1, lambda x:x+1
+
+### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+# Tested below
+
+print 'if_stmt' # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+if 1: pass
+if 1: pass
+else: pass
+if 0: pass
+elif 0: pass
+if 0: pass
+elif 0: pass
+elif 0: pass
+elif 0: pass
+else: pass
+
+print 'while_stmt' # 'while' test ':' suite ['else' ':' suite]
+while 0: pass
+while 0: pass
+else: pass
+
+print 'for_stmt' # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
+for i in 1, 2, 3: pass
+for i, j, k in (): pass
+else: pass
+class Squares:
+    def __init__(self, max):
+        self.max = max
+        self.sofar = []
+    def __len__(self): return len(self.sofar)
+    def __getitem__(self, i):
+        if not 0 <= i < self.max: raise IndexError
+        n = len(self.sofar)
+        while n <= i:
+            self.sofar.append(n*n)
+            n = n+1
+        return self.sofar[i]
+n = 0
+for x in Squares(10): n = n+x
+if n != 285: print 'Test Failed -', 'for over growing sequence'
+
+print 'try_stmt'
+### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
+###         | 'try' ':' suite 'finally' ':' suite
+### except_clause: 'except' [expr [',' expr]]
+try:
+    1/0
+except ZeroDivisionError:
+    pass
+else:
+    pass
+try: 1/0
+except EOFError: pass
+except TypeError, msg: pass
+except RuntimeError, msg: pass
+except: pass
+else: pass
+try: 1/0
+except (EOFError, TypeError, ZeroDivisionError): pass
+try: 1/0
+except (EOFError, TypeError, ZeroDivisionError), msg: pass
+try: pass
+finally: pass
+
+print 'suite' # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
+if 1: pass
+if 1:
+    pass
+if 1:
+    #
+    #
+    #
+    pass
+    pass
+    #
+    pass
+    #
+
+print 'test'
+### and_test ('or' and_test)*
+### and_test: not_test ('and' not_test)*
+### not_test: 'not' not_test | comparison
+if not 1: pass
+if 1 and 1: pass
+if 1 or 1: pass
+if not not not 1: pass
+if not 1 and 1 and 1: pass
+if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass
+
+print 'comparison'
+### comparison: expr (comp_op expr)*
+### comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+if 1: pass
+x = (1 == 1)
+if 1 == 1: pass
+if 1 != 1: pass
+if 1 <> 1: pass
+if 1 < 1: pass
+if 1 > 1: pass
+if 1 <= 1: pass
+if 1 >= 1: pass
+if 1 is 1: pass
+if 1 is not 1: pass
+if 1 in (): pass
+if 1 not in (): pass
+if 1 < 1 > 1 == 1 >= 1 <= 1 <> 1 != 1 in 1 not in 1 is 1 is not 1: pass
+
+print 'binary mask ops'
+x = 1 & 1
+x = 1 ^ 1
+x = 1 | 1
+
+print 'shift ops'
+x = 1 << 1
+x = 1 >> 1
+x = 1 << 1 >> 1
+
+print 'additive ops'
+x = 1
+x = 1 + 1
+x = 1 - 1 - 1
+x = 1 - 1 + 1 - 1 + 1
+
+print 'multiplicative ops'
+x = 1 * 1
+x = 1 / 1
+x = 1 % 1
+x = 1 / 1 * 1 % 1
+
+print 'unary ops'
+x = +1
+x = -1
+x = ~1
+x = ~1 ^ 1 & 1 | 1 & 1 ^ -1
+x = -1*1/1 + 1*1 - ---1*1
+
+print
+import sys, time
+c = sys.path[0]
+x = time.time()
+x = sys.modules['time'].time()
+a = '01234'
+c = a[0]
+c = a[-1]
+s = a[0:5]
+s = a[:5]
+s = a[0:]
+s = a[:]
+s = a[-5:]
+s = a[:-1]
+s = a[-4:-3]
+
+print 'atoms'
+### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING
+### dictmaker: test ':' test (',' test ':' test)* [',']
+
+x = (1)
+x = (1 or 2 or 3)
+x = (1 or 2 or 3, 2, 3)
+
+x = []
+x = [1]
+x = [1 or 2 or 3]
+x = [1 or 2 or 3, 2, 3]
+x = []
+
+x = {}
+x = {'one': 1}
+x = {'one': 1,}
+x = {'one' or 'two': 1 or 2}
+x = {'one': 1, 'two': 2}
+x = {'one': 1, 'two': 2,}
+x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6}
+
+x = `x`
+x = `1 or 2 or 3`
+x = x
+x = 'x'
+x = 123
+
+### exprlist: expr (',' expr)* [',']
+### testlist: test (',' test)* [',']
+# These have been exercised enough above
+
+print 'classdef' # 'class' NAME ['(' testlist ')'] ':' suite
+class B: pass
+class C1(B): pass
+class C2(B): pass
+class D(C1, C2, B): pass
+class C:
+    def meth1(self): pass
+    def meth2(self, arg): pass
+    def meth3(self, a1, a2): pass
+
+print
+##! Section list_comps
+    
+# list comprehension tests
+nums = [1, 2, 3, 4, 5]
+strs = ["Apple", "Banana", "Coconut"]
+spcs = ["  Apple", " Banana ", "Coco  nut  "]
+
+print [s.strip() for s in spcs]
+print [3 * x for x in nums]
+print [x for x in nums if x > 2]
+print [(i, s) for i in nums for s in strs]
+print [(i, s) for i in nums for s in [f for f in strs if "n" in f]]
+print [(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)]
+
+def test_in_func(l):
+    return [None < x < 3 for x in l if x > 2]
+
+print test_in_func(nums)
+
+def test_nested_front():
+    print [[y for y in [x, x + 1]] for x in [1,3,5]]
+
+test_nested_front()
+
+check_syntax("[i, s for i in nums for s in strs]")
+check_syntax("[x if y]")
+
+suppliers = [
+  (1, "Boeing"),
+  (2, "Ford"),
+  (3, "Macdonalds")
+]
+
+parts = [
+  (10, "Airliner"),
+  (20, "Engine"),
+  (30, "Cheeseburger")
+]
+
+suppart = [
+  (1, 10), (1, 20), (2, 20), (3, 30)
+]
+
+print [
+  (sname, pname)
+    for (sno, sname) in suppliers
+      for (pno, pname) in parts
+        for (sp_sno, sp_pno) in suppart
+          if sno == sp_sno and pno == sp_pno
+]

Added: pypy/trunk/src/pypy/scripttest/grammar.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/grammar.txt	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,86 @@
+##! Section 1.
+1. Parser
+1.1 Tokens
+1.1.1 Backslashes
+1.1.2 Numeric literals
+1.1.2.1 Plain integers
+1.1.2.2 Long integers
+1.1.2.3 Floating point
+1.1.3 String literals
+1.2 Grammar
+single_input
+file_input
+expr_input
+eval_input
+funcdef
+selectors
+
+##! Section lambdef
+lambdef
+
+##! Section simple_stmt
+simple_stmt
+expr_stmt
+del_stmt
+print_stmt
+1 2 3
+1 2 3
+1 1 1
+
+##! Section extended print_stmt
+extended print_stmt
+1 2 3
+1 2 3
+1 1 1
+hello world
+
+##! Section pass_stmt
+pass_stmt
+flow_stmt
+break_stmt
+
+##! Section continue_stmt
+continue_stmt
+continue + try/except ok
+continue + try/finally ok
+testing continue and break in try/except in loop
+
+##! Section return_stmt
+return_stmt
+raise_stmt
+import_stmt
+
+##! Section global_stmt
+global_stmt
+
+##! Section exec_stmt
+exec_stmt
+
+##! Section assert_stmt
+assert_stmt
+if_stmt
+while_stmt
+for_stmt
+try_stmt
+suite
+test
+comparison
+binary mask ops
+shift ops
+additive ops
+multiplicative ops
+unary ops
+
+atoms
+classdef
+
+##! Section list_comps
+['Apple', 'Banana', 'Coco  nut']
+[3, 6, 9, 12, 15]
+[3, 4, 5]
+[(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]
+[(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), (5, 'Banana'), (5, 'Coconut')]
+[[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]]
+[False, False, False]
+[[1, 2], [3, 4], [5, 6]]
+[('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), ('Macdonalds', 'Cheeseburger')]
\ No newline at end of file

Added: pypy/trunk/src/pypy/scripttest/test/__init__.py
==============================================================================

Added: pypy/trunk/src/pypy/scripttest/test/autopath.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/test/autopath.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,80 @@
+"""
+self cloning, automatic path configuration 
+
+copy this into any subdirectory of pypy from which scripts need 
+to be run, typically all of the test subdirs. 
+The idea is that any such script simply issues
+
+    import autopath
+
+and this will make sure that the parent directory containing "pypy"
+is in sys.path. 
+
+If you modify the master "autopath.py" version (in pypy/tool/autopath.py) 
+you can directly run it which will copy itself on all autopath.py files
+it finds under the pypy root directory. 
+
+This module always provides these attributes:
+
+    pypydir    pypy root directory path 
+    this_dir   directory where this autopath.py resides 
+
+"""
+
+
+def __dirinfo(part):
+    """ return (partdir, this_dir) and insert parent of partdir
+    into sys.path. If the parent directories dont have the part
+    an EnvironmentError is raised."""
+
+    import sys, os 
+    try:
+        head = this_dir = os.path.abspath(os.path.dirname(__file__))
+    except NameError:
+        head = this_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
+
+    while head:
+        partdir = head
+        head, tail = os.path.split(head)
+        if tail == part:
+            try:
+                sys.path.remove(head)
+            except ValueError:
+                pass
+            sys.path.insert(0, head)
+            return partdir, this_dir
+        
+    raise EnvironmentError, "'%s' missing in '%r'" % (pathpart,this_path)
+
+def __clone():
+    """ clone master version of autopath.py into all subdirs """
+    from os.path import join, walk
+    if not this_dir.endswith(join('pypy','tool')):
+        raise EnvironmentError("can only clone master version "
+                               "'%s'" % join(pypydir, 'tool',_myname))
+
+
+    def sync_walker(arg, dirname, fnames):
+        if _myname in fnames:
+            fn = join(dirname, _myname)
+            f = open(fn, 'rwb+')
+            try:
+                if f.read() == arg:
+                    print "checkok", fn
+                else:
+                    print "syncing", fn
+                    f = open(fn, 'w')
+                    f.write(arg)
+            finally:
+                f.close()
+    s = open(join(pypydir, 'tool', _myname), 'rb').read()
+    walk(pypydir, sync_walker, s)
+
+_myname = 'autopath.py'
+
+# set guaranteed attributes
+
+pypydir, this_dir = __dirinfo('pypy')
+
+if __name__ == '__main__':
+    __clone()

Added: pypy/trunk/src/pypy/scripttest/test/test_grammar.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/test/test_grammar.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,46 @@
+import autopath
+import os, os.path
+from pypy.tool import testit, app_level_diff 
+
+filename = os.path.join(os.path.dirname(__file__), os.pardir, 'grammar.py')
+
+# Test the functionallity of the CPython test_grammar.py regression test
+
+class TestGrammar(testit.IntTestCase):
+    def setUp(self):
+        self.space = testit.objspace()
+    def _section_test(self, section):
+        diff = app_level_diff.compare(self.space, filename, section)
+        if diff:
+            raise AssertionError('Tutorial test failed - ' \
+                                 "run test_grammar.details('%s')" % section)
+    def test_Section_1(self):
+        self._section_test('Section 1.')
+##    def xxx_test_Section_lambdef(self):
+##        self._section_test('Section lambdef')
+    def test_Section_simple_stmt(self):
+        self._section_test('Section simple_stmt')
+    def test_Section_extended_print_stmt(self):
+        self._section_test('Section extended print_stmt')
+    def test_Section_pass_stmt(self):
+        self._section_test('Section pass_stmt')
+    def test_Section_continue_stmt(self):
+        self._section_test('Section continue_stmt')
+    def test_Section_return_stmt(self):
+        self._section_test('Section return_stmt')
+    def test_Section_global_stmt(self):
+        self._section_test('Section global_stmt')
+##    def xxx_test_Section_exec_stmt(self):
+##        self._section_test('Section exec_stmt')
+    def test_Section_assert_stmt(self):
+        self._section_test('Section assert_stmt')
+##    def xxx_test_Section_list_comps(self):
+##        self._section_test('Section list_comps')
+        
+
+def details(section):
+    diff = app_level_diff.compare(testit.objspace(), filename, section)
+    print diff
+    
+if __name__ == '__main__':
+    testit.main()

Added: pypy/trunk/src/pypy/scripttest/test/test_tutorial.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/test/test_tutorial.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,34 @@
+import autopath
+import os, os.path
+from pypy.tool import testit, app_level_diff 
+
+filename = os.path.join(os.path.dirname(__file__), os.pardir, 'tutorial.py')
+
+# Test the functionallity of Guido's tutorial
+
+class TestTutorial(testit.IntTestCase):
+    def setUp(self):
+        self.space = testit.objspace()
+    def _section_test(self, section):
+        diff = app_level_diff.compare(self.space, filename, section)
+        if diff:
+            raise AssertionError('Tutorial test failed - ' \
+                                 "run test_tutorial.details('%s')" % section)
+    def test_Section_2_1_2(self):
+        self._section_test('Section 2.1.2')
+    def test_Section_3_1_1a(self):
+        self._section_test('Section 3.1.1a')
+##    def xxx_test_Section_3_1_1b(self):
+##        self._section_test('Section 3.1.1b')
+##    def xxx_test_Section_3_1_1c(self):
+##        self._section_test('Section 3.1.1c')
+    def test_Section_3_1_2(self):
+        self._section_test('Section 3.1.2')
+        
+
+def details(section):
+    diff = app_level_diff.compare(testit.objspace(), filename, section)
+    print diff
+    
+if __name__ == '__main__':
+    testit.main()

Added: pypy/trunk/src/pypy/scripttest/tutorial.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/tutorial.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,137 @@
+"""Run code from Guido's Tutorial, to make sure it works under PyPy.
+
+Note that as a script, we have to explicitly print stuff to see it.
+"""
+
+##! Section 2.1.2
+
+the_world_is_flat = 1
+
+if the_world_is_flat:
+    print "Be careful not to fall off!"
+
+print
+##! Section 3.1.1a
+
+print repr(2+2)
+print repr((50-5*6)/4)
+print repr(7/3)
+print repr(7/-3)
+
+width = 20
+height = 5*9
+print repr(width * height)
+
+x = y = z = 0  # Zero x, y and z
+print repr(x)
+print repr(y)
+print repr(z)
+
+
+print repr(3 * 3.75 / 1.5)
+print repr(7.0 / 2)
+
+print
+##! Section 3.1.1b
+
+print repr(1j * 1J)
+
+print repr(1j * complex(0,1))
+print repr(3+1j*3)
+print repr((3+1j)*3)
+print repr((1+2j)/(1+1j))
+
+a=1.5+0.5j
+print repr(a.real)
+print repr(a.imag)
+
+a=3.0+4.0j
+try:
+    print repr(float(a))
+except TypeError:
+    print "Got TypeError for repr(float(a))"
+print repr(a.real)
+print repr(a.imag)
+print repr(abs(a))
+
+print
+##! Section 3.1.1c
+
+#Mock up '_' variable use
+tax = 12.5 / 100
+price = 100.50
+print repr(price * tax)
+_ = price * tax
+print repr(price + _)
+_ = price + _
+print repr(round(_, 2))
+
+print
+##! Section 3.1.2
+
+print repr('spam eggs')
+print repr('doesn\'t')
+print repr("doesn't")
+print repr('"Yes," he said.')
+print repr("\"Yes,\" he said.")
+print repr('"Isn\'t," she said.')
+
+hello = "This is a rather long string containing\n\
+several lines of text just as you would do in C.\n\
+    Note that whitespace at the beginning of the line is\
+ significant."
+print hello
+hello = r"This is a rather long string containing\n\
+several lines of text much as you would do in C."
+print hello
+print """
+Usage: thingy [OPTIONS] 
+     -h                        Display this usage message
+     -H hostname               Hostname to connect to
+"""
+
+word = 'Help' + 'A'
+print repr(word)
+print repr('<' + word*5 + '>')
+print repr('str' 'ing')
+print repr('str'.strip() + 'ing')
+print repr(word[4])
+print repr(word[0:2])
+print repr(word[2:4])
+print repr(word[:2])
+print repr(word[2:])
+
+try:
+    word[0] = 'x'
+except TypeError:
+    print "Got a TypeError with word[0] = 'x'"
+try:
+    word[:1] = 'Splat'
+except TypeError:
+    print "Got a TypeError with word[:1] = 'Splat'"
+print repr('x' + word[1:])
+print repr('Splat' + word[4])
+print repr(word[:2] + word[2:])
+print repr(word[:3] + word[3:])
+
+print repr(word[1:100])
+print repr(word[10:])
+print repr(word[2:1])
+print repr(word[-1])
+print repr(word[-2])
+print repr(word[-2:])
+print repr(word[:-2])
+print repr(word[-0])
+
+print repr(word[-100:])
+try:
+    print repr(word[-10])
+except IndexError:
+    print "Got IndexError with word[-10]"
+
+s = 'supercalifragilisticexpialidocious'
+print repr(len(s))
+
+print
+##! Section 3.1.3
+

Added: pypy/trunk/src/pypy/scripttest/tutorial.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/scripttest/tutorial.txt	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,78 @@
+##! Section 2.1.2
+Be careful not to fall off!
+
+##! Section 3.1.1a
+4
+5
+2
+-3
+900
+0
+0
+0
+7.5
+3.5
+
+##! Section 3.1.1b
+(-1+0j)
+(-1+0j)
+(3+3j)
+(9+3j)
+(1.5+0.5j)
+1.5
+0.5
+Got TypeError for repr(float(a))
+3.0
+4.0
+5.0
+
+##! Section 3.1.1c
+12.5625
+113.0625
+113.06
+
+##! Section 3.1.2
+'spam eggs'
+"doesn't"
+"doesn't"
+'"Yes," he said.'
+'"Yes," he said.'
+'"Isn\'t," she said.'
+This is a rather long string containing
+several lines of text just as you would do in C.
+    Note that whitespace at the beginning of the line is significant.
+This is a rather long string containing\n\
+several lines of text much as you would do in C.
+
+Usage: thingy [OPTIONS] 
+     -h                        Display this usage message
+     -H hostname               Hostname to connect to
+
+'HelpA'
+'<HelpAHelpAHelpAHelpAHelpA>'
+'string'
+'string'
+'A'
+'He'
+'lp'
+'He'
+'lpA'
+Got a TypeError with word[0] = 'x'
+Got a TypeError with word[:1] = 'Splat'
+'xelpA'
+'SplatA'
+'HelpA'
+'HelpA'
+'elpA'
+''
+''
+'A'
+'p'
+'pA'
+'Hel'
+'H'
+'HelpA'
+Got IndexError with word[-10]
+34
+
+##! Section 3.1.3

Added: pypy/trunk/src/pypy/tool/app_level_diff.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/tool/app_level_diff.py	Sun Jun 27 22:53:28 2004
@@ -0,0 +1,123 @@
+import autopath
+import difflib
+
+leadincode = """
+import sys
+
+class PseudoOut:
+    def __init__(self):
+        self.out = []
+    def flush(self):
+        pass
+    def write(self, item):
+        self.out.append(str(item))
+    def writelines(self, items):
+        for item in items:
+            self.out.append(str(item))
+    def getoutput(self):
+        '''Not part of the output stream interface.'''
+        return ''.join(self.out)
+
+out = PseudoOut()
+
+oldout, sys.stdout = sys.stdout, out
+olderr, sys.stderr = sys.stderr, out
+"""
+
+cleanupcode = """
+sys.stdout = oldout
+sys.stderr = olderr
+
+retval = out.getoutput()
+"""
+
+def runcode(space, source, filename, w_glob):
+    w = space.wrap
+    w_compile = space.getitem(space.builtin.w_dict, w('compile'))
+    w_code = space.call_function(w_compile, w(source), w(filename), w('exec'))
+    pycode = space.unwrap(w_code)
+    pycode.exec_code(space, w_glob, w_glob)
+    
+def getoutput(space, source, filename):
+    w_bookendglobals = space.newdict([])
+    runcode(space, leadincode, '<str>', w_bookendglobals)
+    w_scratchglobals = space.newdict([])
+    runcode(space, source, filename, w_scratchglobals)
+    runcode(space, cleanupcode, '<str>', w_bookendglobals)
+    #Get 'retval' from the bookendglobals - contains output
+    return space.unwrap(space.getitem(w_bookendglobals, space.wrap('retval')))
+
+def getsection(linelist, section_name = None, savelineno = False):
+    #Strips out all '##!' line delimiters.
+    #If section_name is None, return just the leadin code.
+    #If section_name is not present in the linelist, raise an error.
+    #If savelineno is true, add fake lines to keep the absolute line
+    #   numbers the same as in the original file.
+    
+    #Leadin code is run by all sections
+    save = True
+    seen = False
+    accumulator = []
+    for line in linelist:
+        if line[:3] == '##!':
+            if line[3:].strip() == section_name or section_name is None:
+                save = True
+                seen = True
+            else:
+                save = False
+            if savelineno:
+                accumulator.append('\n')
+        elif save:
+            accumulator.append(line)
+        elif savelineno:
+            accumulator.append('\n')
+    if not seen:
+        raise KeyError('Section "'+section_name+'" not found in file.')
+    return accumulator
+            
+def compare(space, filename, section = None):
+    """Compare an application level script to expected output.
+
+    The output of 'filename' when run at application level as a script
+    is compared to the appropriate '.txt' file (e.g. test.py -> test.txt).
+    If no difference is seen, the function returns an empty string (False).
+    If a difference is seen, the diffenrence in the form of a unified diff is
+    returned as a multiline string (True).
+
+    The optional section argument allows selective execution of portions of
+    the code. It looks for blocks delimited by '##! <section_name>' lines,
+    where <section_name> is the string passed to the section argument. None
+    executes the entire script. The output file should also be delimited by
+    the same section markers.
+    """
+    f = file(filename, 'r')
+    try:
+        sourcelines = f.readlines()
+    finally:
+        f.close()
+    source = ''.join(getsection(sourcelines, section, savelineno = True))
+    output = getoutput(space, source, filename).splitlines(True)
+
+    outfilename = '.'.join(filename.split('.')[:-1]+['txt'])
+    try:
+        f = file(outfilename, 'r')
+        try:
+            outfilelines = f.readlines()
+        finally:
+            f.close()
+    except KeyboardInterrupt:
+        pass
+    except:
+        #If there are problems loading outfile, assume null output
+        outfilelines = ['']
+        
+    outfile = getsection(outfilelines, section)
+    if not outfile and not output: #Catch degenerate case where both are empty
+        return ''
+    diff = list(difflib.unified_diff(outfile, output,
+                                     fromfile=outfilename, tofile=filename))
+
+    if diff:
+        return ''.join(diff)
+    else:
+        return ''



More information about the Pypy-commit mailing list