[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:
parent
3f31ed5742
commit
9f491f2058
|
@ -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')
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue