[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