deprecate py.compat.doctest|subprocess|textwrap|...

(and for now pass through Python stdlib provided modules).

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-08-27 21:12:55 +02:00
parent 681d344eac
commit d1932a30ed
40 changed files with 109 additions and 10965 deletions

View File

@ -261,7 +261,7 @@ class PluginDoc(RestWriter):
return return
self.h2("command line options") self.h2("command line options")
self.Print() self.Print()
formatter = py.compat.optparse.IndentedHelpFormatter() formatter = py.std.optparse.IndentedHelpFormatter()
for opt in options: for opt in options:
switches = formatter.format_option_strings(opt) switches = formatter.format_option_strings(opt)
self.Print("``%s``" % switches) self.Print("``%s``" % switches)

View File

@ -7,9 +7,8 @@ obtain system info from remote machine.
import py import py
import sys import sys
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__) parser = py.std.optparse.OptionParser(usage=__doc__)
parser.add_option("-f", "--sshconfig", action="store", dest="ssh_config", default=None, parser.add_option("-f", "--sshconfig", action="store", dest="ssh_config", default=None,
help="use given ssh config file, and add info all contained hosts for getting info") help="use given ssh config file, and add info all contained hosts for getting info")
parser.add_option("-i", "--ignore", action="store", dest="ignores", default=None, parser.add_option("-i", "--ignore", action="store", dest="ignores", default=None,

View File

@ -1,6 +1,8 @@
Changes between 1.0.x and 'trunk' Changes between 1.0.x and 'trunk'
===================================== =====================================
* deprecate py.compat.doctest|subprocess|textwrap|optparse
* deprecate py.magic.autopath, remove py/magic directory * deprecate py.magic.autopath, remove py/magic directory
* move pytest assertion handling to py/code and a pytest_assertion * move pytest assertion handling to py/code and a pytest_assertion

View File

@ -93,26 +93,10 @@ Cross-Python Version compatibility helpers
sources: sources:
* :source:`py/compat/`
* :source:`py/builtin/` * :source:`py/builtin/`
The compat and builtin namespaces help to write code using newer python features on older python interpreters. The compat and builtin namespaces help to write code using newer python features on older python interpreters.
:api:`py.compat`
----------------
:api:`py.compat` provides fixed versions (currently taken from Python 2.4.4) of
a few selected modules to be able to use them across python versions. Currently these are:
* doctest
* optparse
* subprocess
* textwrap
Note that for example ``import doctest`` and ``from py.compat import doctest`` result
into two different module objects no matter what Python version you are using.
So you should only use exactly one of these to avoid confusion in your program.
:api:`py.builtin` :api:`py.builtin`
----------------- -----------------

View File

@ -7,9 +7,8 @@ obtain system info from remote machine.
import py import py
import sys import sys
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__) parser = py.std.optparse.OptionParser(usage=__doc__)
parser.add_option("-f", "--sshconfig", action="store", dest="ssh_config", default=None, parser.add_option("-f", "--sshconfig", action="store", dest="ssh_config", default=None,
help="use given ssh config file, and add info all contained hosts for getting info") help="use given ssh config file, and add info all contained hosts for getting info")
parser.add_option("-i", "--ignore", action="store", dest="ignores", default=None, parser.add_option("-i", "--ignore", action="store", dest="ignores", default=None,

View File

@ -191,12 +191,12 @@ initpkg(__name__,
'log.STDERR' : ('./log/log.py', 'STDERR'), 'log.STDERR' : ('./log/log.py', 'STDERR'),
'log.Syslog' : ('./log/log.py', 'Syslog'), 'log.Syslog' : ('./log/log.py', 'Syslog'),
# compatibility modules (taken from 2.4.4) # compatibility modules (deprecated)
'compat.__doc__' : ('./compat/__init__.py', '__doc__'), 'compat.__doc__' : ('./compat/__init__.py', '__doc__'),
'compat.doctest' : ('./compat/doctest.py', '*'), 'compat.doctest' : ('./compat/dep_doctest.py', 'doctest'),
'compat.optparse' : ('./compat/optparse.py', '*'), 'compat.optparse' : ('./compat/dep_optparse.py', 'optparse'),
'compat.textwrap' : ('./compat/textwrap.py', '*'), 'compat.textwrap' : ('./compat/dep_textwrap.py', 'textwrap'),
'compat.subprocess' : ('./compat/subprocess.py', '*'), 'compat.subprocess' : ('./compat/dep_subprocess.py', 'subprocess'),
}) })

View File

@ -10,7 +10,7 @@ a ".".
import py import py
def main(): def main():
parser = py.compat.optparse.OptionParser(usage=__doc__) parser = py.std.optparse.OptionParser(usage=__doc__)
parser.add_option("-e", "--remove", dest="ext", default=".pyc", action="store", parser.add_option("-e", "--remove", dest="ext", default=".pyc", action="store",
help="remove files with the given comma-separated list of extensions" help="remove files with the given comma-separated list of extensions"
) )

View File

@ -191,7 +191,7 @@ def main():
import py import py
usage = "usage: %prog [-s [filename ...] | [-i | -c filename ...]]" usage = "usage: %prog [-s [filename ...] | [-i | -c filename ...]]"
optparser = py.compat.optparse.OptionParser(usage) optparser = py.std.optparse.OptionParser(usage)
def select_output (option, opt, value, optparser, **kw): def select_output (option, opt, value, optparser, **kw):
if hasattr(optparser, 'output'): if hasattr(optparser, 'output'):

View File

@ -12,10 +12,9 @@ current working directory). Distinguish between test files and normal ones and
report them separately. report them separately.
""" """
import py import py
from py.compat import optparse
def main(): def main():
parser = optparse.OptionParser(usage=__doc__) parser = py.std.optparse.OptionParser(usage=__doc__)
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
countloc(args) countloc(args)

View File

