[py-svn] r7963 - in py/dist: . example/test py py/builtin/testing py/code py/code/testing py/execnet py/execnet/bin py/magic py/path py/path/extpy py/path/gateway py/path/local py/path/local/popen5 py/path/svn py/path/test py/test py/test/report/text py/test/test py/test/test/data

hpk at codespeak.net hpk at codespeak.net
Wed Dec 22 10:37:33 CET 2004


Author: hpk
Date: Wed Dec 22 10:37:32 2004
New Revision: 7963

Added:
   py/dist/py/conftest.py   (contents, props changed)
      - copied, changed from r7948, py/dist/conftest.py
Removed:
   py/dist/conftest.py
   py/dist/py/magic/dyncode.py
   py/dist/py/magic/test_dyncode.py
Modified:
   py/dist/example/test/failure_demo.py
   py/dist/py/__init__.py
   py/dist/py/builtin/testing/   (props changed)
   py/dist/py/code/excinfo.py
   py/dist/py/code/source.py
   py/dist/py/code/testing/test_excinfo.py
   py/dist/py/code/testing/test_source.py
   py/dist/py/execnet/bin/   (props changed)
   py/dist/py/execnet/bin/startserver.py   (props changed)
   py/dist/py/execnet/channel.py   (props changed)
   py/dist/py/execnet/message.py   (props changed)
   py/dist/py/execnet/test_gateway.py   (props changed)
   py/dist/py/magic/invoke.py
   py/dist/py/magic/test_invoke.py
   py/dist/py/path/common.py
   py/dist/py/path/extpy/extpy.py
   py/dist/py/path/extpy/inc_pseudofs.py   (props changed)
   py/dist/py/path/extpy/inc_test_extpy.py   (props changed)
   py/dist/py/path/gateway/channeltest.py
   py/dist/py/path/gateway/channeltest2.py
   py/dist/py/path/gateway/remotepath.py
   py/dist/py/path/local/local.py
   py/dist/py/path/local/popen5/   (props changed)
   py/dist/py/path/local/popen5/__init__.py   (props changed)
   py/dist/py/path/local/popen5/subprocess.py   (props changed)
   py/dist/py/path/local/popen5/test_subprocess.py   (props changed)
   py/dist/py/path/local/test_local.py
   py/dist/py/path/local/test_posix.py   (contents, props changed)
   py/dist/py/path/svn/svncommon.py
   py/dist/py/path/test/fscommon.py
   py/dist/py/test/defaultconfig.py   (contents, props changed)
   py/dist/py/test/item.py   (props changed)
   py/dist/py/test/raises.py
   py/dist/py/test/report/text/reporter.py
   py/dist/py/test/report/text/summary.py
   py/dist/py/test/test/data/disabled.py   (props changed)
   py/dist/py/test/test/test_setup_nested.py   (props changed)
Log:
ok, sorry for this *huge* checkin ... but i fixed/changed so many 
details during my last train ride that i can't be bothered 
to isolate them. Here is the summary (please read if you 
were using py.magic.dyncode because this is gone now!): 

- got rid of py.magic.dyncode in favour of the cleaner 
  few py.code.* methods. py.code is the place to look 
  for if you are doing dynamic code generation, e.g. 

    co = py.code.compile(source) 

  will do the compile that will let you access its 
  source code with 

    print str(py.code.Source(co))
    
  py.code.Source is an object that offers some more 
  nice methods and flexible ways to construct dynamic 
  code like 

    source = py.code.Source("""
        def f(x): 
            pass 
    """)

  If you now do source.compile() the indentation will 
  not be a problem etc.pp.  I need to write documetnation 
  for this as the API is stabilizing. 

