[Python-modules-commits] [txfixtures] 01/03: New upstream version 0.4.0

Free Ekanayaka freee at moszumanska.debian.org
Mon Feb 6 12:16:58 UTC 2017


This is an automated email from the git hooks/post-receive script.

freee pushed a commit to branch master
in repository txfixtures.

commit 132605ec2f998af97646a2dc6242b88fb47ef1ae
Author: Free Ekanayaka <freee at debian.org>
Date:   Mon Feb 6 11:56:03 2017 +0000

    New upstream version 0.4.0
---
 ChangeLog                                   | 10 ++++
 PKG-INFO                                    |  2 +-
 doc/phantomjs.rst                           |  9 ++--
 doc/reactor.rst                             |  3 +-
 doc/service.rst                             | 22 ++++----
 setup.cfg                                   |  2 +-
 tests/test_mongodb.py                       |  4 +-
 tests/test_phantomjs.py                     |  6 +--
 tests/test_reactor.py                       | 47 ++++++++++-------
 tests/test_service.py                       | 18 ++++---
 txfixtures.egg-info/PKG-INFO                |  2 +-
 txfixtures.egg-info/pbr.json                |  2 +-
 txfixtures/_twisted/tests/test_threading.py |  2 +-
 txfixtures/_twisted/threading.py            |  4 +-
 txfixtures/mongodb.py                       | 24 +++++----
 txfixtures/phantomjs.py                     | 27 ++++++----
 txfixtures/reactor.py                       |  6 +--
 txfixtures/service.py                       | 81 +++++++++++++++--------------
 txfixtures/tests/test_mongodb.py            |  4 +-
 txfixtures/tests/test_phantomjs.py          |  6 +--
 txfixtures/tests/test_reactor.py            |  2 +-
 txfixtures/tests/test_service.py            | 12 +++--
 22 files changed, 165 insertions(+), 130 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index bc691a8..05c1e58 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,16 @@
 CHANGES
 =======
 
+0.4.0
+-----
+
+* Make argument passing explicit (#7)
+
+0.3.0
+-----
+
+* Don't use the global Twisted reactor by default (#6)
+
 0.2.7
 -----
 
diff --git a/PKG-INFO b/PKG-INFO
index d5d1cd6..2440670 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: txfixtures
-Version: 0.2.7
+Version: 0.4.0
 Summary: Treat Twisted applications as Python test fixtures
 Home-page: https://launchpad.net/txfixtures
 Author: Martin Pool
diff --git a/doc/phantomjs.rst b/doc/phantomjs.rst
index f02443d..a76db11 100644
--- a/doc/phantomjs.rst
+++ b/doc/phantomjs.rst
@@ -12,21 +12,22 @@ Selenium_-based assertions:
    >>> from testtools import TestCase
    >>> from txfixtures import Reactor, Service, PhantomJS
 
-   >>> TWIST_COMMAND = "twistd -n web".split(" ")
+   >>> TWISTD = "twistd"
+   >>> TWISTD_ARGS = "-n web".split(" ")
 
    >>> class HTTPServerTest(TestCase):
    ...
    ...     def setUp(self):
    ...         super().setUp()
    ...         self.logger = self.useFixture(FakeLogger())
-   ...         self.useFixture(Reactor())
+   ...         reactor = self.useFixture(Reactor())
    ...
    ...         # Create a sample web server
-   ...         self.service = Service(TWIST_COMMAND)
+   ...         self.service = Service(reactor, TWISTD, args=TWISTD_ARGS)
    ...         self.service.expectPort(8080)
    ...         self.useFixture(self.service)
    ...
-   ...         self.phantomjs = self.useFixture(PhantomJS())
+   ...         self.phantomjs = self.useFixture(PhantomJS(reactor))
    ...
    ...     def test_home_page(self):
    ...         self.phantomjs.webdriver.get("http://localhost:8080")
diff --git a/doc/reactor.rst b/doc/reactor.rst
index 5f24f1d..599ba25 100644
--- a/doc/reactor.rst
+++ b/doc/reactor.rst
@@ -21,6 +21,7 @@ The typical use case is integration testing.
 
 .. doctest::
 
+
    >>> from testtools import TestCase
 
    >>> from twisted.internet import reactor
@@ -33,7 +34,7 @@ The typical use case is integration testing.
    ...
    ...     def setUp(self):
    ...         super().setUp()
-   ...         self.useFixture(Reactor())
+   ...         self.fixture = self.useFixture(Reactor(reactor=reactor))
    ...
    ...     def test_uptime(self):
    ...         out = blockingCallFromThread(reactor, getProcessOutput, b"uptime")
diff --git a/doc/service.rst b/doc/service.rst
index 27310c9..a39e333 100644
--- a/doc/service.rst
+++ b/doc/service.rst
@@ -22,17 +22,18 @@ port 8080:
    >>> from testtools import TestCase
    >>> from txfixtures import Reactor, Service
 
-   >>> HTTP_SERVER = "python3 -m http.server 8080".split(" ")
+   >>> PYTHON = "python3"
+   >>> PYTHON_HTTP_ARGS = "-m http.server 8080".split(" ")
 
    >>> class HTTPServerTest(TestCase):
    ...
    ...     def setUp(self):
    ...         super().setUp()
-   ...         self.useFixture(Reactor())
+   ...         reactor = self.useFixture(Reactor())
    ...
    ...         # Create a service fixture that will spawn the HTTP server
    ...         # and wait for it to listen to port 8080.
-   ...         self.service = Service(HTTP_SERVER)
+   ...         self.service = Service(reactor, PYTHON, args=PYTHON_HTTP_ARGS)
    ...         self.service.expectPort(8080)
    ...
    ...         self.useFixture(self.service)
@@ -58,7 +59,8 @@ the Python logging system:
 
    >>> from fixtures import FakeLogger
 
-   >>> TWIST_COMMAND = "twistd -n web".split(" ")
+   >>> TWISTD = "twistd"
+   >>> TWISTD_ARGS = "-n web".split(" ")
 
    # This format string will be used to build a regular expression to parse
    # each output line of the service, and map it to a Python LogRecord. A
@@ -66,23 +68,23 @@ the Python logging system:
    #
    #   2016-11-17T22:18:36+0000 [-] Site starting on 8080
    #
-   >>> TWIST_FORMAT = "{Y}-{m}-{d}T{H}:{M}:{S}\+0000 \[{name}\] {message}"
+   >>> TWISTD_FORMAT = "{Y}-{m}-{d}T{H}:{M}:{S}\+0000 \[{name}\] {message}"
 
    # This output string will be used as a "marker" indicating that the service
    # has initialized, and should shortly start listening to the expected port (if
    # one was given). The fixture.setUp() method will intercept this marker and
    # then wait for the service to actually open the port.
-   >>> TWIST_OUTPUT = "Site starting on 8080"
+   >>> TWISTD_OUTPUT = "Site starting on 8080"
 
    >>> class TwistedWebTest(TestCase):
    ...
    ...     def setUp(self):
    ...         super().setUp()
    ...         self.logger = self.useFixture(FakeLogger())
-   ...         self.useFixture(Reactor())
-   ...         self.service = Service(TWIST_COMMAND)
-   ...         self.service.setOutputFormat(TWIST_FORMAT)
-   ...         self.service.expectOutput(TWIST_OUTPUT)
+   ...         reactor = self.useFixture(Reactor())
+   ...         self.service = Service(reactor, TWISTD, args=TWISTD_ARGS)
+   ...         self.service.setOutputFormat(TWISTD_FORMAT)
+   ...         self.service.expectOutput(TWISTD_OUTPUT)
    ...         self.service.expectPort(8080)
    ...         self.useFixture(self.service)
    ...
diff --git a/setup.cfg b/setup.cfg
index 9548f8b..ddf50f7 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,7 +32,7 @@ mongodb =
 universal = 1
 
 [egg_info]
-tag_date = 0
 tag_svn_revision = 0
 tag_build = 
+tag_date = 0
 
diff --git a/tests/test_mongodb.py b/tests/test_mongodb.py
index 818fe6b..b6c7101 100644
--- a/tests/test_mongodb.py
+++ b/tests/test_mongodb.py
@@ -11,8 +11,8 @@ class MongoDBIntegrationTest(TestCase):
     def setUp(self):
         super(MongoDBIntegrationTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
-        self.useFixture(Reactor())
-        self.mongodb = MongoDB()
+        reactor = self.useFixture(Reactor())
+        self.mongodb = MongoDB(reactor)
 
     def test_client(self):
         """
diff --git a/tests/test_phantomjs.py b/tests/test_phantomjs.py
index 64b6233..1407acc 100644
--- a/tests/test_phantomjs.py
+++ b/tests/test_phantomjs.py
@@ -18,15 +18,15 @@ class PhantomJSIntegrationTest(TestCase):
     def setUp(self):
         super(PhantomJSIntegrationTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
-        self.useFixture(Reactor())
+        reactor = self.useFixture(Reactor())
 
         # Setup a local web server to test the WebDriver
-        server = Service(["twist", "web"], timeout=5)
+        server = Service(reactor, "twist", args=["web"], timeout=5)
         server.expectOutput("Starting reactor...")
         server.expectPort(8080)
         self.useFixture(server)
 
-        self.fixture = PhantomJS(timeout=5)
+        self.fixture = PhantomJS(reactor, timeout=10)
 
     @skipIf(not hasTwist, "twist executable not available")
     def test_webdriver(self):
diff --git a/tests/test_reactor.py b/tests/test_reactor.py
index 0e48bba..72ee8fd 100644
--- a/tests/test_reactor.py
+++ b/tests/test_reactor.py
@@ -14,8 +14,8 @@ from testtools.monkey import MonkeyPatcher
 
 from fixtures import FakeLogger
 
-from twisted.internet import reactor
 from twisted.internet.utils import getProcessOutput
+from twisted.internet.epollreactor import EPollReactor
 
 from txfixtures._twisted.threading import CallFromThreadTimeout
 
@@ -32,8 +32,9 @@ AsyncioSelectorReactor = try_import(
 class ReactorPatcher(MonkeyPatcher):
     """Monkey patch reactor methods to simulate various failure scenarios."""
 
-    def __init__(self):
+    def __init__(self, reactor):
         super(ReactorPatcher, self).__init__()
+        self.reactor = reactor
         self._originalMainLoop = reactor.mainLoop
         self._originalCallFromThread = reactor.callFromThread
 
@@ -84,7 +85,7 @@ class ReactorPatcher(MonkeyPatcher):
             self.hangingDo.put(None)
         if self.crashingDo:
             self.crashingDo.put(None)
-        reactor.crash()
+        self.reactor.crash()
 
     def _mainLoop(self):
         if self.hangingDo:
@@ -112,7 +113,7 @@ class ReactorPatcher(MonkeyPatcher):
         abruptely = " abruptely" if self.crashingAbruptly else ""
         logging.info("Crashing main loop%s", abruptely)
         if not self.crashingAbruptly:
-            reactor.crash()
+            self.reactor.crash()
         # Notify that we have successfully crashed
         self.crashingNotify.put(None)
         self.crashingDo = None
@@ -156,10 +157,9 @@ class ReactorIntegrationTest(TestCase):
     def setUp(self):
         super(ReactorIntegrationTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
-        self.patcher = ReactorPatcher()
-        self.patcher.patch()
-        self.fixture = Reactor()
-
+        self.reactor = EPollReactor()
+        self.fixture = Reactor(self.reactor)
+        self.patcher = ReactorPatcher(self.fixture.reactor)
         self.addCleanup(self._cleanup)
 
     def _cleanup(self):
@@ -174,7 +174,7 @@ class ReactorIntegrationTest(TestCase):
     def test_reactor_running(self):
         """After setUp is run, the reactor is spinning."""
         self.useFixture(self.fixture)
-        self.assertTrue(reactor.running)
+        self.assertTrue(self.reactor.running)
 
     @skipIf(not AsyncioSelectorReactor, "asyncio reactor not available")
     def test_asyncio_reactor(self):
@@ -204,7 +204,8 @@ class ReactorIntegrationTest(TestCase):
     def test_call(self):
         """The call() method is a convenience around blockingFromThread."""
         self.useFixture(self.fixture)
-        output = self.fixture.call(TIMEOUT, getProcessOutput, b("uptime"))
+        output = self.fixture.call(
+            TIMEOUT, getProcessOutput, b("uptime"), reactor=self.reactor)
         self.assertIn(b("load average"), output)
 
     def test_reset_thread_and_reactor_died(self):
@@ -212,12 +213,12 @@ class ReactorIntegrationTest(TestCase):
         The reset() method creates a new thread if the initial one has died.
         """
         self.useFixture(self.fixture)
-        self.fixture.call(TIMEOUT, reactor.crash)
+        self.fixture.call(TIMEOUT, self.reactor.crash)
         self.fixture.thread.join(timeout=TIMEOUT)
         self.assertFalse(self.fixture.thread.isAlive())
 
         self.fixture.reset()
-        self.assertTrue(reactor.running)
+        self.assertTrue(self.reactor.running)
         self.assertIn(
             "Twisted reactor thread died, trying to recover",
             self.logger.output)
@@ -227,6 +228,8 @@ class ReactorIntegrationTest(TestCase):
         If the reactor crashes badly and is left in a bad state (e.g. running),
         the fixtures tries a best-effort clean up.
         """
+        self.fixture.timeout = 100
+        self.patcher.patch()
         self.patcher.scheduleCrash(abruptly=True)
         self.useFixture(self.fixture)
         self.patcher.crashingDo.put(None)
@@ -234,7 +237,7 @@ class ReactorIntegrationTest(TestCase):
         # At this point the thread should be dead and the reactor broken
         self.fixture.thread.join(TIMEOUT)
         self.assertFalse(self.fixture.thread.isAlive())
-        self.assertTrue(reactor.running)
+        self.assertTrue(self.reactor.running)
 
         self.fixture.reset()
 
@@ -247,13 +250,15 @@ class ReactorIntegrationTest(TestCase):
 
         # Things should be back to normality
         self.assertTrue(self.fixture.thread.isAlive(), "Thread did not resume")
-        self.assertTrue(reactor.running, "Reactor did not recover")
+        self.assertTrue(
+            self.reactor.running, "Reactor did not recover")
 
     def test_reset_thread_alive_but_reactor_is_not_running(self):
         """
         The reset() method bails out if the thread is alive but the reactor
         doesn't appear to be running.
         """
+        self.patcher.patch()
         self.patcher.scheduleHang()
         self.patcher.scheduleCrash()
         self.fixture.setUp()
@@ -262,7 +267,7 @@ class ReactorIntegrationTest(TestCase):
 
         # At this point the thread should be alive and the reactor broken
         self.assertTrue(self.fixture.thread.isAlive())
-        self.assertFalse(reactor.running)
+        self.assertFalse(self.reactor.running)
 
         error = self.assertRaises(RuntimeError, self.fixture.reset)
         self.assertEqual("Hung reactor thread detected", str(error))
@@ -272,14 +277,14 @@ class ReactorIntegrationTest(TestCase):
         self.fixture.setUp()
         self.fixture.cleanUp()
         self.assertFalse(self.fixture.thread.isAlive())
-        self.assertFalse(reactor.running)
+        self.assertFalse(self.reactor.running)
 
     def test_cleanup_thread_not_alive(self):
         """
         If the thread is not alive, the cleanup phase is essentially a no-op.
         """
         self.fixture.setUp()
-        self.fixture.call(TIMEOUT, reactor.crash)
+        self.fixture.call(TIMEOUT, self.reactor.crash)
         self.fixture.thread.join(TIMEOUT)
         self.fixture.cleanUp()
 
@@ -297,6 +302,7 @@ class ReactorIntegrationTest(TestCase):
         If cleanUp() detects a hung thread with no reactor running, an error
         is raised.
         """
+        self.patcher.patch()
         self.patcher.scheduleHang()
         self.patcher.scheduleCrash()
         self.fixture.setUp()
@@ -305,7 +311,7 @@ class ReactorIntegrationTest(TestCase):
 
         # At this point the thread should be alive and the reactor stopped
         self.assertTrue(self.fixture.thread.isAlive())
-        self.assertFalse(reactor.running)
+        self.assertFalse(self.reactor.running)
 
         error = self.assertRaises(RuntimeError, self.fixture.cleanUp)
         self.assertEqual("Hung reactor thread detected", str(error))
@@ -314,13 +320,14 @@ class ReactorIntegrationTest(TestCase):
         """
         If cleanUp() can't stop the reactor, an error is raised.
         """
+        self.patcher.patch()
         self.patcher.scheduleHang()
-        self.patcher.scheduleCallFromThreadTimeout(reactor.crash)
+        self.patcher.scheduleCallFromThreadTimeout(self.reactor.crash)
         self.fixture.setUp()
 
         # At this point the thread should be alive and the reactor running
         self.assertTrue(self.fixture.thread.isAlive())
-        self.assertTrue(reactor.running)
+        self.assertTrue(self.reactor.running)
 
         error = self.assertRaises(RuntimeError, self.fixture.cleanUp)
         self.assertEqual("Could not stop the reactor", str(error))
diff --git a/tests/test_service.py b/tests/test_service.py
index 7780790..0aca936 100644
--- a/tests/test_service.py
+++ b/tests/test_service.py
@@ -36,9 +36,10 @@ class ServiceIntegrationTest(TestCase):
     def setUp(self):
         super(ServiceIntegrationTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
-        self.useFixture(Reactor())
         self.script = self.useFixture(FakeExecutable())
-        self.fixture = Service([self.script.path.encode("utf-8")], timeout=1)
+        reactor = self.useFixture(Reactor())
+        command = self.script.path.encode("utf-8")
+        self.fixture = Service(reactor, command)
 
     def test_service_ready(self):
         """After setUp is run, the service is fully ready."""
@@ -51,17 +52,18 @@ class ServiceIntegrationTest(TestCase):
 
     def test_unknown_command(self):
         """If an unknown command is given, setUp raises an error."""
-        self.fixture.command = [b"/foobar"]
+        self.fixture.command = b"/foobar"
+        self.fixture.protocol.minUptime = 2.5
         error = self.assertRaises(MultipleExceptions, self.fixture.setUp)
         self.assertIsInstance(error.args[0][1], ProcessTerminated)
         self.assertIn("No such file or directory", self.logger.output)
 
     def test_non_executable_command(self):
         """If the given command is not executable, setUp raises an error."""
-        executable = self.useFixture(TempDir()).join("foobar")
-        with open(executable, "w") as fd:
+        path = self.useFixture(TempDir()).join("foobar")
+        with open(path, "w") as fd:
             fd.write("")
-        self.fixture.command = [executable.encode("utf-8")]
+        self.fixture.command = path.encode("utf-8")
         self.fixture.protocol.minUptime = 2.5
         error = self.assertRaises(MultipleExceptions, self.fixture.setUp)
         self.assertIsInstance(error.args[0][1], ProcessTerminated)
@@ -71,7 +73,7 @@ class ServiceIntegrationTest(TestCase):
         If the given command doesn't terminate with SIGTERM, it's SIGKILL'ed.
         """
         self.script.hang()
-        self.fixture.protocol.timeout = 0.2
+        self.fixture.protocol.timeout = 0.5
         self.fixture.expectOutput("hanging")
         self.fixture.setUp()
         self.fixture.cleanUp()
@@ -87,7 +89,7 @@ class ServiceProtocolIntegrationTest(TestCase):
     def setUp(self):
         super(ServiceProtocolIntegrationTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
-        self.protocol = ServiceProtocol()
+        self.protocol = ServiceProtocol(reactor)
         self.process = None
         self.script = self.useFixture(FakeExecutable())
 
diff --git a/txfixtures.egg-info/PKG-INFO b/txfixtures.egg-info/PKG-INFO
index d5d1cd6..2440670 100644
--- a/txfixtures.egg-info/PKG-INFO
+++ b/txfixtures.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: txfixtures
-Version: 0.2.7
+Version: 0.4.0
 Summary: Treat Twisted applications as Python test fixtures
 Home-page: https://launchpad.net/txfixtures
 Author: Martin Pool
diff --git a/txfixtures.egg-info/pbr.json b/txfixtures.egg-info/pbr.json
index 72802ae..3270fbd 100644
--- a/txfixtures.egg-info/pbr.json
+++ b/txfixtures.egg-info/pbr.json
@@ -1 +1 @@
-{"git_version": "9ee4d6a", "is_release": true}
\ No newline at end of file
+{"git_version": "c5d4424", "is_release": true}
\ No newline at end of file
diff --git a/txfixtures/_twisted/tests/test_threading.py b/txfixtures/_twisted/tests/test_threading.py
index a832df9..c00eaed 100644
--- a/txfixtures/_twisted/tests/test_threading.py
+++ b/txfixtures/_twisted/tests/test_threading.py
@@ -21,7 +21,7 @@ class InterruptableCallFromThreadTest(TestCase):
 
     def setUp(self):
         super(InterruptableCallFromThreadTest, self).setUp()
-        self.useFixture(Reactor())
+        self.useFixture(Reactor(reactor))
 
     def test_success(self):
         """
diff --git a/txfixtures/_twisted/threading.py b/txfixtures/_twisted/threading.py
index 18d2e1b..309ad87 100644
--- a/txfixtures/_twisted/threading.py
+++ b/txfixtures/_twisted/threading.py
@@ -13,7 +13,7 @@ class CallFromThreadTimeout(Exception):
     """Raised when interruptableCallFromThread times out."""
 
 
-def interruptableCallFromThread(reactor, timeout, f, *a, **kw):
+def interruptableCallFromThread(_reactor, timeout, f, *a, **kw):
     """An interruptable version of Twisted's blockingCallFromThread.
 
     This function has all arguments and semantics of the original one, plus
@@ -25,7 +25,7 @@ def interruptableCallFromThread(reactor, timeout, f, *a, **kw):
     def _callFromThread(queue, f):
         result = maybeDeferred(f, *a, **kw)
         result.addBoth(queue.put)
-    reactor.callFromThread(_callFromThread, queue, f)
+    _reactor.callFromThread(_callFromThread, queue, f)
     try:
         result = queue.get(timeout=timeout)
     except Empty:
diff --git a/txfixtures/mongodb.py b/txfixtures/mongodb.py
index 5bb4720..87509e5 100644
--- a/txfixtures/mongodb.py
+++ b/txfixtures/mongodb.py
@@ -1,9 +1,11 @@
 import pymongo
 
-from fixtures import TempDir
-
-from txfixtures.service import Service
+from txfixtures.service import (
+    TIMEOUT,
+    Service
+)
 
+COMMAND = b"mongod"
 FORMAT = (
     "{Y}-{m}-{d}T{H}:{M}:{S}\.{msecs}\+0000 {levelname} "
     "[A-Z]+ +\[{name}\] {message}")
@@ -12,9 +14,10 @@ FORMAT = (
 class MongoDB(Service):
     """Start and stop a `mongodb` process in the background. """
 
-    def __init__(self, mongod=b"mongod", args=(), **kwargs):
-        command = [mongod] + list(args)
-        super(MongoDB, self).__init__(command, **kwargs)
+    def __init__(self, reactor, command=COMMAND, args=None, env=None,
+                 timeout=None):
+        super(MongoDB, self).__init__(
+            reactor, command=command, args=args, env=env, timeout=timeout)
 
         self.expectOutput("waiting for connections on port")
         self.setOutputFormat(FORMAT)
@@ -30,7 +33,7 @@ class MongoDB(Service):
 
     def _setUp(self):
         self.expectPort(self.allocatePort())
-        self._dbPath = self.useFixture(TempDir())
+        self.addDataDir()
         super(MongoDB, self)._setUp()
         uri = "mongodb://localhost:%d" % self.port
         self.client = pymongo.MongoClient(uri, **self.clientKwargs)
@@ -39,10 +42,9 @@ class MongoDB(Service):
         # XXX Workaround pymongo leaving threads around.
         self.addCleanup(pymongo.periodic_executor._shutdown_executors)
 
-    @property
-    def _args(self):
-        return self.command[:] + [
+    def _extraArgs(self):
+        return [
             b"--port=%d" % self.port,
-            b"--dbpath=%s" % self._dbPath.path.encode("utf-8"),
+            b"--dbpath=%s" % self._data_dirs[0].encode("utf-8"),
             b"--nojournal",
         ]
diff --git a/txfixtures/phantomjs.py b/txfixtures/phantomjs.py
index 7366081..07c32ee 100644
--- a/txfixtures/phantomjs.py
+++ b/txfixtures/phantomjs.py
@@ -1,10 +1,14 @@
+import os
+
 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
 from selenium.webdriver.remote import webdriver
 
-from fixtures import TempDir
-
-from txfixtures.service import Service
+from txfixtures.service import (
+    TIMEOUT,
+    Service,
+)
 
+COMMAND = b"phantomjs"
 FORMAT = (
     "\[{levelname} +- +{Y}-{m}-{d}T{H}:{M}:{S}\.{msecs}Z\] {name} - {message}")
 
@@ -12,9 +16,10 @@ FORMAT = (
 class PhantomJS(Service):
     """Start and stop a `phantomjs` process in the background. """
 
-    def __init__(self, phantomjs="phantomjs", args=(), **kwargs):
-        command = [phantomjs] + list(args)
-        super(PhantomJS, self).__init__(command, **kwargs)
+    def __init__(self, reactor, command=COMMAND, args=None, env=None,
+                 timeout=None):
+        super(PhantomJS, self).__init__(
+            reactor, command=command, args=args, env=env, timeout=timeout)
 
         #: Desired capabilities that will be passed to the webdriver.
         self.desiredCapabilities = DesiredCapabilities.PHANTOMJS
@@ -28,16 +33,16 @@ class PhantomJS(Service):
 
     def _setUp(self):
         self.expectPort(self.allocatePort())
-        self._cookies = self.useFixture(TempDir()).join("phantomjs.cookies")
+        self.addDataDir()
         super(PhantomJS, self)._setUp()
         url = "http://localhost:%d/wd/hub" % self.protocol.expectedPort
         self.webdriver = webdriver.WebDriver(
             command_executor=url,
             desired_capabilities=self.desiredCapabilities)
 
-    @property
-    def _args(self):
-        return self.command[:] + [
+    def _extraArgs(self):
+        cookies_file = os.path.join(self._data_dirs[0], "phantomjs.cookies")
+        return [
             "--webdriver=%d" % self.protocol.expectedPort,
-            "--cookies-file=%s" % self._cookies,
+            "--cookies-file=%s" % cookies_file,
         ]
diff --git a/txfixtures/reactor.py b/txfixtures/reactor.py
index df28428..7bc3627 100644
--- a/txfixtures/reactor.py
+++ b/txfixtures/reactor.py
@@ -7,8 +7,8 @@ from six.moves.queue import Queue
 
 from fixtures import Fixture
 
-from twisted.internet import reactor as defaultTwistedReactor
 from twisted.internet.posixbase import _SIGCHLDWaker
+from twisted.internet.epollreactor import EPollReactor
 
 from txfixtures._twisted.threading import (
     CallFromThreadTimeout,
@@ -36,7 +36,7 @@ class Reactor(Fixture):
         :ivar thread: The `~threading.Thread` that the reactor runs in.
         """
         super(Reactor, self).__init__()
-        self.reactor = reactor or defaultTwistedReactor
+        self.reactor = reactor or EPollReactor()
         self.timeout = timeout
         self.thread = None
 
@@ -107,6 +107,7 @@ class Reactor(Fixture):
         # reactor thread as it's not thread-safe. The SIGCHLD waker will
         # react to SIGCHLD signals by writing to a dummy pipe, which will
         # wake up epoll() calls.
+        self.reactor._childWaker = _SIGCHLDWaker(self.reactor)
         self.call(1, self._addSIGCHLDWaker)
 
         # Install the actual signal hander (this needs to happen in the main
@@ -171,7 +172,6 @@ class Reactor(Fixture):
 
     def _addSIGCHLDWaker(self):
         """Add a `_SIGNCHLDWaker` to wake up the reactor when a child exits."""
-        self.reactor._childWaker = _SIGCHLDWaker(self.reactor)
         self.reactor._internalReaders.add(self.reactor._childWaker)
         self.reactor.addReader(self.reactor._childWaker)
 
diff --git a/txfixtures/service.py b/txfixtures/service.py
index f716c56..1043823 100644
--- a/txfixtures/service.py
+++ b/txfixtures/service.py
@@ -3,15 +3,16 @@ import os
 import re
 import signal
 import socket
-import logging
 
 from datetime import datetime
 
 from psutil import Process
 
-from fixtures import Fixture
+from fixtures import (
+    Fixture,
+    TempDir,
+)
 
-from twisted.internet import reactor as defaultTwistedReactor
 from twisted.internet.protocol import (
     Factory,
     Protocol,
@@ -29,7 +30,6 @@ from twisted.internet.error import (
 )
 from twisted.protocols.basic import LineOnlyReceiver
 
-from txfixtures._twisted.threading import interruptableCallFromThread
 from txfixtures._twisted.backports.defer import addTimeout
 
 
@@ -50,28 +50,33 @@ SHORT_LEVELS = {
 class Service(Fixture):
     """Spawn, control and monitor a background service."""
 
-    def __init__(self, command, reactor=None, timeout=TIMEOUT, env=None):
+    def __init__(self, reactor, command, args=None, env=None, timeout=None):
         super(Service, self).__init__()
-        self.command = command
-        self.env = _encodeDictValues(env or os.environ.copy())
-        parser = ServiceOutputParser(self._executable)
 
-        # XXX Set the reactor as private, since the public 'reactor' attribute
-        #     is typically a Reactor fixture, set by testresources as
-        #     dependency.
-        if reactor is None:
-            reactor = defaultTwistedReactor
-        self._reactor = reactor
+        self.reactor = reactor
+        self.command = command
+        self.args = args or []
 
-        self.protocol = ServiceProtocol(
-            reactor=self._reactor, parser=parser, timeout=timeout)
+        if env is None:
+            env = os.environ
+        self.env = _encodeDictValues(env)
 
+        self._reactor = reactor.reactor
         self._eventTriggerID = None
+        self._data_dirs = []
+
+        if timeout is None:
+            timeout = TIMEOUT
+        self.protocol = ServiceProtocol(reactor=self._reactor, timeout=timeout)
 
     def reset(self):
         if self.protocol.terminated.called:
             raise RuntimeError("Service died")
 
+    def addDataDir(self):
+        data_dir = self.useFixture(TempDir())
+        self._data_dirs.append(data_dir.path)
+
     def expectOutput(self, data):
         self.protocol.expectedOutput = data
 
@@ -104,22 +109,19 @@ class Service(Fixture):
         self.addCleanup(self._stop)
         self._callFromThread(self._start)
 
-    @property
-    def _executable(self):
-        return self.command[0]
-
-    @property
-    def _args(self):
-        return self.command
+    def _extraArgs(self):
+        return []
 
     @property
     def _name(self):
-        return os.path.basename(self._executable)
+        return os.path.basename(self.command)
 
     @inlineCallbacks
     def _start(self):
+        self.protocol.parser.setServiceName(self._name)
+        args = [self.command] + self.args + self._extraArgs()
         self._reactor.spawnProcess(
-            self.protocol, self._executable, args=self._args, env=self.env)
+            self.protocol, self.command, args=args, env=self.env)
 
         # This cleanup handler will be triggered in case of SIGTERM and SIGINT,
         # when the reactor will initiate an unexpected shutdown sequence.
@@ -148,8 +150,7 @@ class Service(Fixture):
         # want this timeout to be greater than the 'ready' deferred timeout
         # set in _start(), so if the reactor thread is hung or dies we still
         # properly timeout.
-        timeout = self.protocol.timeout + 1
-        interruptableCallFromThread(self._reactor, timeout, f)
+        self.reactor.call(self.protocol.timeout + 1, f)
 
     @inlineCallbacks
     def _terminateProcess(self):
@@ -178,11 +179,11 @@ class ServiceProtocol(ProcessProtocol):
     #: The service process must stay up at least this amount of seconds, before
     #: it's considered running. This allows to catch common issues like the
     #: service process executable not being in PATH or not being executable.
-    minUptime = 0.1
+    minUptime = 0.2
 
-    def __init__(self, reactor=None, parser=None, timeout=TIMEOUT):
-        self.reactor = reactor or defaultTwistedReactor
-        self.parser = parser or ServiceOutputParser("")
+    def __init__(self, reactor, parser=None, timeout=TIMEOUT):
+        self.reactor = reactor
+        self.parser = parser or ServiceOutputParser()
 
         #: Maximum amount of seconds to wait for the service to be ready. After
         #: that, the 'ready' deferred will errback with a TimeoutError.
@@ -445,17 +446,19 @@ class ServiceOutputParser(LineOnlyReceiver):
         "message": "(?P<message>.+)",
     }
 
-    def __init__(self, service, logger=None, pattern=None):
-        """
-        :param service: A string identifying the service whose output is being
-            parsed. It will be attached as 'service' attribute to all log
-            records emitted.
-        """
-        self.service = service
+    #: A string identifying the service whose output is being
+    #: parsed. It will be attached as 'service' attribute to all log
+    #: records emitted.
+    service = ""
+
+    def __init__(self, logger=None, pattern=None):
         self.pattern = pattern or "{message}"
         self.logger = logger or logging.getLogger("")
         self._callbacks = {}
 
+    def setServiceName(self, name):
+        self.service = name
+
     def whenLineContains(self, text, callback):
         """Fire the given callback when a line contains the given text.
 
@@ -540,7 +543,7 @@ def _encodeDictValues(d):
     """
     return dict(
         [(_maybeEncode(k), _maybeEncode(v))
-        for k, v in d.items() if v is not None])
+         for k, v in d.items() if v is not None])
 
 
 def _maybeEncode(x):
diff --git a/txfixtures/tests/test_mongodb.py b/txfixtures/tests/test_mongodb.py
index 95ab699..d3a3cb0 100644
--- a/txfixtures/tests/test_mongodb.py
+++ b/txfixtures/tests/test_mongodb.py
@@ -9,7 +9,7 @@ from testtools.matchers import (
 from fixtures import FakeLogger
 
 from txfixtures._twisted.testing import ThreadedMemoryReactorClock
-
+from txfixtures.reactor import Reactor
 from txfixtures.mongodb import MongoDB
 
 OUT = (
@@ -25,7 +25,7 @@ class MongoDBTest(TestCase):
         super(MongoDBTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
         self.reactor = ThreadedMemoryReactorClock()
-        self.fixture = MongoDB(reactor=self.reactor)
+        self.fixture = MongoDB(Reactor(self.reactor))
 
     def test_setup(self):
         """
diff --git a/txfixtures/tests/test_phantomjs.py b/txfixtures/tests/test_phantomjs.py
index 1fd6238..77ecb01 100644
--- a/txfixtures/tests/test_phantomjs.py
+++ b/txfixtures/tests/test_phantomjs.py
@@ -11,7 +11,7 @@ from selenium.webdriver.remote import webdriver
 from fixtures import FakeLogger
 
 from txfixtures._twisted.testing import ThreadedMemoryReactorClock
-
+from txfixtures.reactor import Reactor
 from txfixtures.phantomjs import PhantomJS
 
 OUT = (
@@ -27,7 +27,7 @@ class PhantomJSTest(TestCase):
         super(PhantomJSTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
         self.reactor = ThreadedMemoryReactorClock()
-        self.fixture = PhantomJS(reactor=self.reactor)
+        self.fixture = PhantomJS(Reactor(self.reactor))
 
     def test_setup(self):
         """
@@ -46,7 +46,7 @@ class PhantomJSTest(TestCase):
 
         self.fixture.setUp()
         executable, arg1, arg2 = self.reactor.process.args
-        self.assertEqual("phantomjs", executable)
+        self.assertEqual(b"phantomjs", executable)
         self.assertEqual("--webdriver=666", arg1)
         self.assertThat(arg2, StartsWith("--cookies-file="))
         self.assertThat(os.path.dirname(arg2.split("=")[1]), DirExists())
diff --git a/txfixtures/tests/test_reactor.py b/txfixtures/tests/test_reactor.py
index cbd96c0..e817c20 100644
--- a/txfixtures/tests/test_reactor.py
+++ b/txfixtures/tests/test_reactor.py
@@ -18,7 +18,7 @@ class ReactorTest(TestCase):
         super(ReactorTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
         self.reactor = ThreadedMemoryReactorClock()
-        self.fixture = Reactor(reactor=self.reactor, timeout=0)
+        self.fixture = Reactor(self.reactor, timeout=0)
         self.threads = self.useFixture(FakeThreads())
 
     def test_install_sigchld_waker(self):
diff --git a/txfixtures/tests/test_service.py b/txfixtures/tests/test_service.py
index 919fd78..c0e117b 100644
--- a/txfixtures/tests/test_service.py
+++ b/txfixtures/tests/test_service.py
@@ -42,6 +42,7 @@ from txfixtures._twisted.testing import (
     MemoryProcess,
 )
 
+from txfixtures.reactor import Reactor
 from txfixtures.service import (
     Service,
     ServiceProtocol,
@@ -55,7 +56,7 @@ class ServiceTest(TestCase):
         super(ServiceTest, self).setUp()
         self.logger = self.useFixture(FakeLogger())
         self.reactor = ThreadedMemoryReactorClock()
-        self.fixture = Service(["foo"], reactor=self.reactor)
+        self.fixture = Service(Reactor(self.reactor), "foo")
 
     def test_setup_start_process(self):
         """
@@ -153,7 +154,7 @@ class ServiceProtocolTest(TestCase):
         self.logger = self.useFixture(FakeLogger())
         self.reactor = MemoryReactorClock()
         self.process = MemoryProcess()
-        self.protocol = ServiceProtocol(reactor=self.reactor)
+        self.protocol = ServiceProtocol(self.reactor)
         self.process.proto = self.protocol
 
     def test_fork(self):
@@ -175,10 +176,10 @@ class ServiceProtocolTest(TestCase):
         'ready' Deferred gets fired.
         """
         self.protocol.makeConnection(self.process)
-        self.reactor.advance(0.1)
+        self.reactor.advance(0.2)
         self.assertThat(self.protocol.ready, succeeded(Is(None)))
         self.assertIn(
-            "Service process alive for 0.1 seconds", self.logger.output)
+            "Service process alive for 0.2 seconds", self.logger.output)
 
     def test_expected_output(self):
         """
@@ -360,7 +361,8 @@ class ServiceOutputParserTest(TestCase):
         self.transport = StringTransport()
         self.handler = BufferingHandler(2)
         self.useFixture(LogHandler(self.handler))
-        self.parser = ServiceOutputParser("my-app")
+        self.parser = ServiceOutputParser()
+        self.parser.setServiceName("my-app")
         self.parser.makeConnection(self.transport)
 
     def test_full_match(self):

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/txfixtures.git



More information about the Python-modules-commits mailing list