r47361 - merge forward

hawkowl-TA+aISz0psMTMxyoc4vAAJOcrHinNvQL0E9HWUfgJXw@public.gmane.org Sun, 8 May 2016 08:46:41 -0600 (MDT)
Newsgroups gmane.comp.python.twisted.commits
Message-ID <[email protected]>
Author: hawkowl
Date: Sun May  8 08:46:35 2016
New Revision: 47361

Added:
   branches/cov-subprocess-8266-3/admin/_copy.py
   branches/cov-subprocess-8266-3/admin/zz_coverage.pth
   branches/cov-subprocess-8266-3/twisted/test/process_getargv.py
   branches/cov-subprocess-8266-3/twisted/test/process_getenv.py
   branches/cov-subprocess-8266-3/twisted/topfiles/8266.misc
Removed:
   branches/cov-subprocess-8266-3/twisted/test/_preamble.py
Modified:
   branches/cov-subprocess-8266-3/.coveragerc
   branches/cov-subprocess-8266-3/.gitignore
   branches/cov-subprocess-8266-3/tox.ini
   branches/cov-subprocess-8266-3/twisted/internet/test/test_process.py
   branches/cov-subprocess-8266-3/twisted/python/dist3.py
   branches/cov-subprocess-8266-3/twisted/python/test/test_dist3.py
   branches/cov-subprocess-8266-3/twisted/test/process_fds.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_consumer.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_halfclose.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_hostpeer.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_lastwrite.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_loseconn.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_producer.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_write.py
   branches/cov-subprocess-8266-3/twisted/test/stdio_test_writeseq.py
   branches/cov-subprocess-8266-3/twisted/test/test_process.py
   branches/cov-subprocess-8266-3/twisted/test/test_stdio.py

Log:
merge forward

Modified: branches/cov-subprocess-8266-3/.coveragerc
==============================================================================
--- branches/cov-subprocess-8266-3/.coveragerc	(original)
+++ branches/cov-subprocess-8266-3/.coveragerc	Sun May  8 08:46:35 2016
@@ -1,6 +1,13 @@
 [run]
-source = twisted
 branch = True
+parallel = True
+source = twisted
+
+[paths]
+source=
+   twisted
+   build/*/lib/python*/site-packages/twisted
+   build/pypy*/site-packages/twisted
 
 [report]
 precision = 2

Modified: branches/cov-subprocess-8266-3/.gitignore
==============================================================================
--- branches/cov-subprocess-8266-3/.gitignore	(original)
+++ branches/cov-subprocess-8266-3/.gitignore	Sun May  8 08:46:35 2016
@@ -10,7 +10,7 @@
 dist/
 venv/
 htmlcov/
-.coverage
+.coverage*
 *~
 *.lock
 apidocs/

Modified: branches/cov-subprocess-8266-3/tox.ini
==============================================================================
--- branches/cov-subprocess-8266-3/tox.ini	(original)
+++ branches/cov-subprocess-8266-3/tox.ini	Sun May  8 08:46:35 2016
@@ -36,6 +36,8 @@
      ; Documentation
      apidocs: pydoctor
      narrativedocs: sphinx
+setenv =
+   COVERAGE_PROCESS_START = {toxinidir}/.coveragerc
 
 commands =
     {tests,nomodules}: {envbindir}/trial --reactor={env:TWISTED_REACTOR:default} {posargs:twisted}
@@ -46,9 +48,11 @@
     apidocs: {toxinidir}/bin/admin/build-apidocs {toxinidir} apidocs
     narrativedocs: sphinx-build -aW -b html -d {toxinidir}/docs/_build {toxinidir}/docs {toxinidir}/docs/_build/
 
+    coverage: python {toxinidir}/admin/_copy.py {toxinidir}/admin/zz_coverage.pth {envsitepackagesdir}/zz_coverage.pth
     coverage: coverage erase
-    coverage: coverage run --rcfile={toxinidir}/.coveragerc {envbindir}/trial --reactor={env:TWISTED_REACTOR:default} {posargs:twisted}
-    coverage: coverage report --rcfile={toxinidir}/.coveragerc
+    coverage: coverage run -p --rcfile={toxinidir}/.coveragerc {envbindir}/trial --reactor={env:TWISTED_REACTOR:default} {posargs:twisted}
+    coverage: python {toxinidir}/admin/_copy.py "_trial_temp/.coverage*" {toxinidir}
+    coverage: python {toxinidir}/admin/_copy.py ".coverage*" {toxinidir}
 
 [testenv:twistedchecker]
 basepython=python2.7

