deprecate py.compat.doctest|subprocess|textwrap|...
(and for now pass through Python stdlib provided modules). --HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									681d344eac
								
							
						
					
					
						commit
						d1932a30ed
					
				| 
						 | 
				
			
			@ -261,7 +261,7 @@ class PluginDoc(RestWriter):
 | 
			
		|||
            return
 | 
			
		||||
        self.h2("command line options")
 | 
			
		||||
        self.Print()
 | 
			
		||||
        formatter = py.compat.optparse.IndentedHelpFormatter()
 | 
			
		||||
        formatter = py.std.optparse.IndentedHelpFormatter()
 | 
			
		||||
        for opt in options:
 | 
			
		||||
            switches = formatter.format_option_strings(opt)
 | 
			
		||||
            self.Print("``%s``" % switches)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,8 @@ obtain system info from remote machine.
 | 
			
		|||
import py
 | 
			
		||||
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,
 | 
			
		||||
                  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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
Changes between 1.0.x and 'trunk'
 | 
			
		||||
=====================================
 | 
			
		||||
 | 
			
		||||
* deprecate py.compat.doctest|subprocess|textwrap|optparse
 | 
			
		||||
 | 
			
		||||
* deprecate py.magic.autopath, remove py/magic directory 
 | 
			
		||||
 | 
			
		||||
* move pytest assertion handling to py/code and a pytest_assertion
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								doc/misc.txt
								
								
								
								
							
							
						
						
									
										16
									
								
								doc/misc.txt
								
								
								
								
							| 
						 | 
				
			
			@ -93,26 +93,10 @@ Cross-Python Version compatibility helpers
 | 
			
		|||
 | 
			
		||||