@ -16,9 +16,7 @@ curdir = py.path.local()
def rec(p): def rec(p):
return p.check(dotfile=0) return p.check(dotfile=0)
optparse = py.compat.optparse parser = py.std.optparse.OptionParser(usage=__doc__)
parser = optparse.OptionParser(usage=__doc__)
parser.add_option("-i", "--ignore-case", action="store_true", dest="ignorecase", parser.add_option("-i", "--ignore-case", action="store_true", dest="ignorecase",
help="ignore case distinctions") help="ignore case distinctions")
parser.add_option("-C", "--context", action="store", type="int", dest="context", parser.add_option("-C", "--context", action="store", type="int", dest="context",

View File

@ -22,9 +22,8 @@ else:
def log(msg): def log(msg):
pass pass
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__) parser = py.std.optparse.OptionParser(usage=__doc__)
parser.add_option("--topdf", action="store_true", dest="topdf", default=False, parser.add_option("--topdf", action="store_true", dest="topdf", default=False,
help="generate pdf files") help="generate pdf files")
parser.add_option("--stylesheet", dest="stylesheet", default=None, parser.add_option("--stylesheet", dest="stylesheet", default=None,

View File

@ -41,9 +41,8 @@ def svnwcrevert(path, root=None, precious=[]):
svnwcrevert(p, root) svnwcrevert(p, root)
# XXX add a functional test # XXX add a functional test
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__) parser = py.std.optparse.OptionParser(usage=__doc__)
parser.add_option("-p", "--precious", parser.add_option("-p", "--precious",
action="append", dest="precious", default=[], action="append", dest="precious", default=[],
help="preserve files with this name") help="preserve files with this name")

View File

@ -1,8 +0,0 @@
License for modules in py/compat directory
==============================================================
The "*.py" files in py/compat/ and subdirectories are all
- except when otherwise stated at the beginning of the file -
copyrighted by the Python Software Foundation and licensed
under the Python Software License of which you can find a copy
here: http://www.python.org/doc/Copyright.html

View File

@ -1,5 +0,0 @@
import py
class Directory(py.test.collect.Directory):
def collect(self):
py.test.skip("compat tests need to be run manually")

4
py/compat/dep_doctest.py Normal file
View File

@ -0,0 +1,4 @@
import py
py.log._apiwarn("1.1", "py.compat.doctest deprecated, use standard library version.", stacklevel="initpkg")
doctest = py.std.doctest

View File

@ -0,0 +1,4 @@
import py
py.log._apiwarn("1.1", "py.compat.optparse deprecated, use standard library version.", stacklevel="initpkg")
optparse = py.std.optparse

View File

@ -0,0 +1,4 @@
import py
py.log._apiwarn("1.1", "py.compat.subprocess deprecated, use standard library version.", stacklevel="initpkg")
subprocess = py.std.subprocess

View File

@ -0,0 +1,4 @@
import py
py.log._apiwarn("1.1", "py.compat.textwrap deprecated, use standard library version.", stacklevel="initpkg")
textwrap = py.std.textwrap

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
def test_functional_deprecation(testdir):
testdir.makepyfile("""
import py
def test_compat_deprecations(recwarn):
for name in 'subprocess optparse textwrap doctest'.split():
check(recwarn, name)
def check(recwarn, name):
x = getattr(py.compat, name)
recwarn.pop(DeprecationWarning)
recwarn.clear()
assert x == getattr(py.std, name)
""")
result = testdir.runpytest()
assert result.ret == 0

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +0,0 @@
This is a sample doctest in a text file.
In this example, we'll rely on a global variable being set for us
already:
>>> favorite_color
'blue'
We can make this fail by disabling the blank-line feature.
>>> if 1:
... print 'a'
... print
... print 'b'
a
<BLANKLINE>
b

View File

@ -1,122 +0,0 @@
# -*- coding: utf-8 -*-
u"""A module to test whether doctest recognizes some 2.2 features,
like static and class methods.
>>> print 'yup' # 1
yup
We include some (random) encoded (utf-8) text in the text surrounding
the example. It should be ignored:
ЉЊЈЁЂ
"""
from test import test_support
class C(object):
u"""Class C.
>>> print C() # 2
42
We include some (random) encoded (utf-8) text in the text surrounding
the example. It should be ignored:
ЉЊЈЁЂ
"""
def __init__(self):
"""C.__init__.
>>> print C() # 3
42
"""
def __str__(self):
"""
>>> print C() # 4
42
"""
return "42"
class D(object):
"""A nested D class.
>>> print "In D!" # 5
In D!
"""
def nested(self):
"""
>>> print 3 # 6
3
"""
def getx(self):
"""
>>> c = C() # 7
>>> c.x = 12 # 8
>>> print c.x # 9
-12
"""
return -self._x
def setx(self, value):
"""
>>> c = C() # 10
>>> c.x = 12 # 11
>>> print c.x # 12
-12
"""
self._x = value
x = property(getx, setx, doc="""\
>>> c = C() # 13
>>> c.x = 12 # 14
>>> print c.x # 15
-12
""")
def statm():
"""
A static method.
>>> print C.statm() # 16
666
>>> print C().statm() # 17
666
"""
return 666
statm = staticmethod(statm)
def clsm(cls, val):
"""
A class method.
>>> print C.clsm(22) # 18
22
>>> print C().clsm(23) # 19
23
"""
return val
clsm = classmethod(clsm)
def test_main():
from py.__.compat.testing import test_doctest2
EXPECTED = 19
f, t = test_support.run_doctest(test_doctest2)
if t != EXPECTED:
raise test_support.TestFailed("expected %d tests to run, not %d" %
(EXPECTED, t))
# Pollute the namespace with a bunch of imported functions and classes,
# to make sure they don't get tested.
from py.compat.doctest import *
if __name__ == '__main__':
test_main()

View File

@ -1,14 +0,0 @@
This is a sample doctest in a text file.
In this example, we'll rely on some silly setup:
>>> import test.test_doctest
>>> test.test_doctest.sillySetup
True
This test also has some (random) encoded (utf-8) unicode text:
ЉЊЈЁЂ
This doesn't cause a problem in the tect surrounding the examples, but
we include it here (in this test text file) to make sure. :)

File diff suppressed because it is too large Load Diff

View File

@ -1,563 +0,0 @@
import unittest
from test import test_support
from py.compat import subprocess
import sys
import signal
import os
import tempfile
import time
import re
mswindows = (sys.platform == "win32")
#
# Depends on the following external programs: Python
#
if mswindows:
SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), '
'os.O_BINARY);')
else:
SETBINARY = ''
# In a debug build, stuff like "[6580 refs]" is printed to stderr at
# shutdown time. That frustrates tests trying to check stderr produced
# from a spawned Python process.
def remove_stderr_debug_decorations(stderr):
return re.sub(r"\[\d+ refs\]\r?\n?$", "", stderr)
class ProcessTestCase(unittest.TestCase):
def mkstemp(self):
"""wrapper for mkstemp, calling mktemp if mkstemp is not available"""
if hasattr(tempfile, "mkstemp"):
return tempfile.mkstemp()
else:
fname = tempfile.mktemp()
return os.open(fname, os.O_RDWR|os.O_CREAT), fname
#
# Generic tests
#
def test_call_seq(self):
# call() function with sequence argument
rc = subprocess.call([sys.executable, "-c",
"import sys; sys.exit(47)"])
self.assertEqual(rc, 47)
def test_call_kwargs(self):
# call() function with keyword args
newenv = os.environ.copy()
newenv["FRUIT"] = "banana"
rc = subprocess.call([sys.executable, "-c",
'import sys, os;' \
'sys.exit(os.getenv("FRUIT")=="banana")'],
env=newenv)
self.assertEqual(rc, 1)
def test_stdin_none(self):
# .stdin is None when not redirected
p = subprocess.Popen([sys.executable, "-c", 'print "banana"'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
self.assertEqual(p.stdin, None)
def test_stdout_none(self):
# .stdout is None when not redirected
p = subprocess.Popen([sys.executable, "-c",
'print " this bit of output is from a '
'test of stdout in a different '
'process ..."'],
stdin=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
self.assertEqual(p.stdout, None)
def test_stderr_none(self):
# .stderr is None when not redirected
p = subprocess.Popen([sys.executable, "-c", 'print "banana"'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.wait()
self.assertEqual(p.stderr, None)
def test_executable(self):
p = subprocess.Popen(["somethingyoudonthave",
"-c", "import sys; sys.exit(47)"],
executable=sys.executable)
p.wait()
self.assertEqual(p.returncode, 47)
def test_stdin_pipe(self):
# stdin redirection
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.exit(sys.stdin.read() == "pear")'],
stdin=subprocess.PIPE)
p.stdin.write("pear")
p.stdin.close()
p.wait()
self.assertEqual(p.returncode, 1)
def test_stdin_filedes(self):
# stdin is set to open file descriptor
tf = tempfile.TemporaryFile()
d = tf.fileno()
os.write(d, "pear")
os.lseek(d, 0, 0)
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.exit(sys.stdin.read() == "pear")'],
stdin=d)
p.wait()
self.assertEqual(p.returncode, 1)
def test_stdin_fileobj(self):
# stdin is set to open file object
tf = tempfile.TemporaryFile()
tf.write("pear")
tf.seek(0)
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.exit(sys.stdin.read() == "pear")'],
stdin=tf)
p.wait()
self.assertEqual(p.returncode, 1)
def test_stdout_pipe(self):
# stdout redirection
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.stdout.write("orange")'],
stdout=subprocess.PIPE)
self.assertEqual(p.stdout.read(), "orange")
def test_stdout_filedes(self):
# stdout is set to open file descriptor
tf = tempfile.TemporaryFile()
d = tf.fileno()
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.stdout.write("orange")'],
stdout=d)
p.wait()
os.lseek(d, 0, 0)
self.assertEqual(os.read(d, 1024), "orange")
def test_stdout_fileobj(self):
# stdout is set to open file object
tf = tempfile.TemporaryFile()
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.stdout.write("orange")'],
stdout=tf)
p.wait()
tf.seek(0)
self.assertEqual(tf.read(), "orange")
def test_stderr_pipe(self):
# stderr redirection
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.stderr.write("strawberry")'],
stderr=subprocess.PIPE)
self.assertEqual(remove_stderr_debug_decorations(p.stderr.read()),
"strawberry")
def test_stderr_filedes(self):
# stderr is set to open file descriptor
tf = tempfile.TemporaryFile()
d = tf.fileno()
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.stderr.write("strawberry")'],
stderr=d)
p.wait()
os.lseek(d, 0, 0)
self.assertEqual(remove_stderr_debug_decorations(os.read(d, 1024)),
"strawberry")
def test_stderr_fileobj(self):
# stderr is set to open file object
tf = tempfile.TemporaryFile()
p = subprocess.Popen([sys.executable, "-c",
'import sys; sys.stderr.write("strawberry")'],
stderr=tf)
p.wait()
tf.seek(0)
self.assertEqual(remove_stderr_debug_decorations(tf.read()),
"strawberry")
def test_stdout_stderr_pipe(self):
# capture stdout and stderr to the same pipe
p = subprocess.Popen([sys.executable, "-c",
'import sys;' \
'sys.stdout.write("apple");' \
'sys.stdout.flush();' \
'sys.stderr.write("orange")'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output = p.stdout.read()
stripped = remove_stderr_debug_decorations(output)
self.assertEqual(stripped, "appleorange")
def test_stdout_stderr_file(self):
# capture stdout and stderr to the same open file
tf = tempfile.TemporaryFile()
p = subprocess.Popen([sys.executable, "-c",
'import sys;' \
'sys.stdout.write("apple");' \
'sys.stdout.flush();' \
'sys.stderr.write("orange")'],
stdout=tf,
stderr=tf)
p.wait()
tf.seek(0)
output = tf.read()
stripped = remove_stderr_debug_decorations(output)
self.assertEqual(stripped, "appleorange")
def test_cwd(self):
tmpdir = os.getenv("TEMP", "/tmp")
# We cannot use os.path.realpath to canonicalize the path,
# since it doesn't expand Tru64 {memb} strings. See bug 1063571.
cwd = os.getcwd()
os.chdir(tmpdir)
tmpdir = os.getcwd()
os.chdir(cwd)
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' \
'sys.stdout.write(os.getcwd())'],
stdout=subprocess.PIPE,
cwd=tmpdir)
normcase = os.path.normcase
self.assertEqual(normcase(p.stdout.read()), normcase(tmpdir))
def test_env(self):
newenv = os.environ.copy()
newenv["FRUIT"] = "orange"
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' \
'sys.stdout.write(os.getenv("FRUIT"))'],
stdout=subprocess.PIPE,
env=newenv)
self.assertEqual(p.stdout.read(), "orange")
def test_communicate(self):
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' \
'sys.stderr.write("pineapple");' \
'sys.stdout.write(sys.stdin.read())'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(stdout, stderr) = p.communicate("banana")
self.assertEqual(stdout, "banana")
self.assertEqual(remove_stderr_debug_decorations(stderr),
"pineapple")
def test_communicate_returns(self):
# communicate() should return None if no redirection is active
p = subprocess.Popen([sys.executable, "-c",
"import sys; sys.exit(47)"])
(stdout, stderr) = p.communicate()
self.assertEqual(stdout, None)
self.assertEqual(stderr, None)
def test_communicate_pipe_buf(self):
# communicate() with writes larger than pipe_buf
# This test will probably deadlock rather than fail, if
# communicate() does not work properly.
x, y = os.pipe()
if mswindows:
pipe_buf = 512
else:
pipe_buf = os.fpathconf(x, "PC_PIPE_BUF")
os.close(x)
os.close(y)
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;'
'sys.stdout.write(sys.stdin.read(47));' \
'sys.stderr.write("xyz"*%d);' \
'sys.stdout.write(sys.stdin.read())' % pipe_buf],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
string_to_write = "abc"*pipe_buf
(stdout, stderr) = p.communicate(string_to_write)
self.assertEqual(stdout, string_to_write)
def test_writes_before_communicate(self):
# stdin.write before communicate()
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' \
'sys.stdout.write(sys.stdin.read())'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
p.stdin.write("banana")
(stdout, stderr) = p.communicate("split")
self.assertEqual(stdout, "bananasplit")
self.assertEqual(remove_stderr_debug_decorations(stderr), "")
def test_universal_newlines(self):
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' + SETBINARY +
'sys.stdout.write("line1\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line2\\r");'
'sys.stdout.flush();'
'sys.stdout.write("line3\\r\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line4\\r");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline5");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline6");'],
stdout=subprocess.PIPE,
universal_newlines=1)
stdout = p.stdout.read()
if hasattr(open, 'newlines'):
# Interpreter with universal newline support
self.assertEqual(stdout,
"line1\nline2\nline3\nline4\nline5\nline6")
else:
# Interpreter without universal newline support
self.assertEqual(stdout,
"line1\nline2\rline3\r\nline4\r\nline5\nline6")
def test_universal_newlines_communicate(self):
# universal newlines through communicate()
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' + SETBINARY +
'sys.stdout.write("line1\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line2\\r");'
'sys.stdout.flush();'
'sys.stdout.write("line3\\r\\n");'
'sys.stdout.flush();'
'sys.stdout.write("line4\\r");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline5");'
'sys.stdout.flush();'
'sys.stdout.write("\\nline6");'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=1)
(stdout, stderr) = p.communicate()
if hasattr(open, 'newlines'):
# Interpreter with universal newline support
self.assertEqual(stdout,
"line1\nline2\nline3\nline4\nline5\nline6")
else:
# Interpreter without universal newline support
self.assertEqual(stdout, "line1\nline2\rline3\r\nline4\r\nline5\nline6")
def test_no_leaking(self):
# Make sure we leak no resources
if test_support.is_resource_enabled("subprocess") and not mswindows:
max_handles = 1026 # too much for most UNIX systems
else:
max_handles = 65
for i in range(max_handles):
p = subprocess.Popen([sys.executable, "-c",
"import sys;sys.stdout.write(sys.stdin.read())"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
data = p.communicate("lime")[0]
self.assertEqual(data, "lime")
def test_list2cmdline(self):
self.assertEqual(subprocess.list2cmdline(['a b c', 'd', 'e']),
'"a b c" d e')
self.assertEqual(subprocess.list2cmdline(['ab"c', '\\', 'd']),
'ab\\"c \\ d')
self.assertEqual(subprocess.list2cmdline(['a\\\\\\b', 'de fg', 'h']),
'a\\\\\\b "de fg" h')
self.assertEqual(subprocess.list2cmdline(['a\\"b', 'c', 'd']),
'a\\\\\\"b c d')
self.assertEqual(subprocess.list2cmdline(['a\\\\b c', 'd', 'e']),
'"a\\\\b c" d e')
self.assertEqual(subprocess.list2cmdline(['a\\\\b\\ c', 'd', 'e']),
'"a\\\\b\\ c" d e')
def test_poll(self):
p = subprocess.Popen([sys.executable,
"-c", "import time; time.sleep(1)"])
count = 0
while p.poll() is None:
time.sleep(0.1)
count += 1
# We expect that the poll loop probably went around about 10 times,
# but, based on system scheduling we can't control, it's possible
# poll() never returned None. It "should be" very rare that it
# didn't go around at least twice.
self.assert_(count >= 2)
# Subsequent invocations should just return the returncode
self.assertEqual(p.poll(), 0)
def test_wait(self):
p = subprocess.Popen([sys.executable,
"-c", "import time; time.sleep(2)"])
self.assertEqual(p.wait(), 0)
# Subsequent invocations should just return the returncode
self.assertEqual(p.wait(), 0)
def test_invalid_bufsize(self):
# an invalid type of the bufsize argument should raise
# TypeError.
try:
subprocess.Popen([sys.executable, "-c", "pass"], "orange")
except TypeError:
pass
else:
self.fail("Expected TypeError")
#
# POSIX tests
#
if not mswindows:
def test_exceptions(self):
# catched & re-raised exceptions
try:
p = subprocess.Popen([sys.executable, "-c", ""],
cwd="/this/path/does/not/exist")
except OSError, e:
# The attribute child_traceback should contain "os.chdir"
# somewhere.
self.assertNotEqual(e.child_traceback.find("os.chdir"), -1)
else:
self.fail("Expected OSError")
def test_run_abort(self):
# returncode handles signal termination
p = subprocess.Popen([sys.executable,
"-c", "import os; os.abort()"])
p.wait()
self.assertEqual(-p.returncode, signal.SIGABRT)
def test_preexec(self):
# preexec function
p = subprocess.Popen([sys.executable, "-c",
'import sys,os;' \
'sys.stdout.write(os.getenv("FRUIT"))'],
stdout=subprocess.PIPE,
preexec_fn=lambda: os.putenv("FRUIT", "apple"))
self.assertEqual(p.stdout.read(), "apple")
def test_args_string(self):
# args is a string
f, fname = self.mkstemp()
os.write(f, "#!/bin/sh\n")
os.write(f, "exec %s -c 'import sys; sys.exit(47)'\n" %
sys.executable)
os.close(f)
os.chmod(fname, 0700)
p = subprocess.Popen(fname)
p.wait()
os.remove(fname)
self.assertEqual(p.returncode, 47)
def test_invalid_args(self):
# invalid arguments should raise ValueError
self.assertRaises(ValueError, subprocess.call,
[sys.executable,
"-c", "import sys; sys.exit(47)"],
startupinfo=47)
self.assertRaises(ValueError, subprocess.call,
[sys.executable,
"-c", "import sys; sys.exit(47)"],
creationflags=47)
def test_shell_sequence(self):
# Run command through the shell (sequence)
newenv = os.environ.copy()
newenv["FRUIT"] = "apple"
p = subprocess.Popen(["echo $FRUIT"], shell=1,
stdout=subprocess.PIPE,
env=newenv)
self.assertEqual(p.stdout.read().strip(), "apple")
def test_shell_string(self):
# Run command through the shell (string)
newenv = os.environ.copy()
newenv["FRUIT"] = "apple"
p = subprocess.Popen("echo $FRUIT", shell=1,
stdout=subprocess.PIPE,
env=newenv)
self.assertEqual(p.stdout.read().strip(), "apple")
def test_call_string(self):
# call() function with string argument on UNIX
f, fname = self.mkstemp()
os.write(f, "#!/bin/sh\n")
os.write(f, "exec %s -c 'import sys; sys.exit(47)'\n" %
sys.executable)
os.close(f)
os.chmod(fname, 0700)
rc = subprocess.call(fname)
os.remove(fname)
self.assertEqual(rc, 47)
#
# Windows tests
#
if mswindows:
def test_startupinfo(self):
# startupinfo argument
# We uses hardcoded constants, because we do not want to
# depend on win32all.
STARTF_USESHOWWINDOW = 1
SW_MAXIMIZE = 3
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags = STARTF_USESHOWWINDOW
startupinfo.wShowWindow = SW_MAXIMIZE
# Since Python is a console process, it won't be affected
# by wShowWindow, but the argument should be silently
# ignored
subprocess.call([sys.executable, "-c", "import sys; sys.exit(0)"],
startupinfo=startupinfo)
def test_creationflags(self):
# creationflags argument
CREATE_NEW_CONSOLE = 16
sys.stderr.write(" a DOS box should flash briefly ...\n")
subprocess.call(sys.executable +
' -c "import time; time.sleep(0.25)"',
creationflags=CREATE_NEW_CONSOLE)
def test_invalid_args(self):
# invalid arguments should raise ValueError
self.assertRaises(ValueError, subprocess.call,
[sys.executable,
"-c", "import sys; sys.exit(47)"],
preexec_fn=lambda: 1)
self.assertRaises(ValueError, subprocess.call,
[sys.executable,
"-c", "import sys; sys.exit(47)"],
close_fds=True)
def test_shell_sequence(self):
# Run command through the shell (sequence)
newenv = os.environ.copy()
newenv["FRUIT"] = "physalis"
p = subprocess.Popen(["set"], shell=1,
stdout=subprocess.PIPE,
env=newenv)
self.assertNotEqual(p.stdout.read().find("physalis"), -1)
def test_shell_string(self):
# Run command through the shell (string)
newenv = os.environ.copy()
newenv["FRUIT"] = "physalis"
p = subprocess.Popen("set", shell=1,
stdout=subprocess.PIPE,
env=newenv)
self.assertNotEqual(p.stdout.read().find("physalis"), -1)
def test_call_string(self):
# call() function with string argument on Windows
rc = subprocess.call(sys.executable +
' -c "import sys; sys.exit(47)"')
self.assertEqual(rc, 47)
def test_main():
test_support.run_unittest(ProcessTestCase)
if __name__ == "__main__":
test_main()

View File

@ -1,532 +0,0 @@
#
# Test suite for the textwrap module.
#
# Original tests written by Greg Ward <gward@python.net>.
# Converted to PyUnit by Peter Hansen <peter@engcorp.com>.
# Currently maintained by Greg Ward.
#
# $Id: test_textwrap.py 38573 2005-03-05 02:38:33Z gward $
#
import unittest
from test import test_support
import py
textwrap = py.compat.textwrap
TextWrapper = textwrap.TextWrapper
wrap = textwrap.wrap
fill = textwrap.fill
dedent = textwrap.dedent
class BaseTestCase(unittest.TestCase):
'''Parent class with utility methods for textwrap tests.'''
def show(self, textin):
if isinstance(textin, list):
result = []
for i in range(len(textin)):
result.append(" %d: %r" % (i, textin[i]))
result = '\n'.join(result)
elif isinstance(textin, basestring):
result = " %s\n" % repr(textin)
return result
def check(self, result, expect):
self.assertEquals(result, expect,
'expected:\n%s\nbut got:\n%s' % (
self.show(expect), self.show(result)))
def check_wrap(self, text, width, expect, **kwargs):
result = wrap(text, width, **kwargs)
self.check(result, expect)
def check_split(self, text, expect):
result = self.wrapper._split(text)
self.assertEquals(result, expect,
"\nexpected %r\n"
"but got %r" % (expect, result))
class WrapTestCase(BaseTestCase):
def setUp(self):
self.wrapper = TextWrapper(width=45)
def test_simple(self):
# Simple case: just words, spaces, and a bit of punctuation
text = "Hello there, how are you this fine day? I'm glad to hear it!"
self.check_wrap(text, 12,
["Hello there,",
"how are you",
"this fine",
"day? I'm",
"glad to hear",
"it!"])
self.check_wrap(text, 42,
["Hello there, how are you this fine day?",
"I'm glad to hear it!"])
self.check_wrap(text, 80, [text])
def test_whitespace(self):
# Whitespace munging and end-of-sentence detection
text = """\
This is a paragraph that already has
line breaks. But some of its lines are much longer than the others,
so it needs to be wrapped.
Some lines are \ttabbed too.
What a mess!
"""
expect = ["This is a paragraph that already has line",
"breaks. But some of its lines are much",
"longer than the others, so it needs to be",
"wrapped. Some lines are tabbed too. What a",
"mess!"]
wrapper = TextWrapper(45, fix_sentence_endings=True)
result = wrapper.wrap(text)
self.check(result, expect)
result = wrapper.fill(text)
self.check(result, '\n'.join(expect))
def test_fix_sentence_endings(self):
wrapper = TextWrapper(60, fix_sentence_endings=True)
# SF #847346: ensure that fix_sentence_endings=True does the
# right thing even on input short enough that it doesn't need to
# be wrapped.
text = "A short line. Note the single space."
expect = ["A short line. Note the single space."]
self.check(wrapper.wrap(text), expect)
# Test some of the hairy end cases that _fix_sentence_endings()
# is supposed to handle (the easy stuff is tested in
# test_whitespace() above).
text = "Well, Doctor? What do you think?"
expect = ["Well, Doctor? What do you think?"]
self.check(wrapper.wrap(text), expect)
text = "Well, Doctor?\nWhat do you think?"
self.check(wrapper.wrap(text), expect)
text = 'I say, chaps! Anyone for "tennis?"\nHmmph!'
expect = ['I say, chaps! Anyone for "tennis?" Hmmph!']
self.check(wrapper.wrap(text), expect)
wrapper.width = 20
expect = ['I say, chaps!', 'Anyone for "tennis?"', 'Hmmph!']
self.check(wrapper.wrap(text), expect)
text = 'And she said, "Go to hell!"\nCan you believe that?'
expect = ['And she said, "Go to',
'hell!" Can you',
'believe that?']
self.check(wrapper.wrap(text), expect)
wrapper.width = 60
expect = ['And she said, "Go to hell!" Can you believe that?']
self.check(wrapper.wrap(text), expect)
def test_wrap_short(self):
# Wrapping to make short lines longer
text = "This is a\nshort paragraph."
self.check_wrap(text, 20, ["This is a short",
"paragraph."])
self.check_wrap(text, 40, ["This is a short paragraph."])
def test_wrap_short_1line(self):
# Test endcases
text = "This is a short line."
self.check_wrap(text, 30, ["This is a short line."])
self.check_wrap(text, 30, ["(1) This is a short line."],
initial_indent="(1) ")
def test_hyphenated(self):
# Test breaking hyphenated words
text = ("this-is-a-useful-feature-for-"
"reformatting-posts-from-tim-peters'ly")
self.check_wrap(text, 40,
["this-is-a-useful-feature-for-",
"reformatting-posts-from-tim-peters'ly"])
self.check_wrap(text, 41,
["this-is-a-useful-feature-for-",
"reformatting-posts-from-tim-peters'ly"])
self.check_wrap(text, 42,
["this-is-a-useful-feature-for-reformatting-",
"posts-from-tim-peters'ly"])
def test_hyphenated_numbers(self):
# Test that hyphenated numbers (eg. dates) are not broken like words.
text = ("Python 1.0.0 was released on 1994-01-26. Python 1.0.1 was\n"
"released on 1994-02-15.")
self.check_wrap(text, 30, ['Python 1.0.0 was released on',
'1994-01-26. Python 1.0.1 was',
'released on 1994-02-15.'])
self.check_wrap(text, 40, ['Python 1.0.0 was released on 1994-01-26.',
'Python 1.0.1 was released on 1994-02-15.'])
text = "I do all my shopping at 7-11."
self.check_wrap(text, 25, ["I do all my shopping at",
"7-11."])
self.check_wrap(text, 27, ["I do all my shopping at",
"7-11."])
self.check_wrap(text, 29, ["I do all my shopping at 7-11."])
def test_em_dash(self):
# Test text with em-dashes
text = "Em-dashes should be written -- thus."
self.check_wrap(text, 25,
["Em-dashes should be",
"written -- thus."])
# Probe the boundaries of the properly written em-dash,
# ie. " -- ".
self.check_wrap(text, 29,
["Em-dashes should be written",
"-- thus."])
expect = ["Em-dashes should be written --",
"thus."]
self.check_wrap(text, 30, expect)
self.check_wrap(text, 35, expect)
self.check_wrap(text, 36,
["Em-dashes should be written -- thus."])
# The improperly written em-dash is handled too, because
# it's adjacent to non-whitespace on both sides.
text = "You can also do--this or even---this."
expect = ["You can also do",
"--this or even",
"---this."]
self.check_wrap(text, 15, expect)
self.check_wrap(text, 16, expect)
expect = ["You can also do--",
"this or even---",
"this."]
self.check_wrap(text, 17, expect)
self.check_wrap(text, 19, expect)
expect = ["You can also do--this or even",
"---this."]
self.check_wrap(text, 29, expect)
self.check_wrap(text, 31, expect)
expect = ["You can also do--this or even---",
"this."]
self.check_wrap(text, 32, expect)
self.check_wrap(text, 35, expect)
# All of the above behaviour could be deduced by probing the
# _split() method.
text = "Here's an -- em-dash and--here's another---and another!"
expect = ["Here's", " ", "an", " ", "--", " ", "em-", "dash", " ",
"and", "--", "here's", " ", "another", "---",
"and", " ", "another!"]
self.check_split(text, expect)
text = "and then--bam!--he was gone"
expect = ["and", " ", "then", "--", "bam!", "--",
"he", " ", "was", " ", "gone"]
self.check_split(text, expect)
def test_unix_options (self):
# Test that Unix-style command-line options are wrapped correctly.
# Both Optik (OptionParser) and Docutils rely on this behaviour!
text = "You should use the -n option, or --dry-run in its long form."
self.check_wrap(text, 20,
["You should use the",
"-n option, or --dry-",
"run in its long",
"form."])
self.check_wrap(text, 21,
["You should use the -n",
"option, or --dry-run",
"in its long form."])
expect = ["You should use the -n option, or",
"--dry-run in its long form."]
self.check_wrap(text, 32, expect)
self.check_wrap(text, 34, expect)
self.check_wrap(text, 35, expect)
self.check_wrap(text, 38, expect)
expect = ["You should use the -n option, or --dry-",
"run in its long form."]
self.check_wrap(text, 39, expect)
self.check_wrap(text, 41, expect)
expect = ["You should use the -n option, or --dry-run",
"in its long form."]
self.check_wrap(text, 42, expect)
# Again, all of the above can be deduced from _split().
text = "the -n option, or --dry-run or --dryrun"
expect = ["the", " ", "-n", " ", "option,", " ", "or", " ",
"--dry-", "run", " ", "or", " ", "--dryrun"]
self.check_split(text, expect)
def test_funky_hyphens (self):
# Screwy edge cases cooked up by David Goodger. All reported
# in SF bug #596434.
self.check_split("what the--hey!", ["what", " ", "the", "--", "hey!"])
self.check_split("what the--", ["what", " ", "the--"])
self.check_split("what the--.", ["what", " ", "the--."])
self.check_split("--text--.", ["--text--."])
# When I first read bug #596434, this is what I thought David
# was talking about. I was wrong; these have always worked
# fine. The real problem is tested in test_funky_parens()
# below...
self.check_split("--option", ["--option"])
self.check_split("--option-opt", ["--option-", "opt"])
self.check_split("foo --option-opt bar",
["foo", " ", "--option-", "opt", " ", "bar"])
def test_punct_hyphens(self):
# Oh bother, SF #965425 found another problem with hyphens --
# hyphenated words in single quotes weren't handled correctly.
# In fact, the bug is that *any* punctuation around a hyphenated
# word was handled incorrectly, except for a leading "--", which
# was special-cased for Optik and Docutils. So test a variety
# of styles of punctuation around a hyphenated word.
# (Actually this is based on an Optik bug report, #813077).
self.check_split("the 'wibble-wobble' widget",
['the', ' ', "'wibble-", "wobble'", ' ', 'widget'])
self.check_split('the "wibble-wobble" widget',
['the', ' ', '"wibble-', 'wobble"', ' ', 'widget'])
self.check_split("the (wibble-wobble) widget",
['the', ' ', "(wibble-", "wobble)", ' ', 'widget'])
self.check_split("the ['wibble-wobble'] widget",
['the', ' ', "['wibble-", "wobble']", ' ', 'widget'])
def test_funky_parens (self):
# Second part of SF bug #596434: long option strings inside
# parentheses.
self.check_split("foo (--option) bar",
["foo", " ", "(--option)", " ", "bar"])
# Related stuff -- make sure parens work in simpler contexts.
self.check_split("foo (bar) baz",
["foo", " ", "(bar)", " ", "baz"])
self.check_split("blah (ding dong), wubba",
["blah", " ", "(ding", " ", "dong),",
" ", "wubba"])
def test_initial_whitespace(self):
# SF bug #622849 reported inconsistent handling of leading
# whitespace; let's test that a bit, shall we?
text = " This is a sentence with leading whitespace."
self.check_wrap(text, 50,
[" This is a sentence with leading whitespace."])
self.check_wrap(text, 30,
[" This is a sentence with", "leading whitespace."])
def test_unicode(self):
# *Very* simple test of wrapping Unicode strings. I'm sure
# there's more to it than this, but let's at least make
# sure textwrap doesn't crash on Unicode input!
text = u"Hello there, how are you today?"
self.check_wrap(text, 50, [u"Hello there, how are you today?"])
self.check_wrap(text, 20, [u"Hello there, how are", "you today?"])
olines = self.wrapper.wrap(text)
assert isinstance(olines, list) and isinstance(olines[0], unicode)
otext = self.wrapper.fill(text)
assert isinstance(otext, unicode)
def test_split(self):
# Ensure that the standard _split() method works as advertised
# in the comments
text = "Hello there -- you goof-ball, use the -b option!"
result = self.wrapper._split(text)
self.check(result,
["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
"ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"])
def test_bad_width(self):
# Ensure that width <= 0 is caught.
text = "Whatever, it doesn't matter."
self.assertRaises(ValueError, wrap, text, 0)
self.assertRaises(ValueError, wrap, text, -1)
class LongWordTestCase (BaseTestCase):
def setUp(self):
self.wrapper = TextWrapper()
self.text = '''\
Did you say "supercalifragilisticexpialidocious?"
How *do* you spell that odd word, anyways?
'''
def test_break_long(self):
# Wrap text with long words and lots of punctuation
self.check_wrap(self.text, 30,
['Did you say "supercalifragilis',
'ticexpialidocious?" How *do*',
'you spell that odd word,',
'anyways?'])
self.check_wrap(self.text, 50,
['Did you say "supercalifragilisticexpialidocious?"',
'How *do* you spell that odd word, anyways?'])
# SF bug 797650. Prevent an infinite loop by making sure that at
# least one character gets split off on every pass.
self.check_wrap('-'*10+'hello', 10,
['----------',
' h',
' e',
' l',
' l',
' o'],
subsequent_indent = ' '*15)
def test_nobreak_long(self):
# Test with break_long_words disabled
self.wrapper.break_long_words = 0
self.wrapper.width = 30
expect = ['Did you say',
'"supercalifragilisticexpialidocious?"',
'How *do* you spell that odd',
'word, anyways?'
]
result = self.wrapper.wrap(self.text)
self.check(result, expect)
# Same thing with kwargs passed to standalone wrap() function.
result = wrap(self.text, width=30, break_long_words=0)
self.check(result, expect)
class IndentTestCases(BaseTestCase):
# called before each test method
def setUp(self):
self.text = '''\
This paragraph will be filled, first without any indentation,
and then with some (including a hanging indent).'''
def test_fill(self):
# Test the fill() method
expect = '''\
This paragraph will be filled, first
without any indentation, and then with
some (including a hanging indent).'''
result = fill(self.text, 40)
self.check(result, expect)
def test_initial_indent(self):
# Test initial_indent parameter
expect = [" This paragraph will be filled,",
"first without any indentation, and then",
"with some (including a hanging indent)."]
result = wrap(self.text, 40, initial_indent=" ")
self.check(result, expect)
expect = "\n".join(expect)
result = fill(self.text, 40, initial_indent=" ")
self.check(result, expect)
def test_subsequent_indent(self):
# Test subsequent_indent parameter
expect = '''\
* This paragraph will be filled, first
without any indentation, and then
with some (including a hanging
indent).'''
result = fill(self.text, 40,
initial_indent=" * ", subsequent_indent=" ")
self.check(result, expect)
# Despite the similar names, DedentTestCase is *not* the inverse
# of IndentTestCase!
class DedentTestCase(unittest.TestCase):
def test_dedent_nomargin(self):
# No lines indented.
text = "Hello there.\nHow are you?\nOh good, I'm glad."
self.assertEquals(dedent(text), text)
# Similar, with a blank line.
text = "Hello there.\n\nBoo!"
self.assertEquals(dedent(text), text)
# Some lines indented, but overall margin is still zero.
text = "Hello there.\n This is indented."
self.assertEquals(dedent(text), text)
# Again, add a blank line.
text = "Hello there.\n\n Boo!\n"
self.assertEquals(dedent(text), text)
def test_dedent_even(self):
# All lines indented by two spaces.
text = " Hello there.\n How are ya?\n Oh good."
expect = "Hello there.\nHow are ya?\nOh good."
self.assertEquals(dedent(text), expect)
# Same, with blank lines.
text = " Hello there.\n\n How are ya?\n Oh good.\n"
expect = "Hello there.\n\nHow are ya?\nOh good.\n"
self.assertEquals(dedent(text), expect)
# Now indent one of the blank lines.
text = " Hello there.\n \n How are ya?\n Oh good.\n"
expect = "Hello there.\n\nHow are ya?\nOh good.\n"
self.assertEquals(dedent(text), expect)
def test_dedent_uneven(self):
# Lines indented unevenly.
text = '''\
def foo():
while 1:
return foo
'''
expect = '''\
def foo():
while 1:
return foo
'''
self.assertEquals(dedent(text), expect)
# Uneven indentation with a blank line.
text = " Foo\n Bar\n\n Baz\n"
expect = "Foo\n Bar\n\n Baz\n"
self.assertEquals(dedent(text), expect)
# Uneven indentation with a whitespace-only line.
text = " Foo\n Bar\n \n Baz\n"
expect = "Foo\n Bar\n\n Baz\n"
self.assertEquals(dedent(text), expect)
def test_main():
test_support.run_unittest(WrapTestCase,
LongWordTestCase,
IndentTestCases,
DedentTestCase)
if __name__ == '__main__':
test_main()

View File

@ -1,357 +0,0 @@
"""Text wrapping and filling.
"""
# Copyright (C) 1999-2001 Gregory P. Ward.
# Copyright (C) 2002, 2003 Python Software Foundation.
# Written by Greg Ward <gward@python.net>
__revision__ = "$Id: textwrap.py 36379 2007-01-09 16:55:49Z cfbolz $"
import string, re
# Do the right thing with boolean values for all known Python versions
# (so this module can be copied to projects that don't depend on Python
# 2.3, e.g. Optik and Docutils).
try:
True, False
except NameError:
(True, False) = (1, 0)
__all__ = ['TextWrapper', 'wrap', 'fill']
# Hardcode the recognized whitespace characters to the US-ASCII
# whitespace characters. The main reason for doing this is that in
# ISO-8859-1, 0xa0 is non-breaking whitespace, so in certain locales
# that character winds up in string.whitespace. Respecting
# string.whitespace in those cases would 1) make textwrap treat 0xa0 the
# same as any other whitespace char, which is clearly wrong (it's a
# *non-breaking* space), 2) possibly cause problems with Unicode,
# since 0xa0 is not in range(128).
_whitespace = '\t\n\x0b\x0c\r '
class TextWrapper:
"""
Object for wrapping/filling text. The public interface consists of
the wrap() and fill() methods; the other methods are just there for
subclasses to override in order to tweak the default behaviour.
If you want to completely replace the main wrapping algorithm,
you'll probably have to override _wrap_chunks().
Several instance attributes control various aspects of wrapping:
width (default: 70)
the maximum width of wrapped lines (unless break_long_words
is false)
initial_indent (default: "")
string that will be prepended to the first line of wrapped
output. Counts towards the line's width.
subsequent_indent (default: "")
string that will be prepended to all lines save the first
of wrapped output; also counts towards each line's width.
expand_tabs (default: true)
Expand tabs in input text to spaces before further processing.
Each tab will become 1 .. 8 spaces, depending on its position in
its line. If false, each tab is treated as a single character.
replace_whitespace (default: true)
Replace all whitespace characters in the input text by spaces
after tab expansion. Note that if expand_tabs is false and
replace_whitespace is true, every tab will be converted to a
single space!
fix_sentence_endings (default: false)
Ensure that sentence-ending punctuation is always followed
by two spaces. Off by default because the algorithm is
(unavoidably) imperfect.
break_long_words (default: true)
Break words longer than 'width'. If false, those words will not
be broken, and some lines might be longer than 'width'.
"""
whitespace_trans = string.maketrans(_whitespace, ' ' * len(_whitespace))
unicode_whitespace_trans = {}
uspace = ord(u' ')
for x in map(ord, _whitespace):
unicode_whitespace_trans[x] = uspace
# This funky little regex is just the trick for splitting
# text up into word-wrappable chunks. E.g.
# "Hello there -- you goof-ball, use the -b option!"
# splits into
# Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option!
# (after stripping out empty strings).
wordsep_re = re.compile(
r'(\s+|' # any whitespace
r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words
r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash
# XXX this is not locale- or charset-aware -- string.lowercase
# is US-ASCII only (and therefore English-only)
sentence_end_re = re.compile(r'[%s]' # lowercase letter
r'[\.\!\?]' # sentence-ending punct.
r'[\"\']?' # optional end-of-quote
% string.lowercase)
def __init__(self,
width=70,
initial_indent="",
subsequent_indent="",
expand_tabs=True,
replace_whitespace=True,
fix_sentence_endings=False,
break_long_words=True):
self.width = width
self.initial_indent = initial_indent
self.subsequent_indent = subsequent_indent
self.expand_tabs = expand_tabs
self.replace_whitespace = replace_whitespace
self.fix_sentence_endings = fix_sentence_endings
self.break_long_words = break_long_words
# -- Private methods -----------------------------------------------
# (possibly useful for subclasses to override)
def _munge_whitespace(self, text):
"""_munge_whitespace(text : string) -> string
Munge whitespace in text: expand tabs and convert all other
whitespace characters to spaces. Eg. " foo\tbar\n\nbaz"
becomes " foo bar baz".
"""
if self.expand_tabs:
text = text.expandtabs()
if self.replace_whitespace:
if isinstance(text, str):
text = text.translate(self.whitespace_trans)
elif isinstance(text, unicode):
text = text.translate(self.unicode_whitespace_trans)
return text
def _split(self, text):
"""_split(text : string) -> [string]
Split the text to wrap into indivisible chunks. Chunks are
not quite the same as words; see wrap_chunks() for full
details. As an example, the text
Look, goof-ball -- use the -b option!
breaks into the following chunks:
'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
'use', ' ', 'the', ' ', '-b', ' ', 'option!'
"""
chunks = self.wordsep_re.split(text)
chunks = filter(None, chunks)
return chunks
def _fix_sentence_endings(self, chunks):
"""_fix_sentence_endings(chunks : [string])
Correct for sentence endings buried in 'chunks'. Eg. when the
original text contains "... foo.\nBar ...", munge_whitespace()
and split() will convert that to [..., "foo.", " ", "Bar", ...]
which has one too few spaces; this method simply changes the one
space to two.
"""
i = 0
pat = self.sentence_end_re
while i < len(chunks)-1:
if chunks[i+1] == " " and pat.search(chunks[i]):
chunks[i+1] = " "
i += 2
else:
i += 1
def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
"""_handle_long_word(chunks : [string],
cur_line : [string],
cur_len : int, width : int)
Handle a chunk of text (most likely a word, not whitespace) that
is too long to fit in any line.
"""
space_left = max(width - cur_len, 1)
# If we're allowed to break long words, then do so: put as much
# of the next chunk onto the current line as will fit.
if self.break_long_words:
cur_line.append(reversed_chunks[-1][:space_left])
reversed_chunks[-1] = reversed_chunks[-1][space_left:]
# Otherwise, we have to preserve the long word intact. Only add
# it to the current line if there's nothing already there --
# that minimizes how much we violate the width constraint.
elif not cur_line:
cur_line.append(reversed_chunks.pop())
# If we're not allowed to break long words, and there's already
# text on the current line, do nothing. Next time through the
# main loop of _wrap_chunks(), we'll wind up here again, but
# cur_len will be zero, so the next line will be entirely
# devoted to the long word that we can't handle right now.
def _wrap_chunks(self, chunks):
"""_wrap_chunks(chunks : [string]) -> [string]
Wrap a sequence of text chunks and return a list of lines of
length 'self.width' or less. (If 'break_long_words' is false,
some lines may be longer than this.) Chunks correspond roughly
to words and the whitespace between them: each chunk is
indivisible (modulo 'break_long_words'), but a line break can
come between any two chunks. Chunks should not have internal
whitespace; ie. a chunk is either all whitespace or a "word".
Whitespace chunks will be removed from the beginning and end of
lines, but apart from that whitespace is preserved.
"""
lines = []
if self.width <= 0:
raise ValueError("invalid width %r (must be > 0)" % self.width)
# Arrange in reverse order so items can be efficiently popped
# from a stack of chucks.
chunks.reverse()
while chunks:
# Start the list of chunks that will make up the current line.
# cur_len is just the length of all the chunks in cur_line.
cur_line = []
cur_len = 0
# Figure out which static string will prefix this line.
if lines:
indent = self.subsequent_indent
else:
indent = self.initial_indent
# Maximum width for this line.
width = self.width - len(indent)
# First chunk on line is whitespace -- drop it, unless this
# is the very beginning of the text (ie. no lines started yet).
if chunks[-1].strip() == '' and lines:
del chunks[-1]
while chunks:
l = len(chunks[-1])
# Can at least squeeze this chunk onto the current line.
if cur_len + l <= width:
cur_line.append(chunks.pop())
cur_len += l
# Nope, this line is full.
else:
break
# The current line is full, and the next chunk is too big to
# fit on *any* line (not just this one).
if chunks and len(chunks[-1]) > width:
self._handle_long_word(chunks, cur_line, cur_len, width)
# If the last chunk on this line is all whitespace, drop it.
if cur_line and cur_line[-1].strip() == '':
del cur_line[-1]
# Convert current line back to a string and store it in list
# of all lines (return value).
if cur_line:
lines.append(indent + ''.join(cur_line))
return lines
# -- Public interface ----------------------------------------------
def wrap(self, text):
"""wrap(text : string) -> [string]
Reformat the single paragraph in 'text' so it fits in lines of
no more than 'self.width' columns, and return a list of wrapped
lines. Tabs in 'text' are expanded with string.expandtabs(),
and all other whitespace characters (including newline) are
converted to space.
"""
text = self._munge_whitespace(text)
chunks = self._split(text)
if self.fix_sentence_endings:
self._fix_sentence_endings(chunks)
return self._wrap_chunks(chunks)
def fill(self, text):
"""fill(text : string) -> string
Reformat the single paragraph in 'text' to fit in lines of no
more than 'self.width' columns, and return a new string
containing the entire wrapped paragraph.
"""
return "\n".join(self.wrap(text))
# -- Convenience interface ---------------------------------------------
def wrap(text, width=70, **kwargs):
"""Wrap a single paragraph of text, returning a list of wrapped lines.
Reformat the single paragraph in 'text' so it fits in lines of no
more than 'width' columns, and return a list of wrapped lines. By
default, tabs in 'text' are expanded with string.expandtabs(), and
all other whitespace characters (including newline) are converted to
space. See TextWrapper class for available keyword args to customize
wrapping behaviour.
"""
w = TextWrapper(width=width, **kwargs)
return w.wrap(text)
def fill(text, width=70, **kwargs):
"""Fill a single paragraph of text, returning a new string.
Reformat the single paragraph in 'text' to fit in lines of no more
than 'width' columns, and return a new string containing the entire
wrapped paragraph. As with wrap(), tabs are expanded and other
whitespace characters converted to space. See TextWrapper class for
available keyword args to customize wrapping behaviour.
"""
w = TextWrapper(width=width, **kwargs)
return w.fill(text)
# -- Loosely related functionality -------------------------------------
def dedent(text):
"""dedent(text : string) -> string
Remove any whitespace than can be uniformly removed from the left
of every line in `text`.
This can be used e.g. to make triple-quoted strings line up with
the left edge of screen/whatever, while still presenting it in the
source code in indented form.
For example:
def test():
# end first line with \ to avoid the empty line!
s = '''\
hello
world
'''
print repr(s) # prints ' hello\n world\n '
print repr(dedent(s)) # prints 'hello\n world\n'
"""
lines = text.expandtabs().split('\n')
margin = None
for line in lines:
content = line.lstrip()
if not content:
continue
indent = len(line) - len(content)
if margin is None:
margin = indent
else:
margin = min(margin, indent)
if margin is not None and margin > 0:
for i in range(len(lines)):
lines[i] = lines[i][margin:]
return '\n'.join(lines)

View File

@ -1,12 +1,8 @@
import os, inspect, socket import os, inspect, socket
import sys import sys
from py.magic import autopath ; mypath = autopath() import py
try:
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
except ImportError:
from py.__.compat.subprocess import Popen, PIPE
import py import py
if sys.platform == "win32": if sys.platform == "win32":
@ -128,8 +124,9 @@ class SocketGateway(InstallableGateway):
host, port = ('', 0) # XXX works on all platforms? host, port = ('', 0) # XXX works on all platforms?
else: else:
host, port = hostport host, port = hostport
mydir = py.path.local(__file__).dirpath()
socketserverbootstrap = py.code.Source( socketserverbootstrap = py.code.Source(
mypath.dirpath('script', 'socketserver.py').read('rU'), """ mydir.join('script', 'socketserver.py').read('rU'), """
import socket import socket
sock = bind_and_listen((%r, %r)) sock = bind_and_listen((%r, %r))
port = sock.getsockname() port = sock.getsockname()

View File

@ -27,6 +27,32 @@ def test_stacklevel():
warning = str(err) warning = str(err)
assert warning.find(":%s" % lno) != -1 assert warning.find(":%s" % lno) != -1
def test_stacklevel_initpkg_with_resolve(testdir):
mod = testdir.makepyfile(initpkg="""
import py
def __getattr__():
f()
def f():
py.log._apiwarn("x", "some", stacklevel="initpkg")
""").pyimport()
capture = py.io.StdCapture()
mod.__getattr__()
out, err = capture.reset()
lno = test_stacklevel_initpkg_with_resolve.func_code.co_firstlineno + 9
warning = str(err)
assert warning.find(":%s" % lno) != -1
def test_stacklevel_initpkg_no_resolve():
def f():
py.log._apiwarn("x", "some", stacklevel="initpkg")
capture = py.io.StdCapture()
f()
out, err = capture.reset()
lno = test_stacklevel_initpkg_no_resolve.func_code.co_firstlineno + 2
warning = str(err)
assert warning.find(":%s" % lno) != -1
def test_function(): def test_function():
capture = py.io.StdCapture() capture = py.io.StdCapture()
py.log._apiwarn("x.y.z", "something", function=test_function) py.log._apiwarn("x.y.z", "something", function=test_function)

View File

@ -13,6 +13,18 @@ class Warning(py.std.exceptions.DeprecationWarning):
def _apiwarn(startversion, msg, stacklevel=1, function=None): def _apiwarn(startversion, msg, stacklevel=1, function=None):
# below is mostly COPIED from python2.4/warnings.py's def warn() # below is mostly COPIED from python2.4/warnings.py's def warn()
# Get context information # Get context information
if stacklevel == "initpkg":
frame = sys._getframe(1)
level = 2
while frame:
co = frame.f_code
if co.co_name == "__getattr__" and co.co_filename.find("initpkg") !=-1:
stacklevel = level
break
level += 1
frame = frame.f_back
else:
stacklevel = 1
msg = "%s (since version %s)" %(msg, startversion) msg = "%s (since version %s)" %(msg, startversion)
warn(msg, stacklevel=stacklevel+1, function=function) warn(msg, stacklevel=stacklevel+1, function=function)

View File

@ -165,6 +165,8 @@ class LocalPath(FSBase):
try: try:
import hashlib as mod import hashlib as mod
except ImportError: except ImportError:
if hashtype == "sha1":
hashtype = "sha"
mod = __import__(hashtype) mod = __import__(hashtype)
hash = getattr(mod, hashtype)() hash = getattr(mod, hashtype)()
except (AttributeError, ImportError): except (AttributeError, ImportError):
@ -534,7 +536,7 @@ class LocalPath(FSBase):
to be executed. Note that this process is directly to be executed. Note that this process is directly
invoked and not through a system shell. invoked and not through a system shell.
""" """
from py.compat.subprocess import Popen, PIPE from subprocess import Popen, PIPE
argv = map(str, argv) argv = map(str, argv)
proc = Popen([str(self)] + list(argv), stdout=PIPE, stderr=PIPE) proc = Popen([str(self)] + list(argv), stdout=PIPE, stderr=PIPE)
stdout, stderr = proc.communicate() stdout, stderr = proc.communicate()

View File

@ -23,7 +23,7 @@ class Config(object):
""" test configuration object, provides access to config valueso, """ test configuration object, provides access to config valueso,
the pluginmanager and plugin api. the pluginmanager and plugin api.
""" """
Option = py.compat.optparse.Option # deprecated Option = py.std.optparse.Option
Error = Error Error = Error
basetemp = None basetemp = None
_sessionclass = None _sessionclass = None

View File

@ -14,7 +14,7 @@ for options. basic usage:
""" """
import py import py
from py.compat import optparse import optparse
class Parser: class Parser:
""" Parser for command line arguments. """ """ Parser for command line arguments. """
@ -76,11 +76,11 @@ class OptionGroup:
def addoption(self, *optnames, **attrs): def addoption(self, *optnames, **attrs):
""" add an option to this group. """ """ add an option to this group. """
option = py.compat.optparse.Option(*optnames, **attrs) option = optparse.Option(*optnames, **attrs)
self._addoption_instance(option, shortupper=False) self._addoption_instance(option, shortupper=False)
def _addoption(self, *optnames, **attrs): def _addoption(self, *optnames, **attrs):
option = py.compat.optparse.Option(*optnames, **attrs) option = optparse.Option(*optnames, **attrs)
self._addoption_instance(option, shortupper=True) self._addoption_instance(option, shortupper=True)
def _addoption_instance(self, option, shortupper=False): def _addoption_instance(self, option, shortupper=False):

View File

@ -15,6 +15,7 @@ as well.
import py import py
from py.__.code.code import TerminalRepr, ReprFileLocation from py.__.code.code import TerminalRepr, ReprFileLocation
import doctest
def pytest_addoption(parser): def pytest_addoption(parser):
group = parser.addgroup("doctest options") group = parser.addgroup("doctest options")
@ -46,7 +47,7 @@ class DoctestItem(py.test.collect.Item):
self.fspath = path self.fspath = path
def repr_failure(self, excinfo): def repr_failure(self, excinfo):
if excinfo.errisinstance(py.compat.doctest.DocTestFailure): if excinfo.errisinstance(doctest.DocTestFailure):
doctestfailure = excinfo.value doctestfailure = excinfo.value
example = doctestfailure.example example = doctestfailure.example
test = doctestfailure.test test = doctestfailure.test
@ -54,8 +55,8 @@ class DoctestItem(py.test.collect.Item):
lineno = test.lineno + example.lineno + 1 lineno = test.lineno + example.lineno + 1
message = excinfo.type.__name__ message = excinfo.type.__name__
reprlocation = ReprFileLocation(filename, lineno, message) reprlocation = ReprFileLocation(filename, lineno, message)
checker = py.compat.doctest.OutputChecker() checker = doctest.OutputChecker()
REPORT_UDIFF = py.compat.doctest.REPORT_UDIFF REPORT_UDIFF = doctest.REPORT_UDIFF
filelines = py.path.local(filename).readlines(cr=0) filelines = py.path.local(filename).readlines(cr=0)
i = max(test.lineno, max(0, lineno - 10)) # XXX? i = max(test.lineno, max(0, lineno - 10)) # XXX?
lines = [] lines = []
@ -65,7 +66,7 @@ class DoctestItem(py.test.collect.Item):
lines += checker.output_difference(example, lines += checker.output_difference(example,
doctestfailure.got, REPORT_UDIFF).split("\n") doctestfailure.got, REPORT_UDIFF).split("\n")
return ReprFailDoctest(reprlocation, lines) return ReprFailDoctest(reprlocation, lines)
elif excinfo.errisinstance(py.compat.doctest.UnexpectedException): elif excinfo.errisinstance(doctest.UnexpectedException):
excinfo = py.code.ExceptionInfo(excinfo.value.exc_info) excinfo = py.code.ExceptionInfo(excinfo.value.exc_info)
return super(DoctestItem, self).repr_failure(excinfo) return super(DoctestItem, self).repr_failure(excinfo)
else: else:
@ -74,14 +75,14 @@ class DoctestItem(py.test.collect.Item):
class DoctestTextfile(DoctestItem): class DoctestTextfile(DoctestItem):
def runtest(self): def runtest(self):
if not self._deprecated_testexecution(): if not self._deprecated_testexecution():
failed, tot = py.compat.doctest.testfile( failed, tot = doctest.testfile(
str(self.fspath), module_relative=False, str(self.fspath), module_relative=False,
raise_on_error=True, verbose=0) raise_on_error=True, verbose=0)
class DoctestModule(DoctestItem): class DoctestModule(DoctestItem):
def runtest(self): def runtest(self):
module = self.fspath.pyimport() module = self.fspath.pyimport()
failed, tot = py.compat.doctest.testmod( failed, tot = doctest.testmod(
module, raise_on_error=True, verbose=0) module, raise_on_error=True, verbose=0)

View File

@ -231,7 +231,7 @@ class DoctestText(py.test.collect.Item):
l.append(line) l.append(line)
docstring = "\n".join(l) docstring = "\n".join(l)
mod.__doc__ = docstring mod.__doc__ = docstring
failed, tot = py.compat.doctest.testmod(mod, verbose=1) failed, tot = py.std.doctest.testmod(mod, verbose=1)
if failed: if failed:
py.test.fail("doctest %s: %s failed out of %s" %( py.test.fail("doctest %s: %s failed out of %s" %(
self.fspath, failed, tot)) self.fspath, failed, tot))

View File

@ -30,7 +30,7 @@ class TestParser:
group = parseopt.OptionGroup("hello") group = parseopt.OptionGroup("hello")
group.addoption("--option1", action="store_true") group.addoption("--option1", action="store_true")
assert len(group.options) == 1 assert len(group.options) == 1
assert isinstance(group.options[0], py.compat.optparse.Option) assert isinstance(group.options[0], parseopt.optparse.Option)
def test_group_shortopt_lowercase(self): def test_group_shortopt_lowercase(self):
parser = parseopt.Parser() parser = parseopt.Parser()

View File

@ -1,8 +1,8 @@
import py,sys import py,sys
py.test.skip("implementation missing: recording")
class TestRecordingAccept: class TestRecordingAccept:
def test_recording_and_back(self, testdir): def test_recording_and_back(self, testdir):
py.test.skip("implementation missing: recording")
p = testdir.makepyfile(""" p = testdir.makepyfile("""
import py import py
def test_fail(): def test_fail():