Modified: branches/cov-subprocess-8266-3/twisted/internet/test/test_process.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/internet/test/test_process.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/internet/test/test_process.py	Sun May  8 08:46:35 2016
@@ -3,6 +3,9 @@
 
 """
 Tests for implementations of L{IReactorProcess}.
+
+@var properEnv: A copy of L{os.environ} which has L{bytes} keys/values on POSIX
+    platforms and native L{str} keys/values on Windows.
 """
 
 from __future__ import division, absolute_import, print_function
@@ -20,7 +23,8 @@
 from twisted.python.log import msg, err
 from twisted.python.runtime import platform
 from twisted.python.filepath import FilePath, _asFilesystemBytes
-from twisted.python.compat import networkString, _PY3, xrange, items
+from twisted.python.compat import (networkString, _PY3, xrange, items,
+                                   bytesEnviron)
 from twisted.internet import utils
 from twisted.internet.interfaces import IReactorProcess, IProcessTransport
 from twisted.internet.defer import Deferred, succeed
@@ -37,12 +41,19 @@
     resource = None
     process = None
     _uidgidSkip = "Cannot change UID/GID on Windows"
+
+    properEnv = dict(os.environ)
+    properEnv["PYTHONPATH"] = os.pathsep.join(sys.path)
 else:
     import resource
     from twisted.internet import process
     if os.getuid() != 0:
         _uidgidSkip = "Cannot change UID/GID except as root"
 
+    properEnv = bytesEnviron()
+    properEnv[b"PYTHONPATH"] = os.pathsep.join(sys.path).encode(
+        sys.getfilesystemencoding())
+
 
 
 def onlyOnPOSIX(testMethod):
@@ -597,7 +608,7 @@
     """
     usePTY = False
 
-    keepStdioOpenProgram = FilePath(__file__).sibling(b'process_helper.py').path
+    keepStdioOpenProgram = b'twisted.internet.test.process_helper'
     if platform.isWindows():
         keepStdioOpenArg = b"windows"
     else:
@@ -622,12 +633,12 @@
             def childConnectionLost(self, childFD):
                 lost[childFD].callback(None)
 
-        target = FilePath(__file__).sibling(b"process_loseconnection.py")
+        target = b"twisted.internet.test.process_loseconnection"
 
         reactor = self.buildReactor()
         reactor.callWhenRunning(
             reactor.spawnProcess, Closer(), pyExe,
-            [pyExe, target.path], usePTY=self.usePTY)
+            [pyExe, b"-m", target], env=properEnv, usePTY=self.usePTY)
 
         def cbConnected(transport):
             transport.write(b'2\n')
@@ -680,9 +691,9 @@
         reactor = self.buildReactor()
         reactor.callWhenRunning(
             reactor.spawnProcess, Ender(), pyExe,
-            [pyExe, self.keepStdioOpenProgram, b"child",
+            [pyExe, b"-m", self.keepStdioOpenProgram, b"child",
              self.keepStdioOpenArg],
-            usePTY=self.usePTY)
+            env=properEnv, usePTY=self.usePTY)
 
         def cbEnded(args):
             failure, = args
@@ -728,9 +739,9 @@
         reactor = self.buildReactor()
         reactor.callWhenRunning(
             reactor.spawnProcess, Waiter(), pyExe,
-            [pyExe, self.keepStdioOpenProgram, b"child",
+            [pyExe, b"-u", b"-m", self.keepStdioOpenProgram, b"child",
              self.keepStdioOpenArg],
-            usePTY=self.usePTY)
+            env=properEnv, usePTY=self.usePTY)
 
         def cbExited(args):
             failure, = args
@@ -804,7 +815,7 @@
         Arguments given to spawnProcess are passed to the child process as
         originally intended.
         """
-        us = FilePath(__file__).sibling(b"process_cli.py")
+        us = b"twisted.internet.test.process_cli"
 
         args = [b'hello', b'"', b' \t|<>^&', br'"\\"hello\\"', br'"foo\ bar baz\""']
         # Ensure that all non-NUL characters can be passed too.
@@ -829,7 +840,8 @@
         def spawnChild():
             d = succeed(None)
             d.addCallback(lambda dummy: utils.getProcessOutputAndValue(
-                pyExe, [us.path] + args, reactor=reactor))
+                pyExe, [b"-m", us] + args, env=properEnv,
+                reactor=reactor))
             d.addCallback(processFinished)
             d.addBoth(shutdown)
 

Modified: branches/cov-subprocess-8266-3/twisted/python/dist3.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/python/dist3.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/python/dist3.py	Sun May  8 08:46:35 2016
@@ -458,13 +458,14 @@
     "twisted.positioning.test.receiver",
     "twisted.python.test.pullpipe",
     "twisted.python.test.pullpipe",
-    "twisted.test._preamble",
     "twisted.test.plugin_basic",
     "twisted.test.plugin_extra1",
     "twisted.test.plugin_extra2",
     "twisted.test.process_cmdline",
     "twisted.test.process_echoer",
     "twisted.test.process_fds",
+    "twisted.test.process_getargv",
+    "twisted.test.process_getenv",
     "twisted.test.process_linger",
     "twisted.test.process_reader",
     "twisted.test.process_signal",

Modified: branches/cov-subprocess-8266-3/twisted/python/test/test_dist3.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/python/test/test_dist3.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/python/test/test_dist3.py	Sun May  8 08:46:35 2016
@@ -49,4 +49,5 @@
         root = os.path.dirname(os.path.dirname(twisted.__file__))
         for file in testDataFiles:
             self.assertTrue(os.path.exists(
-                os.path.join(root, os.path.sep.join(file.split(".")) + ".py")))
+                os.path.join(root, os.path.sep.join(file.split(".")) + ".py")),
+                            "Data file {0} does not exist".format(file))

Modified: branches/cov-subprocess-8266-3/twisted/test/process_fds.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/process_fds.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/process_fds.py	Sun May  8 08:46:35 2016
@@ -7,35 +7,37 @@
 
 import os, sys
 
-debug = 0
+if __name__ == "__main__":
 
-if debug: stderr = os.fdopen(2, "w")
+    debug = 0
 
-if debug: print("this is stderr", file=stderr)
+    if debug: stderr = os.fdopen(2, "w")
 
-abcd = os.read(0, 4)
-if debug: print("read(0):", abcd, file=stderr)
-if abcd != b"abcd":
-    sys.exit(1)
+    if debug: print("this is stderr", file=stderr)
 
-if debug: print("os.write(1, righto)", file=stderr)
-os.write(1, b"righto")
+    abcd = os.read(0, 4)
+    if debug: print("read(0):", abcd, file=stderr)
+    if abcd != b"abcd":
+        sys.exit(1)
 
-efgh = os.read(3, 4)
-if debug: print("read(3):", file=stderr)
-if efgh != b"efgh":
-    sys.exit(2)
+    if debug: print("os.write(1, righto)", file=stderr)
+    os.write(1, b"righto")
 
-if debug: print("os.close(4)", file=stderr)
-os.close(4)
+    efgh = os.read(3, 4)
+    if debug: print("read(3):", file=stderr)
+    if efgh != b"efgh":
+        sys.exit(2)
 
-eof = os.read(5, 4)
-if debug: print("read(5):", eof, file=stderr)
-if eof != b"":
-    sys.exit(3)
+    if debug: print("os.close(4)", file=stderr)
+    os.close(4)
 
-if debug: print("os.write(1, closed)", file=stderr)
-os.write(1, b"closed")
+    eof = os.read(5, 4)
+    if debug: print("read(5):", eof, file=stderr)
+    if eof != b"":
+        sys.exit(3)
 
-if debug: print("sys.exit(0)", file=stderr)
-sys.exit(0)
+    if debug: print("os.write(1, closed)", file=stderr)
+    os.write(1, b"closed")
+
+    if debug: print("sys.exit(0)", file=stderr)
+    sys.exit(0)

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_consumer.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_consumer.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_consumer.py	Sun May  8 08:46:35 2016
@@ -10,7 +10,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from twisted.python import log, reflect

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_halfclose.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_halfclose.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_halfclose.py	Sun May  8 08:46:35 2016
@@ -11,7 +11,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from zope.interface import implementer

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_hostpeer.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_hostpeer.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_hostpeer.py	Sun May  8 08:46:35 2016
@@ -10,7 +10,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from twisted.internet import stdio, protocol

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_lastwrite.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_lastwrite.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_lastwrite.py	Sun May  8 08:46:35 2016
@@ -11,7 +11,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from twisted.internet.protocol import Protocol

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_loseconn.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_loseconn.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_loseconn.py	Sun May  8 08:46:35 2016
@@ -10,7 +10,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from twisted.internet.error import ConnectionDone

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_producer.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_producer.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_producer.py	Sun May  8 08:46:35 2016
@@ -10,7 +10,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from twisted.internet import stdio, protocol

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_write.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_write.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_write.py	Sun May  8 08:46:35 2016
@@ -10,7 +10,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from twisted.internet import stdio, protocol

Modified: branches/cov-subprocess-8266-3/twisted/test/stdio_test_writeseq.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/stdio_test_writeseq.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/stdio_test_writeseq.py	Sun May  8 08:46:35 2016
@@ -10,7 +10,6 @@
 
 from __future__ import absolute_import, division
 
-__import__('_preamble')
 import sys
 
 from twisted.internet import stdio, protocol

