[svn r37729] Added some code to py.io.FDCapture and py.io.OutErrCapture to allow writing

to the original (patched) file descriptor. Also made that the capturing object
is passed to apigen.py's build() function (from rsession.py), which uses the
new methods to print progress information.

--HG--
branch : trunk
This commit is contained in:
guido 2007-02-01 14:56:31 +01:00
parent 3f31ed5742
commit 9f491f2058
4 changed files with 81 additions and 4 deletions

View File

@ -17,7 +17,7 @@ def get_documentable_items(pkgdir):
rootmod = __import__(pkgdir.basename) rootmod = __import__(pkgdir.basename)
return 'py', pkg_to_dict(rootmod) return 'py', pkg_to_dict(rootmod)
def build(pkgdir, dsa): def build(pkgdir, dsa, capture):
l = linker.Linker() l = linker.Linker()
proj = project.Project() proj = project.Project()
@ -32,16 +32,25 @@ def build(pkgdir, dsa):
apb = htmlgen.ApiPageBuilder(targetdir, l, dsa, pkgdir, namespace_tree) apb = htmlgen.ApiPageBuilder(targetdir, l, dsa, pkgdir, namespace_tree)
spb = htmlgen.SourcePageBuilder(targetdir, l, pkgdir) spb = htmlgen.SourcePageBuilder(targetdir, l, pkgdir)
capture.writeorgerr('preparing namespace pages\n')
ns_data = apb.prepare_namespace_pages() ns_data = apb.prepare_namespace_pages()
capture.writeorgerr('preparing class pages\n')
class_names = dsa.get_class_names() class_names = dsa.get_class_names()
class_data = apb.prepare_class_pages(class_names) class_data = apb.prepare_class_pages(class_names)
capture.writeorgerr('preparing function pages\n')
function_names = dsa.get_function_names() function_names = dsa.get_function_names()
func_data = apb.prepare_function_pages(function_names) func_data = apb.prepare_function_pages(function_names)
capture.writeorgerr('preparing source pages\n')
source_data = spb.prepare_pages(pkgdir) source_data = spb.prepare_pages(pkgdir)
capture.writeorgerr('building namespace pages\n')
apb.build_namespace_pages(ns_data, proj) apb.build_namespace_pages(ns_data, proj)
capture.writeorgerr('building class pages\n')
apb.build_class_pages(class_data, proj) apb.build_class_pages(class_data, proj)
#apb.build_method_pages(method_data, proj) apb.build_method_pages(method_data, proj)
capture.writeorgerr('building function pages\n')
apb.build_function_pages(func_data, proj) apb.build_function_pages(func_data, proj)
capture.writeorgerr('building source pages\n')
spb.build_pages(source_data, proj, pkgdir) spb.build_pages(source_data, proj, pkgdir)
capture.writeorgerr('done building documentation\n')

View File

@ -1,9 +1,12 @@
import os, sys import os
import sys
import thread
import py import py
class FDCapture: class FDCapture:
""" Capture IO to/from a given os-level filedescriptor. """ """ Capture IO to/from a given os-level filedescriptor. """
def __init__(self, targetfd, tmpfile=None): def __init__(self, targetfd, tmpfile=None):
self.targetfd = targetfd self.targetfd = targetfd
if tmpfile is None: if tmpfile is None:
@ -14,16 +17,22 @@ class FDCapture:
self._patched = [] self._patched = []
def setasfile(self, name, module=sys): def setasfile(self, name, module=sys):
""" patch <module>.<name> to self.tmpfile
"""
key = (module, name) key = (module, name)
self._patched.append((key, getattr(module, name))) self._patched.append((key, getattr(module, name)))
setattr(module, name, self.tmpfile) setattr(module, name, self.tmpfile)
def unsetfiles(self): def unsetfiles(self):
""" unpatch all patched items
"""
while self._patched: while self._patched:
(module, name), value = self._patched.pop() (module, name), value = self._patched.pop()
setattr(module, name, value) setattr(module, name, value)
def done(self): def done(self):
""" unpatch and clean up, returns the self.tmpfile (file object)
"""
os.dup2(self._savefd, self.targetfd) os.dup2(self._savefd, self.targetfd)
self.unsetfiles() self.unsetfiles()
os.close(self._savefd) os.close(self._savefd)
@ -31,11 +40,23 @@ class FDCapture:
return self.tmpfile return self.tmpfile
def maketmpfile(self): def maketmpfile(self):
""" create a temporary file
"""
f = os.tmpfile() f = os.tmpfile()
newf = py.io.dupfile(f) newf = py.io.dupfile(f)
f.close() f.close()
return newf return newf
def writeorg(self, str):
""" write a string to the original file descriptor
"""
tempfp = os.tmpfile()
try:
os.dup2(self._savefd, tempfp.fileno())
tempfp.write(str)
finally:
tempfp.close()
class OutErrCapture: class OutErrCapture:
""" capture Stdout and Stderr both on filedescriptor """ capture Stdout and Stderr both on filedescriptor
and sys.stdout/stderr level. and sys.stdout/stderr level.
@ -51,6 +72,11 @@ class OutErrCapture:
self.err.setasfile('stderr') self.err.setasfile('stderr')
def reset(self): def reset(self):
""" reset sys.stdout and sys.stderr
returns a tuple of file objects (out, err) for the captured
data
"""
out = err = "" out = err = ""
if hasattr(self, 'out'): if hasattr(self, 'out'):
outfile = self.out.done() outfile = self.out.done()
@ -60,6 +86,20 @@ class OutErrCapture:
err = errfile.read() err = errfile.read()
return out, err return out, err
def writeorgout(self, str):
""" write something to the original stdout
"""
if not hasattr(self, 'out'):
raise IOError('stdout not patched')
self.out.writeorg(str)
def writeorgerr(self, str):
""" write something to the original stderr
"""
if not hasattr(self, 'err'):
raise IOError('stderr not patched')
self.err.writeorg(str)
def callcapture(func, *args, **kwargs): def callcapture(func, *args, **kwargs):
""" call the given function with args/kwargs """ call the given function with args/kwargs
and return a (res, out, err) tuple where and return a (res, out, err) tuple where

View File

@ -30,6 +30,33 @@ class TestFDCapture:
f = cap.done() f = cap.done()
assert x == "3" assert x == "3"
def test_writeorg(self):
tmppath = py.test.ensuretemp('test_writeorg').ensure('stderr',
file=True)
tmpfp = tmppath.open('w+b')
try:
cap = py.io.FDCapture(tmpfp.fileno())
print >>tmpfp, 'foo'
cap.writeorg('bar\n')
finally:
tmpfp.close()
f = cap.done()
scap = f.read()
assert scap == 'foo\n'
stmp = tmppath.read()
assert stmp == "bar\n"
def test_writeorg_wrongtype(self):
tmppath = py.test.ensuretemp('test_writeorg').ensure('stdout',
file=True)
tmpfp = tmppath.open('r')
try:
cap = py.io.FDCapture(tmpfp.fileno())
py.test.raises(IOError, "cap.writeorg('bar\\n')")
finally:
tmpfp.close()
f = cap.done()
class TestCapturing: class TestCapturing:
def getcapture(self): def getcapture(self):
return py.io.OutErrCapture() return py.io.OutErrCapture()

View File

@ -263,7 +263,8 @@ class LSession(AbstractSession):
try: try:
pkgdir = self.getpkgdir(self.config.args[0]) pkgdir = self.getpkgdir(self.config.args[0])
apigen.build(pkgdir, apigen.build(pkgdir,
DocStorageAccessor(self.docstorage)) DocStorageAccessor(self.docstorage),
capture)
finally: finally:
capture.reset() capture.reset()