- refactored the test-text-reporter to use the higher 
  level py.code.* introspection model.  Basically 
  Source, ExceptionInfo and *Frame wrap cpython's 
  according objects and present clean helper methods. 

  NOTE that py.code.* and other py lib introspection 
  code (e.g. py.path.extpy().getfilelino() will always 
  give you linenumbers starting from 0.  So if you 
  display linenumbers to the user that you got from 
  py.code.* somewhere be sure to +1 it. 

- refactored the output of the text reporter to be 
  more clean.  Please suggest improvements! 

- refactored execnet code to use more explicit 
  names (Armin is a mathematician who has no problems 
  keeping the meaning of 'c', 'n' and so on in his
  mind but for the rest of us it's nice to read 
  'channel' and 'id' instead :-) 

- moved the py libs test-configuration files to 
  within the py lib so that if you use 'dist/py' 
  as an external it's still there. 

- the path.get() method now always returns a list. 
  I plan to make this method an underscore method 
  because it is more of an implementation detail now. 
  The official nice way to access the according information 
  is 

    path.basename    # property returning the basename 
    path.ext         # property returning the extension part (with the dot) 
    path.purebasename # property returning the basename without extension 

  and so on. 

- fixeol 



Deleted: /py/dist/conftest.py
==============================================================================
--- /py/dist/conftest.py	Wed Dec 22 10:37:32 2004
+++ (empty file)
@@ -1,20 +0,0 @@
-#pythonexecutables = ('python2.2', 'python2.3',) 
-#pythonexecutable = 'python2.2' 
-
-# in the future we want to be able to say here: 
-#def setup_module(extpy):
-#    mod = extpy.resolve() 
-#    mod.module = 23
-#    directory = pypath.root.dirpath()
-
-import py
-rootdir = py.magic.autopath().dirpath()
-    
-# default values for options (modified from cmdline) 
-verbose = 0 
-nocapture = False 
-collectonly = False 
-exitfirstproblem = False 
-fulltrace = False 
-showlocals = False
-nomagic = False 

Modified: py/dist/example/test/failure_demo.py
==============================================================================
--- py/dist/example/test/failure_demo.py	(original)
+++ py/dist/example/test/failure_demo.py	Wed Dec 22 10:37:32 2004
@@ -77,8 +77,9 @@
     def test_tupleerror(self):
         a,b = [1]
 
-    def test_reinterpret_fails(self):
+    def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
         l = [1,2,3]
+        print "l is", l
         a,b = l.pop()
 
     def test_some_error(self):

Modified: py/dist/py/__init__.py
==============================================================================
--- py/dist/py/__init__.py	(original)
+++ py/dist/py/__init__.py	Wed Dec 22 10:37:32 2004
@@ -34,19 +34,11 @@
     'path.Invalid'           : ('./path/error.py', 'Invalid'),
     'path.Denied'            : ('./path/error.py', 'PermissionDenied'),
 
+    'magic.invoke'           : ('./magic/invoke.py', 'invoke'),
     'magic.revoke'           : ('./magic/invoke.py', 'revoke'),
-    'magic.revert'           : ('./magic/patch.py', 'revert'),
     'magic.patch'            : ('./magic/patch.py', 'patch'),
-    'magic.invoke'           : ('./magic/invoke.py', 'invoke'),
+    'magic.revert'           : ('./magic/patch.py', 'revert'),
     'magic.greenlet'         : ('./magic/greenlet/greenlet.c', 'greenlet'),
-    'magic.dyncode.tbinfo'   : ('./magic/dyncode.py', 'tbinfo'),
-    'magic.dyncode.listtb'   : ('./magic/dyncode.py', 'listtb'),
-    'magic.dyncode.getsource': ('./magic/dyncode.py', 'getsource'),
-    'magic.dyncode.getlines' : ('./magic/dyncode.py', 'getlines'),
-    'magic.dyncode.getline'  : ('./magic/dyncode.py', 'getline'),
-    'magic.dyncode.findsource': ('./magic/dyncode.py', 'findsource'),
-    'magic.dyncode.compile2' : ('./magic/dyncode.py', 'compile2'),
-    'magic.dyncode.compile'  : ('./magic/dyncode.py', 'compile'),
     'magic.autopath'         : ('./magic/autopath.py', 'autopath'),
     'magic.View'             : ('./magic/viewtype.py', 'View'),
     'magic.AssertionError'   : ('./magic/assertion.py', 'AssertionError'),
@@ -57,6 +49,8 @@
     'code.RunnerFrame'       : ('./code/frame.py', 'RunnerFrame'),
     'code.ExceptionInfo'     : ('./code/excinfo.py', 'ExceptionInfo'),
 
+    'builtin.enumerate'      : ('./builtin/enumerate.py', 'enumerate'),
+
     'execnet.SocketGateway'  : ('./execnet/register.py', 'SocketGateway'),
     'execnet.PopenGateway'   : ('./execnet/register.py', 'PopenGateway'),
     'execnet.SshGateway'     : ('./execnet/register.py', 'SshGateway'),

Modified: py/dist/py/code/excinfo.py
==============================================================================
--- py/dist/py/code/excinfo.py	(original)
+++ py/dist/py/code/excinfo.py	Wed Dec 22 10:37:32 2004
@@ -22,6 +22,38 @@
         for x in func(self.type, self.value): 
             yield x 
 
+    def getentries(self, startcondition=None, endcondition=None): 
+        if startcondition is not None and not callable(startcondition): 
+            raise TypeError("%r is not callable or None" % startcondition) 
+        if endcondition is not None and not callable(endcondition): 
+            raise TypeError("%r is not callable or None" % endcondition) 
+        result = []
+        gen = iter(self)
+        for x in gen: 
+            if startcondition is None or startcondition(x): 
+                result.append(x) 
+                break 
+        for x in gen: 
+            result.append(x) 
+            if endcondition is not None and endcondition(x): 
+                break 
+        return result 
+        #entries = list(self) 
+        #gen = py.builtin.enumerate(self) 
+        #if start is not None: 
+        #    for i, entry in gen: 
+        #        p,l = entry.frame.code.path, entry.frame.code.firstlineno
+        #        if start == i or (p,l) == start: 
+        #            break 
+        #res = []
+        #for i, entry in gen: 
+        #    res.append(entry)
+        #    if end is not None: 
+        #       p,l = entry.frame.code.path, entry.frame.code.firstlineno 
+        #       if i == end or (p,l) == end: 
+        #           break 
+        #return res 
+
 class TracebackEntry(object): 
     def __init__(self, rawentry, excinfo): 
         self._rawentry = rawentry

Modified: py/dist/py/code/source.py
==============================================================================
--- py/dist/py/code/source.py	(original)
+++ py/dist/py/code/source.py	Wed Dec 22 10:37:32 2004
@@ -182,15 +182,21 @@
     return co 
 
 def getsource(obj, **kwargs): 
-    if hasattr(obj, 'f_code'): 
+    if hasattr(obj, 'func_code'): 
+        obj = obj.func_code
+    elif hasattr(obj, 'f_code'): 
         obj = obj.f_code 
     try:
-        return obj.co_filename.__source__ 
+        fullsource = obj.co_filename.__source__ 
     except AttributeError: 
         import inspect 
         strsrc = inspect.getsource(obj) 
         assert isinstance(strsrc, str) 
         return Source(strsrc, **kwargs) 
+    else: 
+        lineno = obj.co_firstlineno - 1 
+        end = fullsource.getblockend(lineno)
+        return fullsource[lineno:end+1]
 
 # 
 # various helper functions 

Modified: py/dist/py/code/testing/test_excinfo.py
==============================================================================
--- py/dist/py/code/testing/test_excinfo.py	(original)
+++ py/dist/py/code/testing/test_excinfo.py	Wed Dec 22 10:37:32 2004
@@ -27,3 +27,39 @@
     #for x in info: 
     #    print "%s:%d  %s" %(x.path.relto(root), x.lineno, x.statement)
     #xxx
+
+# testchain for getentries test below
+def f(): 
+    raise ValueError 
+def g(): 
+    f()
+def h(): 
+    g()
+
+def test_excinfo_getentries_nocut(): 
+    excinfo = py.test.raises(ValueError, h) 
+    entries = excinfo.getentries() 
+    assert len(entries) == 4 # fragile 
+    names = ['f','g','h']
+    for entry in entries: 
+        try: 
+            names.remove(entry.frame.code.name)
+        except ValueError: 
+            pass 
+    assert not names 
+
+def test_excinfo_getentries_cut(): 
+    excinfo = py.test.raises(ValueError, h) 
+    entries = excinfo.getentries(
+            lambda x: x.frame.code.name != 'raises', 
+            lambda x: x.frame.code.name != 'f')
+    names = [x.frame.code.name for x in entries]
+    assert names == ['h','g']
+
+def test_excinfo_getentries_type_error(): 
+    excinfo = py.test.raises(ValueError, h) 
+    entries = excinfo.getentries(
+            lambda x: x.frame.code.name != 'raises', 
+            lambda x: x.frame.code.name != 'f')
+    names = [x.frame.code.name for x in entries]
+    assert names == ['h','g']

Modified: py/dist/py/code/testing/test_source.py
==============================================================================
--- py/dist/py/code/testing/test_source.py	(original)
+++ py/dist/py/code/testing/test_source.py	Wed Dec 22 10:37:32 2004
@@ -43,10 +43,10 @@
     x = 23"""
 
 def test_syntaxerror_rerepresentation():
-    ex = py.test.raises(SyntaxError, py.code.compile, 'x x')[1]
-    assert ex.lineno == 1
-    assert ex.offset == 3
-    assert ex.text.strip(), 'x x'
+    ex = py.test.raises(SyntaxError, py.code.compile, 'x x')
+    assert ex.value.lineno == 1
+    assert ex.value.offset == 3
+    assert ex.value.text.strip(), 'x x'
 
 def test_isparseable(): 
     assert Source("hello").isparseable()
@@ -210,3 +210,15 @@
     source = list(excinfo)[-1].statement 
     assert str(source).strip() == 'c(1)' 
 
+def test_getfuncsource_dynamic():
+    source = """
+        def f():
+            raise ValueError
+
+        def g(): pass
+    """
+    co = py.code.compile(source) 
+    exec co 
+    assert str(py.code.Source(f)).strip() == 'def f():\n    raise ValueError'
+    assert str(py.code.Source(g)).strip() == 'def g(): pass'
+

Copied: py/dist/py/conftest.py (from r7948, py/dist/conftest.py)
==============================================================================
--- py/dist/conftest.py	(original)
+++ py/dist/py/conftest.py	Wed Dec 22 10:37:32 2004
@@ -8,7 +8,7 @@
 #    directory = pypath.root.dirpath()
 
 import py
-rootdir = py.magic.autopath().dirpath()
+rootdir = py.magic.autopath().dirpath().dirpath()
     
 # default values for options (modified from cmdline) 
 verbose = 0 

Deleted: /py/dist/py/magic/dyncode.py
==============================================================================
--- /py/dist/py/magic/dyncode.py	Wed Dec 22 10:37:32 2004
+++ (empty file)
@@ -1,259 +0,0 @@
-"""
-    creating code objects and keeping track of their source code 
-    with artificial unique filenames. Provides and extends some 
-    'inspect' functions which usually only work with code coming 
-    from static modules. 
-"""
-from __future__ import generators
-import sys
-import inspect
-import os
-import re
-from linecache import getline as linecache_getline
-from linecache import getlines as linecache_getlines
-from inspect import findsource as inspect_findsource
-import linecache
-import __builtin__
-from __builtin__ import compile as oldcompile 
-from py import magic
-
-def gettb(tb, n=-1):
-    """ return the n'th traceback. """
-    return listtb(tb)[n]
-
-def listtb(tb):
-    tblist = []
-    while tb:
-        tblist.append(tb)
-        tb = tb.tb_next
-    return tblist
-
-def getparseablestartingblock(obj): 
-    if hasattr(obj, 'tb_lineno'): 
-        lineno = obj.tb_lineno-1
-        frame = obj.tb_frame
-    elif hasattr(obj, 'f_lineno'):
-        lineno = obj.f_lineno-1
-        frame = obj
-    else:
-        raise ValueError, "can only grok frame and traceback objects" 
-    #lineno_hint = frame.f_lineno - 1 
-    #print "getstartingblock: lineno_hint is %d" % lineno_hint 
-    lines = magic.dyncode.getlines(frame.f_code.co_filename) 
-    source = getsource_tryparsing(lines, lineno) 
-    #print "getstartingblock: returning %r" % source
-    return source 
-
-def getsource_tryparsing(lines, lineno_hint):
-    # the famous try-parsing technique is back! :-) 
-    # first we go forward, afterwards we try parsing backwards, i don't
-    # see how we could do better ...  given that a multiline assert
-    # statement has its frame.f_lineno set to the first line, while
-    # 'A(x,\n  y)' will have its frame.f_lineno set to the second line 
-    current = lineno_hint 
-    while current < len(lines)+1: 
-        source = "".join(lines[lineno_hint:current+1])
-        source = source.lstrip()
-        if isparseable(source):
-            return source 
-        current += 1
-
-    current = lineno_hint 
-    while current >= 0:
-        source = "".join(lines[current:lineno_hint+1]) 
-        source = source.lstrip()
-        if isparseable(source):
-            return source 
-        current -= 1
-
-def isparseable(source):
-    import parser
-    try:
-        parser.suite(source)
-    except (parser.ParserError, SyntaxError):
-        return False
-    else:
-        return True 
-
-_dynfileregistry = {}
-
-def deindent(pysource):
-    """ return a list of deindented lines from the given python
-        source code.  The first indentation offset of a non-blank
-        line determines the deindentation-offset for all the lines. 
-        Subsequent lines which have a lower indentation size will
-        be copied verbatim as they are assumed to be part of
-        multilines. 
-    """
-    lines = []
-    indentsize = 0
-    for line in pysource.split('\n'):
-        if not lines:
-            if not line.strip():
-                continue # skip first empty lines 
-            indentsize = len(line) - len(line.lstrip())
-        line = line.expandtabs()
-        if line.strip():
-            if len(line) - len(line.lstrip()) >= indentsize:
-                line = line[indentsize:]
-        lines.append(line + '\n')
-
-    # treat trailing whitespace-containing lines correctly 
-    # (the python parser at least in python 2.2. is picky about it)
-    while lines:
-        line = lines.pop()
-        if not line.strip():
-            continue
-        if not line.endswith('\n'):
-            line = line + '\n'
-        lines.append(line)
-        break
-    return lines
-
-def compile2(source, mode='exec', flag=generators.compiler_flag):
-    frame = inspect.currentframe(1) # the caller
-    return newcompile(frame, source, mode, flag) 
-
-def newcompile(frame, source, mode='exec', flag=generators.compiler_flag):
-    lines = deindent(source)
-    source = "".join(lines)
-    origin = "%s:%d" % (frame.f_code.co_filename, frame.f_lineno)
-    filename = _makedynfilename(origin, lines)
-    #print "frames filename", frame.f_code.co_filename
-    #print "making dynfilename", filename
-    try:
-        #print "compiling source:", repr(source)
-        co = oldcompile(source+'\n', filename, mode, flag)
-    except SyntaxError, ex:
-        # re-represent syntax errors from parsing python strings 
-        newex = SyntaxError('\n'.join([
-            "".join(lines[:ex.lineno]),
-            " " * ex.offset + '^', 
-            "syntax error probably generated here: %s" % origin]))
-        newex.offset = ex.offset
-        newex.lineno = ex.lineno
-        newex.text = ex.text
-        raise newex
-    _dynfileregistry[filename] = origin, lines, co 
-    return co
-
-builtin_compile = compile
-def compile(source, filename, mode='exec', flag=generators.compiler_flag):
-    if os.path.exists(filename):
-        return builtin_compile(source, filename, mode, flag)
-    frame = inspect.currentframe(1) # the caller
-    return newcompile(frame, source, mode, flag) 
-    
-def invoke():
-    # a hack for convenience of displaying tracebacks 
-    magic.patch(linecache, 'getline', getline)
-    magic.patch(linecache, 'getlines', getlines)
-    magic.patch(__builtin__, 'compile', compile)
-    magic.patch(inspect, 'findsource', findsource)
-
-def revoke():
-    magic.revert(linecache, 'getline') 
-    magic.revert(linecache, 'getlines') 
-    magic.revert(__builtin__, 'compile') 
-    magic.revert(inspect, 'findsource') 
-
-def tbinfo(tb, index = -1):
-    """ return an (filename:lineno, linecontent) tuple for the given 
-        traceback.  Works also with code generated from compile2(). 
-    """
-    tb = gettb(tb, index)
-    filename = tb.tb_frame.f_code.co_filename
-    lineno = tb.tb_lineno 
-    return filename, lineno
-
-def getframe(tb, index = -1):
-    """ return an (filename:lineno, linecontent) tuple for the given 
-        traceback.  Works also with code generated from compile2(). 
-    """
-    tb = gettb(tb, index)
-    return tb.tb_frame
-
-def _makedynfilename(origin, source, originmap={}):
-    origin = origin
-    entry = originmap.setdefault(origin, [])
-    num = len(entry)
-    entry.append(num)
-    if num > 0:
-        return "<%s [%d]>" % (origin, num)
-    else:
-        return "<%s>" % origin 
-
-def getline(filename, lineno):
-    """ return line in filename (possibly dyncode). """
-    tup = _dynfileregistry.get(filename, None)
-    if tup is not None:
-        origin, lines, co = tup
-        return lines[lineno-1]
-    else:
-        return linecache_getline(filename, lineno)
-
-def getlines(filename): 
-    """ return line in filename (possibly dyncode). """
-    tup = _dynfileregistry.get(filename, None)
-    if tup is not None:
-        origin, lines, co = tup
-        return lines 
-    else:
-        return linecache_getlines(filename) 
-
-
-def getcode(obj):
-    if inspect.iscode(obj):
-        return obj
-    for name in ('func_code', 'f_code'):
-        if hasattr(obj, name):
-            return getattr(obj, name)
-        
-def getsourcelines(object):
-    """Return a list of source lines and starting line number for an object.
-
-    The argument may be a module, class, method, function, traceback,
-    frame, or (a dynamically created) code object.  The source code is
-    returned as a list of the lines corresponding to the object and the
-    line number indicates where in the original source file the first
-    line of code was found.  An IOError is raised if the source code
-    cannot be retrieved.
-    """
-    lines, lnum = findsource(object)
-    if inspect.ismodule(object): 
-        return lines, 0
-    else: 
-        return inspect.getblock(lines[lnum:]), lnum + 1
-
-def getsource(object):
-    """Return the text of the source code for an object.
-
-    The argument may be a module, class, method, function, traceback, frame,
-    or code object.  The source code is returned as a single string.  An
-    IOError is raised if the source code cannot be retrieved."""
-    lines, lnum = getsourcelines(object)
-    return ''.join(lines)
-
-def findsource(obj):
-    obj = getcode(obj)
-    filename = obj.co_filename
-    if _dynfileregistry.has_key(filename):
-        origin, lines, gencode = _dynfileregistry[filename]
-
-        lnum = obj.co_firstlineno - 1
-        print "firstlineno", lnum
-        pat = re.compile(r'^(\s*def\s)|(.*\slambda(:|\s))')
-        while lnum > 0:
-            if pat.match(lines[lnum]): 
-                break
-            lnum = lnum - 1
-        return lines, lnum
-    else:
-        return inspect_findsource(obj)
-
-def getpyfile(obj):
-    fn = inspect.getfile(obj)
-    if fn.endswith('.pyc'):
-        fn = fn[:-1]
-    assert fn.endswith('.py')
-    return fn

Modified: py/dist/py/magic/invoke.py
==============================================================================
--- py/dist/py/magic/invoke.py	(original)
+++ py/dist/py/magic/invoke.py	Wed Dec 22 10:37:32 2004
@@ -1,29 +1,18 @@
 
-def invoke(dyncode=False, assertion=False): 
+def invoke(assertion=False): 
     """ invoke magic, currently you can specify:
 
-        dyncode    patches some syslibs and the compile builtins 
-                   to support better traces for dynamically compiled
-                   code. e.g. inspect.getsource(compile('...', ...))
-                   should work. 
-
         assertion  patches the builtin AssertionError to try to give
                    more meaningful AssertionErrors, which by means
                    of deploying a mini-interpreter constructs
                    a useful error message. 
     """
-    if dyncode:
-        from py.__impl__.magic import dyncode 
-        dyncode.invoke()
     if assertion: 
         from py.__impl__.magic import assertion 
         assertion.invoke()
 
-def revoke(dyncode=False, assertion=False):
+def revoke(assertion=False):
     """ revoke previously invoked magic (see invoke())."""
-    if dyncode:
-        from py.__impl__.magic import dyncode 
-        dyncode.revoke()
     if assertion:
         from py.__impl__.magic import assertion 
         assertion.revoke()

Deleted: /py/dist/py/magic/test_dyncode.py
==============================================================================
--- /py/dist/py/magic/test_dyncode.py	Wed Dec 22 10:37:32 2004
+++ (empty file)
@@ -1,97 +0,0 @@
-import sys
-import os
-#print "dyncode_test: __name__ ==", __name__
-from py.__impl__.magic import dyncode, exprinfo
-import py
-
-def setup_module(mod):
-    py.magic.invoke(dyncode=1)
-def teardown_module(mod):
-    py.magic.revoke(dyncode=1)
-
-def test_dyncode_trace():
-    source = """
-        def f():
-            raise ValueError
-    """
-    co = dyncode.compile2(source)
-    exec co 
-    excinfo = py.test.raises(ValueError, f)
-    filename, lineno = dyncode.tbinfo(excinfo[2])
-    line = dyncode.getline(filename, lineno)
-    assert line.strip() == 'raise ValueError'
-
-def test_dyncode_trace_multiple():
-    test_dyncode_trace()
-    test_dyncode_trace()
-
-def test_unique_filenames():
-    fn1 = dyncode._makedynfilename('fn','source')
-    fn2 = dyncode._makedynfilename('fn','source')
-    assert fn1 != fn2
-
-def test_syntaxerror_rerepresentation():
-    ex = py.test.raises(SyntaxError, dyncode.compile2, 'x x')[1]
-    assert ex.lineno == 1
-    assert ex.offset == 3
-    assert ex.text.strip(), 'x x'
-
-def test_getfuncsource_dynamic():
-    source = """
-        def f():
-            raise ValueError
-
-        def g(): pass
-    """
-    co = dyncode.compile2(source)
-    exec co 
-    source = dyncode.getsource(f)
-    assert dyncode.getsource(f) == 'def f():\n    raise ValueError\n'
-    assert dyncode.getsource(g) == 'def g(): pass\n'
-    lines, lnum = dyncode.findsource(g) 
-    lines = lines[lnum:] 
-    assert lines and lines[0] == 'def g(): pass\n' 
-
-def test_getpyfile():
-    fn = dyncode.getpyfile(dyncode)
-    assert os.path.exists(fn)
-
-def DEPRECATED_test_getstartingblock_singleline():
-    class A:
-        def __init__(self, *args):
-            frame = sys._getframe(1)
-            self.source = dyncode.getparseablestartingblock(frame)
-           
-    x = A('x', 'y') 
-
-    l = [i for i in x.source.split('\n') if i.strip()]
-    assert len(l) == 1
-
-def DEPRECATED_test_getstartingblock_multiline():
-    class A:
-        def __init__(self, *args):
-            frame = sys._getframe(1)
-            self.source = dyncode.getparseablestartingblock(frame) 
-           
-    x = A('x', 
-          'y' \
-          , 
-          'z') 
-
-    l = [i for i in x.source.split('\n') if i.strip()]
-    assert len(l) == 4
-
-def DEPRECATED_test_getline_finally():
-    def c(): pass
-    excinfo = py.test.raises(TypeError, """
-           teardown = None
-           try:
-                c(1) 
-           finally:
-                if teardown: 
-                    teardown() 
-    """)
-    tb = dyncode.gettb(excinfo[2], -1)
-    source = dyncode.getparseablestartingblock(tb) 
-    assert source.strip() == 'c(1)' 
-

Modified: py/dist/py/magic/test_invoke.py
==============================================================================
--- py/dist/py/magic/test_invoke.py	(original)
+++ py/dist/py/magic/test_invoke.py	Wed Dec 22 10:37:32 2004
@@ -2,27 +2,11 @@
 import py 
 import inspect
 
-def check_dyncode():
-    co = compile('x=3', 'bogus', 'exec') 
-    s = inspect.getfile(co) 
-    assert s
-    line = inspect.getsource(co) 
-    assert line.strip() == "x=3" 
-
 def check_assertion():
     excinfo = py.test.raises(AssertionError, "assert 1 == 2")
     value = excinfo.value 
     assert str(value) == "assert 1 == 2" 
 
-def test_invoke_dyncode():
-    old = compile
-    py.magic.invoke(dyncode=True)
-    try:
-        assert compile != old 
-        check_dyncode()
-    finally:
-        py.magic.revoke(dyncode=True) 
-    
 def test_invoke_assertion():
     py.magic.invoke(assertion=True)
     try:

Modified: py/dist/py/path/common.py
==============================================================================
--- py/dist/py/path/common.py	(original)
+++ py/dist/py/path/common.py	Wed Dec 22 10:37:32 2004
@@ -107,7 +107,7 @@
             return p.check()
 
     def basename(self):
-        return self.get('basename')
+        return self.get('basename')[0]
     basename = property(basename, None, None, 'basename part of path') 
 
     def parts(self, reverse=False): 
@@ -200,7 +200,7 @@
         """
         pattern = self.pattern
         if pattern.find(path.sep) == -1:
-            name = path.get('basename')
+            name = path.basename 
         else:
             name = str(path) # path.strpath # XXX svn? 
             pattern = '*' + path.sep + pattern
@@ -223,7 +223,7 @@
     def ext(self, arg):
         if not arg.startswith('.'):
             arg = '.' + arg
-        return self.path.get('ext') == arg
+        return self.path.ext == arg 
 
 class FSPathBase(PathBase): 
     """ shared implementation for filesystem path objects."""
@@ -240,11 +240,11 @@
         return self.new(basename='').join(*args, **kwargs) 
 
     def ext(self):
-        return self.get('ext')
+        return self.get('ext')[0]
     ext = property(ext, None, None, 'extension part of path') 
 
     def purebasename(self):
-        return self.get('purebasename')
+        return self.get('purebasename')[0]
     purebasename = property(purebasename, None, None, 'basename without extension')
 
     def read(self, mode='rb'):
@@ -310,8 +310,7 @@
     def getpycodeobj(self):
         s = self.read()
         # XXX str(self) should show up somewhere in the code's filename
-        return py.magic.dyncode.compile2(s)
-
+        return py.code.compile(s) 
 
 class PathStr(str):
     def __init__(self, path):

Modified: py/dist/py/path/extpy/extpy.py
==============================================================================
--- py/dist/py/path/extpy/extpy.py	(original)
+++ py/dist/py/path/extpy/extpy.py	Wed Dec 22 10:37:32 2004
@@ -71,13 +71,7 @@
         for name in spec.split(','):
             if name == 'basename':
                 l.append(modparts[-1])
-
-        if len(l) == 1:
-            return l[0]
-        elif len(l) == 0:
-            return None
-        else:
-            return l
+        return l 
 
     def resolve(self):
         """return the python object, obtained from traversing from
@@ -140,10 +134,10 @@
         if inspect.isfunction(obj):
             obj = obj.func_code 
         if inspect.iscode(obj):
-            return py.path.local(obj.co_filename), obj.co_firstlineno
+            return py.path.local(obj.co_filename), obj.co_firstlineno - 1
         else:
             source, lineno = inspect.findsource(obj) 
-            return x.getfile(), lineno 
+            return x.getfile(), lineno - 1
 
     def visit(self, fil=None, rec=None, ignore=None, seen=None):
         def myrec(p, seen={id(self): True}):

Modified: py/dist/py/path/gateway/channeltest.py
==============================================================================
--- py/dist/py/path/gateway/channeltest.py	(original)
+++ py/dist/py/path/gateway/channeltest.py	Wed Dec 22 10:37:32 2004
@@ -10,36 +10,36 @@
         threading.Thread(target=self.serve).start()
 
     def p2c(self, path):
-        n = self.next_id
+        id = self.next_id
         self.next_id += 1
-        self.C2P[n] = path
-        return n
+        self.C2P[id] = path
+        return id
 
-    def command_LIST(self, n, *args):
-        path = self.C2P[n]
+    def command_LIST(self, id, *args):
+        path = self.C2P[id]
         answer = [(self.p2c(p), p.basename) for p in path.listdir(*args)]
         self.channel.send(answer)
 
-    def command_DEL(self, n):
-        del self.C2P[n]
+    def command_DEL(self, id):
+        del self.C2P[id]
 
-    def command_BASENAME(self, n):
-        path = self.C2P[n]
-        self.channel.send(path.basename)
+    def command_GET(self, id, spec):
+        path = self.C2P[id]
+        self.channel.send(path.get(spec)) 
 
-    def command_READ(self, n):
-        path = self.C2P[n]
+    def command_READ(self, id):
+        path = self.C2P[id]
         self.channel.send(path.read())
 
-    def command_JOIN(self, n, n2, *args):
-        path = self.C2P[n]
-        assert n2 not in self.C2P
-        self.C2P[n2] = path.join(*args)
-
-    def command_DIRPATH(self, n, n2):
-        path = self.C2P[n]
-        assert n2 not in self.C2P
-        self.C2P[n2] = path.dirpath()
+    def command_JOIN(self, id, resultid, *args):
+        path = self.C2P[id]
+        assert resultid not in self.C2P
+        self.C2P[resultid] = path.join(*args)
+
+    def command_DIRPATH(self, id, resultid):
+        path = self.C2P[id]
+        assert resultid not in self.C2P
+        self.C2P[resultid] = path.dirpath()
 
     def serve(self):
         try:
@@ -50,7 +50,6 @@
         except EOFError:
             pass
 
-
 if __name__ == '__main__':
     import py
     gw = py.execnet.PopenGateway()

Modified: py/dist/py/path/gateway/channeltest2.py
==============================================================================
--- py/dist/py/path/gateway/channeltest2.py	(original)
+++ py/dist/py/path/gateway/channeltest2.py	Wed Dec 22 10:37:32 2004
@@ -11,7 +11,8 @@
 '''
 
 
-gw = py.execnet.SshGateway('codespeak.net')
+#gw = py.execnet.SshGateway('codespeak.net')
+gw = py.execnet.PopenGateway() 
 c = gw.remote_exec(SRC)
 subchannel = gw.channelfactory.new()
 c.send(subchannel)

Modified: py/dist/py/path/gateway/remotepath.py
==============================================================================
--- py/dist/py/path/gateway/remotepath.py	(original)
+++ py/dist/py/path/gateway/remotepath.py	Wed Dec 22 10:37:32 2004
@@ -6,39 +6,42 @@
 class RemotePath(common.FSPathBase):
     sep = '/'
 
-    def __init__(self, c, n, basename=None):
-        self._c = c
-        self._n = n
+    def __init__(self, channel, id, basename=None):
+        self._channel = channel
+        self._id = id
         self._basename = basename
+        self._specs = {}
 
     def __del__(self):
-        self._c.send(('DEL', self._n))
+        self._channel.send(('DEL', self._id))
 
     def __repr__(self):
         return 'RemotePath(%s)' % self.basename
 
     def listdir(self, *args):
-        self._c.send(('LIST', self._n) + args)
-        return [RemotePath(self._c, n, basename)
-                for (n, basename) in self._c.receive()]
+        self._channel.send(('LIST', self._id) + args)
+        return [RemotePath(self._channel, id, basename)
+                for (id, basename) in self._channel.receive()]
 
     def dirpath(self):
-        n = ~COUNTER.next()
-        self._c.send(('DIRPATH', self._n, n))
-        return RemotePath(self._c, n)
+        id = ~COUNTER.next()
+        self._channel.send(('DIRPATH', self._id, id))
+        return RemotePath(self._channel, id)
 
     def join(self, *args):
-        n = ~COUNTER.next()
-        self._c.send(('JOIN', self._n, n) + args)
-        return RemotePath(self._c, n)
+        id = ~COUNTER.next()
+        self._channel.send(('JOIN', self._id, id) + args)
+        return RemotePath(self._channel, id)
 
     def get(self, spec):
-        assert spec == 'basename'   # XXX!
-        if self._basename is None:
-            self._c.send(('BASENAME', self._n))
-            self._basename = self._c.receive()
-        return self._basename
+        parts = spec.split(',')
+        ask = [x for x in parts  if x not in self._specs]
+        if ask: 
+            self._channel.send(('GET', self._id, ",".join(ask)))
+            for part, value in zip(ask, self._channel.receive()): 
+                self._specs[part] = value 
+        return [self._specs[x] for x in parts]
 
     def read(self):
-        self._c.send(('READ', self._n))
-        return self._c.receive()
+        self._channel.send(('READ', self._id))
+        return self._channel.receive()

Modified: py/dist/py/path/local/local.py
==============================================================================
--- py/dist/py/path/local/local.py	(original)
+++ py/dist/py/path/local/local.py	Wed Dec 22 10:37:32 2004
@@ -85,22 +85,24 @@
                                     |--|    ext
         """
         obj = object.__new__(self.__class__)
+        drive, dirname, basename, purebasename,ext = self.get(
+             "drive,dirname,basename,purebasename,ext")
         if 'basename' in kw:
             if 'purebasename' in kw or 'ext' in kw:
-                raise ValueError("invalid specification")
+                raise ValueError("invalid specification %r" % kw)
         else:
-            pb = kw.setdefault('purebasename', self.get('purebasename'))
-            if 'ext' in kw:
+            pb = kw.setdefault('purebasename', purebasename) 
+            try:
                 ext = kw['ext']
+            except KeyError: 
+                pass
+            else:
                 if ext and not ext.startswith('.'):
                     ext = '.' + ext
-            else:
-                ext = self.get('ext')
             kw['basename'] = pb + ext
 
-        kw.setdefault('drive', self.get('drive'))
-        kw.setdefault('dirname', self.get('dirname'))
-
+        kw.setdefault('drive', drive) 
+        kw.setdefault('dirname', dirname) 
         kw.setdefault('sep', self.sep)
         obj.strpath = os.path.normpath(
             "%(drive)s%(dirname)s%(sep)s%(basename)s" % kw)
@@ -143,13 +145,7 @@
                         append(ext)
                     else:
                         raise ValueError, "invalid part specification %r" % name
-
-        if len(res) == 1:
-            return res[0]
-        elif len(res) == 0:
-            return None
-        else:
-            return res
+        return res 
 
     def join(self, *args, **kwargs):
         """ return a new path by appending all 'args' as path
@@ -451,7 +447,7 @@
 
         def parse_num(path):
             """ parse the number out of a path (if it matches the base) """
-            bn = path.get('basename')
+            bn = path.basename 
             if bn.startswith(base):
                 try:
                     return int(bn[len(base):])

Modified: py/dist/py/path/local/test_local.py
==============================================================================
--- py/dist/py/path/local/test_local.py	(original)
+++ py/dist/py/path/local/test_local.py	Wed Dec 22 10:37:32 2004
@@ -183,7 +183,7 @@
         for i in range(10):
             numdir = local.make_numbered_dir(root, 'base.', keep=2)
             assert numdir.check()
-            assert numdir.get('basename') == 'base.%d' %i
+            assert numdir.basename == 'base.%d' %i
             if i>=1:
                 assert numdir.new(ext=str(i-1)).check()
             if i>=2:

Modified: py/dist/py/path/local/test_posix.py
==============================================================================
--- py/dist/py/path/local/test_posix.py	(original)
+++ py/dist/py/path/local/test_posix.py	Wed Dec 22 10:37:32 2004
@@ -104,7 +104,7 @@
             filepath.write("")
             linkpath.mksymlinkto(filepath)
             realpath = linkpath.realpath()
-            assert realpath.get('basename') == 'file'
+            assert realpath.basename == 'file' 
         finally:
             tmpdir.remove(rec=1)
 

Modified: py/dist/py/path/svn/svncommon.py
==============================================================================
--- py/dist/py/path/svn/svncommon.py	(original)
+++ py/dist/py/path/svn/svncommon.py	Wed Dec 22 10:37:32 2004
@@ -36,18 +36,19 @@
         """
         obj = object.__new__(self.__class__)
         obj.rev = kw.get('rev', self.rev)
-
+        dirname, basename, purebasename, ext = self.get(
+             "dirname,basename,purebasename,ext")
         if 'basename' in kw:
             if 'purebasename' in kw or 'ext' in kw:
-                raise ValueError("invalid specification")
+                raise ValueError("invalid specification %r" % kw)
         else:
-            pb = kw.setdefault('purebasename', self.get('purebasename'))
-            ext = kw.setdefault('ext', self.get('ext'))
+            pb = kw.setdefault('purebasename', purebasename) 
+            ext = kw.setdefault('ext', ext) 
             if ext and not ext.startswith('.'):
                 ext = '.' + ext
             kw['basename'] = pb + ext
 
-        kw.setdefault('dirname', self.get('dirname'))
+        kw.setdefault('dirname', dirname) 
         kw.setdefault('sep', self.sep)
         if kw['basename']: 
             obj.strpath = "%(dirname)s%(sep)s%(basename)s" % kw
@@ -89,11 +90,7 @@
                     res.append(ext)
                 else:
                     raise NameError, "Don't know part %r" % name
-        if len(res) == 1:
-            return res[0]
-        elif len(res) == 0:
-            return None
-        return res
+        return res 
 
     def __eq__(self, other):
         """ return true if path and rev attributes each match """

Modified: py/dist/py/path/test/fscommon.py
==============================================================================
--- py/dist/py/path/test/fscommon.py	(original)
+++ py/dist/py/path/test/fscommon.py	Wed Dec 22 10:37:32 2004
@@ -66,7 +66,7 @@
 
     def test_dotted_name_ext(self):
         newpath = self.root.join('a.b.c')
-        ext = newpath.get('ext')
+        ext = newpath.ext 
         assert ext == '.c'
         assert newpath.ext == '.c' 
 

Modified: py/dist/py/test/defaultconfig.py
==============================================================================
--- py/dist/py/test/defaultconfig.py	(original)
+++ py/dist/py/test/defaultconfig.py	Wed Dec 22 10:37:32 2004
@@ -8,6 +8,8 @@
 def getreporter():
     return py.test.TextReporter()
 
+additionalinfo = None
+
 options = ('py.test standard options', [
         Option('-v', '--verbose', 
                action="count", dest="verbose", default=0,

Modified: py/dist/py/test/raises.py
==============================================================================
--- py/dist/py/test/raises.py	(original)
+++ py/dist/py/test/raises.py	Wed Dec 22 10:37:32 2004
@@ -32,9 +32,9 @@
         try:
             func(*args[1:], **kwargs)
         except ExpectedException:
-            return sys.exc_info()
+            return py.code.ExceptionInfo()
         except Exception, e:
-            excinfo = sys.exc_info()
+            excinfo = py.code.ExceptionInfo() 
         else:
             excinfo = None
         k = ", ".join(["%s=%r" % x for x in kwargs.items()])

Modified: py/dist/py/test/report/text/reporter.py
==============================================================================
--- py/dist/py/test/report/text/reporter.py	(original)
+++ py/dist/py/test/report/text/reporter.py	Wed Dec 22 10:37:32 2004
@@ -34,10 +34,17 @@
 
     def start(self):
         self.out.sep("=", "test process starts") 
-        mode = py.test.config.option.session and 'session/child process' or 'inprocess'
+        mode = py.test.config.option.session and \
+               'session/child process' or 'inprocess'
         self.out.line("testing-mode: %s" % mode) 
         self.out.line("executable  : %s  (%s)" % 
                           (py.std.sys.executable, repr_pythonversion()))
+        for i, x in py.builtin.enumerate(py.test.config.configpaths): 
+            self.out.line("initial testconfig %d: %s" %(i, x))
+        additional = py.test.config.getfirst('additionalinfo') 
+        if additional: 
+            for key, descr in additional(): 
+                self.out.line("%s: %s" %(key, descr))
         self.out.sep("=")
         if not self.option.nomagic:
             py.magic.invoke(assertion=1) 

Modified: py/dist/py/test/report/text/summary.py
==============================================================================
--- py/dist/py/test/report/text/summary.py	(original)
+++ py/dist/py/test/report/text/summary.py	Wed Dec 22 10:37:32 2004
@@ -19,7 +19,7 @@
         self.out.sep("_") 
         self.out.sep("_", "Collect Error")
         self.out.line()
-        self.repr_traceback_raw(error.excinfo) 
+        self.repr_traceback_raw(error.excinfo.getentries()) 
         #self.repr_failure_result(res)
         #self.out.line()
         #if isinstance(res.excinfo[1], AssertionError):
@@ -80,18 +80,12 @@
                             getattr(res, 'tbindex', -1))
         #self.out.line()
         self.repr_failure_result(res)
-        try:
-            out, err = res.out, res.err
-        except AttributeError:
-            pass
-        else:
-            if out.strip():
-                self.out.sep("- ", "recorded stdout")
-                self.out.line(out.strip())
-            if err.strip():
-                self.out.sep("- ", "recorded stderr")
-                self.out.line(err.strip())
-        #self.out.line()
+        for name in 'out', 'err': 
+            if hasattr(res, name): 
+                out = getattr(res, name) 
+                if out.strip():
+                    self.out.sep("- ", "recorded std%s" % name)
+                    self.out.line(out.strip())
 
     def repr_failure_result(self, res):
         cls = res.excinfo.type 
@@ -139,7 +133,7 @@
                     self.out.line(line)
 
     def repr_source(self, tb): 
-        # represent the source code
+        # represent source code for a given traceback entry 
         self.out.line()
         source = tb.frame.code.fullsource 
         if not source: 
@@ -148,7 +142,6 @@
             #self.out.line("(f_lineno = %r)" % (frame.f_lineno)) 
             return
         start = tb.frame.code.firstlineno 
-        #end = source.getblockend(start) 
         end = tb.lineno
         
         for line in source[start:end]: 
@@ -159,43 +152,26 @@
         self.out.line(">" + line)
         return
 
-    #def tracelines(self, filename, lineno):
-    #    prelines = 3
-    #    if prelines:
-    #        for i in range(lineno-prelines-1, lineno):
-    #            line = py.magic.dyncode.getline(filename, i)
-    #            self.out.line("  %s" % line.rstrip())
-    #    line = py.magic.dyncode.getline(filename, lineno)
-    #    self.out.line("> %s" % line.rstrip())
-
-    def forward_traceback_to_test(self, tbentries, path):
-        for i in range(len(tbentries)): 
-            tb = tbentries[i]
-            #print "eq", tb.frame.code.path, path
-            if tb.frame.code.path == path: 
-                break 
-        return tbentries[i:] 
-
-    def repr_traceback(self, item, excinfo, tbindex=-1):
-        t_file, t_lineno = item.extpy.getfilelineno() 
-        fspath = item.extpy.root 
-        tbentries = list(excinfo)
-        if fspath and not self.option.fulltrace:
-            tbentries = self.forward_traceback_to_test(tbentries, fspath) 
-        else:
-            tbindex = -1
-        self.repr_traceback_raw(tbentries, tbindex) 
-        #t_file, t_lineno = unit.extpy.getfilelineno() 
-        #if t_file != filename or lineno != t_lineno:
-        #self.out.line("%s, line %d" % (unit.extpy, t_lineno) )
-        #self.out.line("%s, line %d" % (item.extpy, t_lineno) )
+    def cut_traceback(self, excinfo, item=None, tbindex=None): 
+        if self.option.fulltrace or item is None: 
+            startcondition = endcondition = None 
+        else: 
+            path,lineno = item.extpy.getfilelineno()
+            def startcondition(entry): 
+                return entry.frame.code.path == path and \
+                       entry.frame.code.firstlineno == lineno 
+            endcondition = None 
+        entries = excinfo.getentries(startcondition, endcondition) 
+        if tbindex is not None and tbindex < -1:
+            entries = entries[:tbindex]
+        return entries 
+
+    def repr_traceback(self, item, excinfo, tbindex=None):
+        tbentries = self.cut_traceback(excinfo, item, tbindex)
+        self.repr_traceback_raw(tbentries) 
         self.out.sep('-')
-        #self.out.sep('-')
-
-    def repr_traceback_raw(self, tbentries, tbindex=-1): 
-        if tbindex < -1 and not self.option.fulltrace:
-            tbentries = tbentries[:tbindex+1]
 
+    def repr_traceback_raw(self, tbentries): 
         recursioncache = {}
         first = True 
         for tb in tbentries:



More information about the pytest-commit mailing list