Modified: branches/cov-subprocess-8266-3/twisted/test/test_process.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/test_process.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/test_process.py	Sun May  8 08:46:35 2016
@@ -12,6 +12,9 @@
     cause spurious failures if this value is pushed too high.  U{Please see
     this ticket for a discussion of how we arrived at its current value.
     <http://twistedmatrix.com/trac/ticket/3404>}
+
+@var properEnv: A copy of L{os.environ} which has L{bytes} keys/values on POSIX
+    platforms and native L{str} keys/values on Windows.
 """
 
 from __future__ import division, absolute_import
@@ -41,13 +44,20 @@
 from twisted.internet import reactor, protocol, error, interfaces, defer
 from twisted.trial import unittest
 from twisted.python import util, runtime, procutils
-from twisted.python.compat import _PY3, networkString, xrange
-from twisted.python.filepath import FilePath, _asFilesystemBytes
+from twisted.python.compat import _PY3, networkString, xrange, bytesEnviron
+from twisted.python.filepath import FilePath
 
 
 # Get the current Python executable as a bytestring.
 pyExe = FilePath(sys.executable)._asBytesPath()
 CONCURRENT_PROCESS_TEST_COUNT = 25
+if not runtime.platform.isWindows():
+    properEnv = bytesEnviron()
+    properEnv[b"PYTHONPATH"] = os.pathsep.join(sys.path).encode(
+        sys.getfilesystemencoding())
+else:
+    properEnv = dict(os.environ)
+    properEnv["PYTHONPATH"] = os.pathsep.join(sys.path)
 
 
 class StubProcessProtocol(protocol.ProcessProtocol):
@@ -364,10 +374,9 @@
     """
     Helper class for launching a Python process and getting a result from it.
 
-    @ivar program: A string giving a Python program for the child process to
-    run.
+    @ivar programName: The name of the program to run.
     """
-    program = None
+    programName = None
 
     @classmethod
     def run(cls, reactor, argv, env):
@@ -381,7 +390,8 @@
         """
         self = cls()
         reactor.spawnProcess(
-            self, pyExe, [pyExe, b"-c", self.program] + argv, env=env)
+            self, pyExe, [pyExe, b"-u", b"-m", self.programName] + argv,
+            env=env)
         return self
 
 
@@ -434,16 +444,12 @@
 
 
 
-
 class GetArgumentVector(UtilityProcessProtocol):
     """
     Protocol which will read a serialized argv from a process and
     expose it to interested parties.
     """
-    program = networkString(
-        "from sys import stdout, argv\n"
-        "stdout.write(chr(0).join(argv))\n"
-        "stdout.flush()\n")
+    programName = b"twisted.test.process_getargv"
 
     def parseChunks(self, chunks):
         """
@@ -461,12 +467,7 @@
     Protocol which will read a serialized environment dict from a process
     and expose it to interested parties.
     """
-    program = networkString(
-        "from sys import stdout\n"
-        "from os import environ\n"
-        "items = environ.items()\n"
-        "stdout.write(chr(0).join([k + chr(0) + v for k, v in items]))\n"
-        "stdout.flush()\n")
+    programName = b"twisted.test.process_getenv"
 
     def parseChunks(self, chunks):
         """
@@ -493,17 +494,20 @@
 
 
 class ProcessTests(unittest.TestCase):
-    """Test running a process."""
-
+    """
+    Test running a process.
+    """
     usePTY = False
 
-    def testStdio(self):
-        """twisted.internet.stdio test."""
-        scriptPath = FilePath(__file__).sibling(b"process_twisted.py").path
+    def test_stdio(self):
+        """
+        L{twisted.internet.stdio} test.
+        """
+        scriptPath = b"twisted.test.process_twisted"
         p = Accumulator()
         d = p.endedDeferred = defer.Deferred()
-        env = {b"PYTHONPATH": _asFilesystemBytes(os.pathsep.join(sys.path))}
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=env,
+        reactor.spawnProcess(p, pyExe, [pyExe, b'-u', b"-m", scriptPath],
+                             env=properEnv,
                              path=None, usePTY=self.usePTY)
         p.transport.write(b"hello, world")
         p.transport.write(b"abc")
@@ -526,9 +530,10 @@
         """
         finished = defer.Deferred()
         p = TrivialProcessProtocol(finished)
-        scriptPath = FilePath(__file__).sibling(b"process_echoer.py").path
+        scriptPath = b"twisted.test.process_echoer"
         procTrans = reactor.spawnProcess(p, pyExe,
-                                    [pyExe, scriptPath], env=None)
+                                         [pyExe, b'-u', b"-m", scriptPath],
+                                         env=properEnv)
         self.assertTrue(procTrans.pid)
 
         def afterProcessEnd(ignored):