sources: 
 | 
			
		||||
 | 
			
		||||
  * :source:`py/compat/`
 | 
			
		||||
  * :source:`py/builtin/`
 | 
			
		||||
 | 
			
		||||
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`
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,8 @@ obtain system info from remote machine.
 | 
			
		|||
import py
 | 
			
		||||
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,
 | 
			
		||||
                  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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -191,12 +191,12 @@ initpkg(__name__,
 | 
			
		|||
    'log.STDERR'             : ('./log/log.py', 'STDERR'),
 | 
			
		||||
    'log.Syslog'             : ('./log/log.py', 'Syslog'),
 | 
			
		||||
 | 
			
		||||
    # compatibility modules (taken from 2.4.4) 
 | 
			
		||||
    # compatibility modules (deprecated)
 | 
			
		||||
    'compat.__doc__'         : ('./compat/__init__.py', '__doc__'),
 | 
			
		||||
    'compat.doctest'         : ('./compat/doctest.py', '*'),
 | 
			
		||||
    'compat.optparse'        : ('./compat/optparse.py', '*'),
 | 
			
		||||
    'compat.textwrap'        : ('./compat/textwrap.py', '*'),
 | 
			
		||||
    'compat.subprocess'      : ('./compat/subprocess.py', '*'),
 | 
			
		||||
    'compat.doctest'         : ('./compat/dep_doctest.py', 'doctest'),
 | 
			
		||||
    'compat.optparse'        : ('./compat/dep_optparse.py', 'optparse'),
 | 
			
		||||
    'compat.textwrap'        : ('./compat/dep_textwrap.py', 'textwrap'),
 | 
			
		||||
    'compat.subprocess'      : ('./compat/dep_subprocess.py', 'subprocess'),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ a ".".
 | 
			
		|||
import py
 | 
			
		||||
 | 
			
		||||
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",
 | 
			
		||||
        help="remove files with the given comma-separated list of extensions"
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -191,7 +191,7 @@ def main():
 | 
			
		|||
    import py
 | 
			
		||||
 | 
			
		||||
    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):
 | 
			
		||||
        if hasattr(optparser, 'output'):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,10 +12,9 @@ current working directory). Distinguish between test files and normal ones and
 | 
			
		|||
report them separately.
 | 
			
		||||
"""
 | 
			
		||||
import py
 | 
			
		||||
from py.compat import optparse
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    parser = optparse.OptionParser(usage=__doc__)
 | 
			
		||||
    parser = py.std.optparse.OptionParser(usage=__doc__)
 | 
			
		||||
    (options, args) = parser.parse_args()
 | 
			
		||||
    countloc(args)
 | 
			
		||||
   
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,9 +16,7 @@ curdir = py.path.local()
 | 
			
		|||
def rec(p):
 | 
			
		||||
    return p.check(dotfile=0)
 | 
			
		||||
 | 
			
		||||
optparse = py.compat.optparse
 | 
			
		||||
 | 
			
		||||
parser = optparse.OptionParser(usage=__doc__)
 | 
			
		||||
parser = py.std.optparse.OptionParser(usage=__doc__)
 | 
			
		||||
parser.add_option("-i", "--ignore-case", action="store_true", dest="ignorecase",
 | 
			
		||||
                  help="ignore case distinctions")
 | 
			
		||||
parser.add_option("-C", "--context", action="store", type="int", dest="context",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,9 +22,8 @@ else:
 | 
			
		|||
    def log(msg):
 | 
			
		||||
        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,
 | 
			
		||||
                  help="generate pdf files")
 | 
			
		||||
parser.add_option("--stylesheet", dest="stylesheet", default=None,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,9 +41,8 @@ def svnwcrevert(path, root=None, precious=[]):
 | 
			
		|||
            svnwcrevert(p, root)
 | 
			
		||||
 | 
			
		||||
# 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",
 | 
			
		||||
                  action="append", dest="precious", default=[],
 | 
			
		||||
                  help="preserve files with this name")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 
 | 
			
		||||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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 
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
							
								
								
									
										2672
									
								
								py/compat/doctest.py
								
								
								
								
							
							
						
						
									
										2672
									
								
								py/compat/doctest.py
								
								
								
								
							
										
											
												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
											
										
									
								
							| 
						 | 
				
			
			@ -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
											
										
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			@ -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
											
										
									
								
							| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +1,8 @@
 | 
			
		|||
 | 
			
		||||
import os, inspect, socket
 | 
			
		||||
import sys
 | 
			
		||||
from py.magic import autopath ; mypath = autopath()
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from subprocess import Popen, PIPE
 | 
			
		||||
except ImportError:
 | 
			
		||||
    from py.__.compat.subprocess import Popen, PIPE
 | 
			
		||||
import py
 | 
			
		||||
from subprocess import Popen, PIPE
 | 
			
		||||
 | 
			
		||||
import py
 | 
			
		||||
if sys.platform == "win32":
 | 
			
		||||
| 
						 | 
				
			
			@ -128,8 +124,9 @@ class SocketGateway(InstallableGateway):
 | 
			
		|||
            host, port = ('', 0)  # XXX works on all platforms? 
 | 
			
		||||
        else:   
 | 
			
		||||
            host, port = hostport 
 | 
			
		||||
        mydir = py.path.local(__file__).dirpath()
 | 
			
		||||
        socketserverbootstrap = py.code.Source(
 | 
			
		||||
            mypath.dirpath('script', 'socketserver.py').read('rU'), """
 | 
			
		||||
            mydir.join('script', 'socketserver.py').read('rU'), """
 | 
			
		||||
            import socket
 | 
			
		||||
            sock = bind_and_listen((%r, %r)) 
 | 
			
		||||
            port = sock.getsockname()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,32 @@ def test_stacklevel():
 | 
			
		|||
    warning = str(err)
 | 
			
		||||
    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():
 | 
			
		||||
    capture = py.io.StdCapture()
 | 
			
		||||
    py.log._apiwarn("x.y.z", "something", function=test_function)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,18 @@ class Warning(py.std.exceptions.DeprecationWarning):
 | 
			
		|||
def _apiwarn(startversion, msg, stacklevel=1, function=None):
 | 
			
		||||
    # below is mostly COPIED from python2.4/warnings.py's def warn()
 | 
			
		||||
    # 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)
 | 
			
		||||
    warn(msg, stacklevel=stacklevel+1, function=function)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -165,6 +165,8 @@ class LocalPath(FSBase):
 | 
			
		|||
            try:
 | 
			
		||||
                import hashlib as mod
 | 
			
		||||
            except ImportError:
 | 
			
		||||
                if hashtype == "sha1":
 | 
			
		||||
                    hashtype = "sha"
 | 
			
		||||
                mod = __import__(hashtype)
 | 
			
		||||
            hash = getattr(mod, hashtype)()
 | 
			
		||||
        except (AttributeError, ImportError):
 | 
			
		||||
| 
						 | 
				
			
			@ -534,7 +536,7 @@ class LocalPath(FSBase):
 | 
			
		|||
            to be executed. Note that this process is directly
 | 
			
		||||
            invoked and not through a system shell.
 | 
			
		||||
        """
 | 
			
		||||
        from py.compat.subprocess import Popen, PIPE
 | 
			
		||||
        from subprocess import Popen, PIPE
 | 
			
		||||
        argv = map(str, argv)
 | 
			
		||||
        proc = Popen([str(self)] + list(argv), stdout=PIPE, stderr=PIPE)
 | 
			
		||||
        stdout, stderr = proc.communicate()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ class Config(object):
 | 
			
		|||
    """ test configuration object, provides access to config valueso, 
 | 
			
		||||
        the pluginmanager and plugin api. 
 | 
			
		||||
    """
 | 
			
		||||
    Option = py.compat.optparse.Option # deprecated
 | 
			
		||||
    Option = py.std.optparse.Option 
 | 
			
		||||
    Error = Error
 | 
			
		||||
    basetemp = None
 | 
			
		||||
    _sessionclass = None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ for options.  basic usage:
 | 
			
		|||
    
 | 
			
		||||
"""
 | 
			
		||||
import py
 | 
			
		||||
from py.compat import optparse
 | 
			
		||||
import optparse 
 | 
			
		||||
 | 
			
		||||
class Parser:
 | 
			
		||||
    """ Parser for command line arguments. """ 
 | 
			
		||||
| 
						 | 
				
			
			@ -76,11 +76,11 @@ class OptionGroup:
 | 
			
		|||
 | 
			
		||||
    def addoption(self, *optnames, **attrs):
 | 
			
		||||
        """ add an option to this group. """
 | 
			
		||||
        option = py.compat.optparse.Option(*optnames, **attrs)
 | 
			
		||||
        option = optparse.Option(*optnames, **attrs)
 | 
			
		||||
        self._addoption_instance(option, shortupper=False)
 | 
			
		||||
 | 
			
		||||
    def _addoption(self, *optnames, **attrs):
 | 
			
		||||
        option = py.compat.optparse.Option(*optnames, **attrs)
 | 
			
		||||
        option = optparse.Option(*optnames, **attrs)
 | 
			
		||||
        self._addoption_instance(option, shortupper=True)
 | 
			
		||||
 | 
			
		||||
    def _addoption_instance(self, option, shortupper=False):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ as well.
 | 
			
		|||
 | 
			
		||||
import py
 | 
			
		||||
from py.__.code.code import TerminalRepr, ReprFileLocation
 | 
			
		||||
import doctest
 | 
			
		||||
 | 
			
		||||
def pytest_addoption(parser):
 | 
			
		||||
    group = parser.addgroup("doctest options")
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +47,7 @@ class DoctestItem(py.test.collect.Item):
 | 
			
		|||
        self.fspath = path 
 | 
			
		||||
 | 
			
		||||
    def repr_failure(self, excinfo):
 | 
			
		||||
        if excinfo.errisinstance(py.compat.doctest.DocTestFailure):
 | 
			
		||||
        if excinfo.errisinstance(doctest.DocTestFailure):
 | 
			
		||||
            doctestfailure = excinfo.value
 | 
			
		||||
            example = doctestfailure.example
 | 
			
		||||
            test = doctestfailure.test
 | 
			
		||||
| 
						 | 
				
			
			@ -54,8 +55,8 @@ class DoctestItem(py.test.collect.Item):
 | 
			
		|||
            lineno = test.lineno + example.lineno + 1
 | 
			
		||||
            message = excinfo.type.__name__
 | 
			
		||||
            reprlocation = ReprFileLocation(filename, lineno, message)
 | 
			
		||||
            checker = py.compat.doctest.OutputChecker() 
 | 
			
		||||
            REPORT_UDIFF = py.compat.doctest.REPORT_UDIFF
 | 
			
		||||
            checker = doctest.OutputChecker() 
 | 
			
		||||
            REPORT_UDIFF = doctest.REPORT_UDIFF
 | 
			
		||||
            filelines = py.path.local(filename).readlines(cr=0)
 | 
			
		||||
            i = max(test.lineno, max(0, lineno - 10)) # XXX? 
 | 
			
		||||
            lines = []
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +66,7 @@ class DoctestItem(py.test.collect.Item):
 | 
			
		|||
            lines += checker.output_difference(example, 
 | 
			
		||||
                    doctestfailure.got, REPORT_UDIFF).split("\n")
 | 
			
		||||
            return ReprFailDoctest(reprlocation, lines)
 | 
			
		||||
        elif excinfo.errisinstance(py.compat.doctest.UnexpectedException):
 | 
			
		||||
        elif excinfo.errisinstance(doctest.UnexpectedException):
 | 
			
		||||
            excinfo = py.code.ExceptionInfo(excinfo.value.exc_info)
 | 
			
		||||
            return super(DoctestItem, self).repr_failure(excinfo)
 | 
			
		||||
        else: 
 | 
			
		||||
| 
						 | 
				
			
			@ -74,14 +75,14 @@ class DoctestItem(py.test.collect.Item):
 | 
			
		|||
class DoctestTextfile(DoctestItem):
 | 
			
		||||
    def runtest(self):
 | 
			
		||||
        if not self._deprecated_testexecution():
 | 
			
		||||
            failed, tot = py.compat.doctest.testfile(
 | 
			
		||||
            failed, tot = doctest.testfile(
 | 
			
		||||
                str(self.fspath), module_relative=False, 
 | 
			
		||||
                raise_on_error=True, verbose=0)
 | 
			
		||||
 | 
			
		||||
class DoctestModule(DoctestItem):
 | 
			
		||||
    def runtest(self):
 | 
			
		||||
        module = self.fspath.pyimport()
 | 
			
		||||
        failed, tot = py.compat.doctest.testmod(
 | 
			
		||||
        failed, tot = doctest.testmod(
 | 
			
		||||
            module, raise_on_error=True, verbose=0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -231,7 +231,7 @@ class DoctestText(py.test.collect.Item):
 | 
			
		|||
                l.append(line)
 | 
			
		||||
        docstring = "\n".join(l)
 | 
			
		||||
        mod.__doc__ = docstring 
 | 
			
		||||
        failed, tot = py.compat.doctest.testmod(mod, verbose=1)
 | 
			
		||||
        failed, tot = py.std.doctest.testmod(mod, verbose=1)
 | 
			
		||||
        if failed: 
 | 
			
		||||
            py.test.fail("doctest %s: %s failed out of %s" %(
 | 
			
		||||
                         self.fspath, failed, tot))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ class TestParser:
 | 
			
		|||
        group = parseopt.OptionGroup("hello")
 | 
			
		||||
        group.addoption("--option1", action="store_true")
 | 
			
		||||
        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):
 | 
			
		||||
        parser = parseopt.Parser()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
import py,sys
 | 
			
		||||
py.test.skip("implementation missing: recording")
 | 
			
		||||
 | 
			
		||||
class TestRecordingAccept:
 | 
			
		||||
    def test_recording_and_back(self, testdir):
 | 
			
		||||
        py.test.skip("implementation missing: recording")
 | 
			
		||||
        p = testdir.makepyfile("""
 | 
			
		||||
            import py
 | 
			
		||||
            def test_fail():
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue