[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