@@ -543,11 +548,12 @@
         Test running a process: check its output, it exitCode, some property of
         signalProcess.
         """
-        scriptPath = FilePath(__file__).sibling(b"process_tester.py").path
+        scriptPath = b"twisted.test.process_tester"
         d = defer.Deferred()
         p = TestProcessProtocol()
         p.deferred = d
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=None)
+        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", b"-m", scriptPath],
+                             env=properEnv)
         def check(ignored):
             self.assertEqual(p.stages, [1, 2, 3, 4, 5])
             f = p.reason
@@ -566,25 +572,28 @@
         d.addCallback(check)
         return d
 
-    def testManyProcesses(self):
+
+    def test_manyProcesses(self):
 
         def _check(results, protocols):
             for p in protocols:
-                self.assertEqual(p.stages, [1, 2, 3, 4, 5], "[%d] stages = %s" % (id(p.transport), str(p.stages)))
+                self.assertEqual(p.stages, [1, 2, 3, 4, 5],
+                                 "[%d] stages = %s" % (id(p.transport),
+                                                       str(p.stages)))
                 # test status code
                 f = p.reason
                 f.trap(error.ProcessTerminated)
                 self.assertEqual(f.value.exitCode, 23)
 
-        scriptPath = FilePath(__file__).sibling(b"process_tester.py").path
-        args = [pyExe, b"-u", scriptPath]
+        scriptPath = b"twisted.test.process_tester"
+        args = [pyExe, b'-u', b"-m", scriptPath]
         protocols = []
         deferreds = []
 
         for i in xrange(CONCURRENT_PROCESS_TEST_COUNT):
             p = TestManyProcessProtocol()
             protocols.append(p)
-            reactor.spawnProcess(p, pyExe, args, env=None)
+            reactor.spawnProcess(p, pyExe, args, env=properEnv)
             deferreds.append(p.deferred)
 
         deferredList = defer.DeferredList(deferreds, consumeErrors=True)
@@ -601,8 +610,9 @@
         finished = defer.Deferred()
         p = EchoProtocol(finished)
 
-        scriptPath = FilePath(__file__).sibling(b"process_echoer.py").path
-        reactor.spawnProcess(p, pyExe, [pyExe, scriptPath], env=None)
+        scriptPath = b"twisted.test.process_echoer"
+        reactor.spawnProcess(p, pyExe, [pyExe, b'-u', b"-m", scriptPath],
+                             env=properEnv)
 
         def asserts(ignored):
             self.assertFalse(p.failure, p.failure)
@@ -616,14 +626,15 @@
         return finished.addCallback(asserts).addErrback(takedownProcess)
 
 
-    def testCommandLine(self):
+    def test_commandLine(self):
         args = [br'a\"b ', br'a\b ', br' a\\"b', br' a\\b', br'"foo bar" "',
                 b'\tab', b'"\\', b'a"b', b"a'b"]
-        scriptPath = FilePath(__file__).sibling(b"process_cmdline.py").path
+        scriptPath = b"twisted.test.process_cmdline"
         p = Accumulator()
         d = p.endedDeferred = defer.Deferred()
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath] + args,
-                             env=None, path=None)
+        reactor.spawnProcess(p, pyExe,
+                             [pyExe, b"-u", b"-m", scriptPath] + args,
+                             env=properEnv, path=None)
 
         def processEnded(ign):
             self.assertEqual(p.errF.getvalue(), b"")
@@ -688,7 +699,8 @@
     okayUnicode = u"UNICODE"
     encodedValue = b"UNICODE"
 
-    def _deprecatedUnicodeSupportTest(self, processProtocolClass, argv=[], env={}):
+    def _deprecatedUnicodeSupportTest(self, processProtocolClass, argv=[],
+                                      env={}):
         """
         Check that a deprecation warning is emitted when passing unicode to
         spawnProcess for an argv value or an environment key or value.
@@ -713,7 +725,10 @@
             self.okayUnicode.encode(sys.getdefaultencoding()),
             self.encodedValue)
 
-        d = processProtocolClass.run(reactor, argv, env)
+        pEnv = properEnv.copy()
+        pEnv.update(env)
+
+        d = processProtocolClass.run(reactor, argv, pEnv)
 
         warnings = self.flushWarnings([UtilityProcessProtocol.run])
 
@@ -736,9 +751,10 @@
         if it can be encoded with the default system encoding, but that a
         deprecation warning is emitted.
         """
-        d = self._deprecatedUnicodeSupportTest(GetArgumentVector, argv=[self.okayUnicode])
+        d = self._deprecatedUnicodeSupportTest(GetArgumentVector,
+                                               argv=[self.okayUnicode])
         def gotArgVector(argv):
-            self.assertEqual(argv, [b'-c', self.encodedValue])
+            self.assertEqual(argv[1], self.encodedValue)
         d.addCallback(gotArgVector)
         return d
 
@@ -795,13 +811,13 @@
         self.verbose = 0
 
     def createProcesses(self, usePTY=0):
-        scriptPath = FilePath(__file__).sibling(b"process_reader.py").path
+        scriptPath = b"twisted.test.process_reader"
         for num in (0,1):
             self.pp[num] = TwoProcessProtocol()
             self.pp[num].num = num
             p = reactor.spawnProcess(self.pp[num], pyExe,
-                                     [pyExe, b"-u", scriptPath],
-                                     env=None, usePTY=usePTY)
+                                     [pyExe, b"-u", b"-m", scriptPath],
+                                     env=properEnv, usePTY=usePTY)
             self.processes[num] = p
 
     def close(self, num):
@@ -815,7 +831,7 @@
     def _onClose(self):
         return defer.gatherResults([ p.deferred for p in self.pp ])
 
-    def testClose(self):
+    def test_close(self):
         if self.verbose: print("starting processes")
         self.createProcesses()
         reactor.callLater(1, self.close, 0)
@@ -845,21 +861,21 @@
         os.kill(p.pid, signal.SIGTERM)
         if self.verbose: print(self.pp[0].finished, self.pp[1].finished)
 
-    def testKill(self):
+    def test_kill(self):
         if self.verbose: print("starting processes")
         self.createProcesses(usePTY=0)
         reactor.callLater(1, self.kill, 0)
         reactor.callLater(2, self.kill, 1)
         return self._onClose()
 
-    def testClosePty(self):
+    def test_closePty(self):
         if self.verbose: print("starting processes")
         self.createProcesses(usePTY=1)
         reactor.callLater(1, self.close, 0)
         reactor.callLater(2, self.close, 1)
         return self._onClose()
 
-    def testKillPty(self):
+    def test_killPty(self):
         if self.verbose: print("starting processes")
         self.createProcesses(usePTY=1)
         reactor.callLater(1, self.kill, 0)
@@ -949,26 +965,26 @@
 
 class FDTests(unittest.TestCase):
 
-    def testFD(self):
-        scriptPath = FilePath(__file__).sibling(b"process_fds.py").path
+    def test_FD(self):
+        scriptPath = b"twisted.test.process_fds"
         d = defer.Deferred()
         p = FDChecker(d)
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=None,
-                             path=None,
+        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", b"-m", scriptPath],
+                             env=properEnv,
                              childFDs={0:"w", 1:"r", 2:2,
                                        3:"w", 4:"r", 5:"w"})
         d.addCallback(lambda x : self.assertFalse(p.failed, p.failed))
         return d
 
-    def testLinger(self):
+    def test_linger(self):
         # See what happens when all the pipes close before the process
         # actually stops. This test *requires* SIGCHLD catching to work,
         # as there is no other way to find out the process is done.
-        scriptPath = FilePath(__file__).sibling(b"process_linger.py").path
+        scriptPath = b"twisted.test.process_linger"
         p = Accumulator()
         d = p.endedDeferred = defer.Deferred()
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=None,
-                             path=None,
+        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", b"-m", scriptPath],
+                             env=properEnv,
                              childFDs={1:"r", 2:2},
                              )
         def processEnded(ign):
@@ -1030,7 +1046,7 @@
                 "%s not found in /bin or /usr/bin" % (commandName,))
 
 
-    def testNormalTermination(self):
+    def test_normalTermination(self):
         cmd = self.getCommand('true')
 
         d = defer.Deferred()
@@ -1066,11 +1082,11 @@
 
 
     def _testSignal(self, sig):
-        scriptPath = FilePath(__file__).sibling(b"process_signal.py").path
+        scriptPath = b"twisted.test.process_signal"
         d = defer.Deferred()
         p = SignalProtocol(d, sig)
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=None,
-                             usePTY=self.usePTY)
+        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", "-m", scriptPath],
+                             env=properEnv, usePTY=self.usePTY)
         return d
 
 
@@ -1181,7 +1197,7 @@
         ended = defer.Deferred()
 
         # This script runs until we disconnect its transport.
-        scriptPath = FilePath(__file__).sibling(b"process_echoer.py").path
+        scriptPath = b"twisted.test.process_echoer"
 
         class ErrorInProcessEnded(protocol.ProcessProtocol):
             """
@@ -1197,8 +1213,8 @@
         # Launch the process.
         reactor.spawnProcess(
             ErrorInProcessEnded(), pyExe,
-            [pyExe, scriptPath],
-            env=None, path=None)
+            [pyExe, b"-u", b"-m", scriptPath],
+            env=properEnv, path=None)
 
         pid = []
         def cbConnected(transport):
@@ -2150,7 +2166,7 @@
         return d.addCallback(processEnded)
 
 
-    def testProcess(self):
+    def test_process(self):
         cmd = self.getCommand('gzip')
         s = b"there's no place like home!\n" * 3
         p = Accumulator()
@@ -2181,12 +2197,12 @@
     # testProcess, but not without p.transport.closeStdin
     #  might be solveable: TODO: add test if so
 
-    def testOpeningTTY(self):
-        scriptPath = FilePath(__file__).sibling(b"process_tty.py").path
+    def test_openingTTY(self):
+        scriptPath = b"twisted.test.process_tty"
         p = Accumulator()
         d = p.endedDeferred = defer.Deferred()
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=None,
-                            path=None, usePTY=self.usePTY)
+        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", b"-m", scriptPath],
+                             env=properEnv, usePTY=self.usePTY)
         p.transport.write(b"hello world!\n")
 
         def processEnded(ign):
@@ -2195,11 +2211,12 @@
             self.assertEqual(
                 p.outF.getvalue(),
                 b"hello world!\r\nhello world!\r\n",
-                "Error message from process_tty follows:\n\n%s\n\n" % p.outF.getvalue())
+                ("Error message from process_tty "
+                 "follows:\n\n%s\n\n" % (p.outF.getvalue(),)))
         return d.addCallback(processEnded)
 
 
-    def testBadArgs(self):
+    def test_badArgs(self):
         pyArgs = [pyExe, b"-u", b"-c", b"print('hello')"]
         p = Accumulator()
         self.assertRaises(ValueError, reactor.spawnProcess, p, pyExe, pyArgs,
@@ -2235,12 +2252,12 @@
     Test process programs that are packaged with twisted.
     """
 
-    def testStdinReader(self):
-        scriptPath = FilePath(__file__).sibling(b"process_stdinreader.py").path
+    def test_stdinReader(self):
+        scriptPath = b"twisted.test.process_stdinreader"
         p = Accumulator()
         d = p.endedDeferred = defer.Deferred()
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=None,
-                             path=None)
+        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", b"-m", scriptPath],
+                             env=properEnv)
         p.transport.write(b"hello, world")
         p.transport.closeStdin()
 
@@ -2250,7 +2267,7 @@
         return d.addCallback(processEnded)
 
 
-    def testBadArgs(self):
+    def test_badArgs(self):
         pyArgs = [pyExe, b"-u", b"-c", b"print('hello')"]
         p = Accumulator()
         self.assertRaises(ValueError,
@@ -2264,10 +2281,11 @@
 
 
     def _testSignal(self, sig):
-        scriptPath = FilePath(__file__).sibling(b"process_signal.py").path
+        scriptPath = b"twisted.test.process_signal"
         d = defer.Deferred()
         p = Win32SignalProtocol(d, sig)
-        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", scriptPath], env=None)
+        reactor.spawnProcess(p, pyExe, [pyExe, b"-u", b"-m", scriptPath],
+                             env=properEnv)
         return d
 
 
@@ -2359,12 +2377,12 @@
         Test C{os.environ} (inherited by every subprocess on Windows) that
         contains an ascii-encodable Unicode string. This is different from
         passing Unicode environment explicitly to spawnProcess (which is not
-        supported).
+        supported on Python 2).
         """
         os.environ[self.goodKey] = self.goodValue
         self.addCleanup(operator.delitem, os.environ, self.goodKey)
 
-        p = GetEnvironmentDictionary.run(reactor, [], {})
+        p = GetEnvironmentDictionary.run(reactor, [], properEnv)
         def gotEnvironment(environ):
             self.assertEqual(
                 environ[self.goodKey.encode('ascii')],
@@ -2470,7 +2488,7 @@
         self.assertEqual(procutils.which("executable"), [])
 
 
-    def testWhich(self):
+    def test_which(self):
         j = os.path.join
         paths = procutils.which("executable")
         expectedPaths = [j(self.foobaz, "executable"),
@@ -2480,7 +2498,7 @@
         self.assertEqual(paths, expectedPaths)
 
 
-    def testWhichPathExt(self):
+    def test_whichPathExt(self):
         j = os.path.join
         old = os.environ.get('PATHEXT', None)
         os.environ['PATHEXT'] = os.pathsep.join(('.bin', '.exe', '.sh'))

Modified: branches/cov-subprocess-8266-3/twisted/test/test_stdio.py
==============================================================================
--- branches/cov-subprocess-8266-3/twisted/test/test_stdio.py	(original)
+++ branches/cov-subprocess-8266-3/twisted/test/test_stdio.py	Sun May  8 08:46:35 2016
@@ -3,6 +3,9 @@
 
 """
 Tests for L{twisted.internet.stdio}.
+
+@var properEnv: A copy of L{os.environ} which has L{bytes} keys/values on POSIX
+    platforms and native L{str} keys/values on Windows.
 """
 
 from __future__ import absolute_import, division
@@ -15,7 +18,7 @@
 from twisted.python import filepath, log
 from twisted.python.reflect import requireModule
 from twisted.python.runtime import platform
-from twisted.python.compat import xrange, intToBytes
+from twisted.python.compat import xrange, intToBytes, bytesEnviron
 from twisted.internet import error, defer, protocol, stdio, reactor
 from twisted.test.test_tcp import ConnectionLostNotifyingProtocol
 
@@ -23,7 +26,7 @@
 # A short string which is intended to appear here and nowhere else,
 # particularly not in any random garbage output CPython unavoidable
 # generates (such as in warning text and so forth).  This is searched
-# for in the output from stdio_test_lastwrite.py and if it is found at
+# for in the output from stdio_test_lastwrite and if it is found at
 # the end, the functionality works.
 UNIQUE_LAST_WRITE_STRING = b'xyz123abc Twisted is great!'
 
@@ -32,6 +35,12 @@
     if requireModule('win32process') is None:
         skipWindowsNopywin32 = ("On windows, spawnProcess is not available "
                                 "in the absence of win32process.")
+    properEnv = dict(os.environ)
+    properEnv["PYTHONPATH"] = os.pathsep.join(sys.path)
+else:
+    properEnv = bytesEnviron()
+    properEnv[b"PYTHONPATH"] = os.pathsep.join(sys.path).encode(
+        sys.getfilesystemencoding())
 
 
 class StandardIOTestProcessProtocol(protocol.ProcessProtocol):
@@ -102,21 +111,14 @@
 
         @return: The L{IProcessTransport} provider for the spawned process.
         """
-        import twisted
-        subenv = dict(os.environ)
-        subenv['PYTHONPATH'] = os.pathsep.join(
-            [os.path.abspath(
-                    os.path.dirname(os.path.dirname(twisted.__file__))),
-             subenv.get('PYTHONPATH', '')
-             ])
         args = [sys.executable,
-                filepath.FilePath(__file__).sibling(sibling).asBytesMode().path,
+                b"-m", b"twisted.test." + sibling,
                 reactor.__class__.__module__] + list(args)
         return reactor.spawnProcess(
             proto,
             sys.executable,
             args,
-            env=subenv,
+            env=properEnv,
             **kw)
 
 
@@ -137,7 +139,7 @@
         log.msg("Child process logging to " + errorLogFile)
         p = StandardIOTestProcessProtocol()
         d = p.onCompletion
-        self._spawnProcess(p, 'stdio_test_loseconn.py', errorLogFile)
+        self._spawnProcess(p, b'stdio_test_loseconn', errorLogFile)
 
         def processEnded(reason):
             # Copy the child's log to ours so it's more visible.
@@ -172,7 +174,7 @@
         d = self._requireFailure(p.onDataReceived, processEnded)
 
         self._spawnProcess(
-            p, 'stdio_test_halfclose.py', errorLogFile)
+            p, b'stdio_test_halfclose', errorLogFile)
         return d
 
 
@@ -196,7 +198,7 @@
 
         try:
             self._spawnProcess(
-                p, 'stdio_test_lastwrite.py', UNIQUE_LAST_WRITE_STRING,
+                p, b'stdio_test_lastwrite', UNIQUE_LAST_WRITE_STRING,
                 usePTY=True)
         except ValueError as e:
             # Some platforms don't work with usePTY=True
@@ -222,7 +224,7 @@
         """
         p = StandardIOTestProcessProtocol()
         d = p.onCompletion
-        self._spawnProcess(p, 'stdio_test_hostpeer.py')
+        self._spawnProcess(p, b'stdio_test_hostpeer')
 
         def processEnded(reason):
             host, peer = p.data[1].splitlines()
@@ -240,7 +242,7 @@
         p = StandardIOTestProcessProtocol()
         d = p.onCompletion
 
-        self._spawnProcess(p, 'stdio_test_write.py')
+        self._spawnProcess(p, b'stdio_test_write')
 
         def processEnded(reason):
             self.assertEqual(p.data[1], b'ok!')
@@ -256,7 +258,7 @@
         p = StandardIOTestProcessProtocol()
         d = p.onCompletion
 
-        self._spawnProcess(p, 'stdio_test_writeseq.py')
+        self._spawnProcess(p, b'stdio_test_writeseq')
 
         def processEnded(reason):
             self.assertEqual(p.data[1], b'ok!')
@@ -289,7 +291,7 @@
                 proc.write(written[-1])
                 reactor.callLater(0.01, connectionMade, None)
 
-        proc = self._spawnProcess(p, 'stdio_test_producer.py')
+        proc = self._spawnProcess(p, b'stdio_test_producer')
 
         p.onConnection.addCallback(connectionMade)
 
@@ -312,7 +314,7 @@
 
         junkPath = self._junkPath()
 
-        self._spawnProcess(p, 'stdio_test_consumer.py', junkPath)
+        self._spawnProcess(p, b'stdio_test_consumer', junkPath)
 
         def processEnded(reason):
             with open(junkPath, 'rb') as f: