Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wait_for and run_in_reactor swallow exceptions #75

Open
hynek opened this issue Feb 6, 2015 · 11 comments
Open

wait_for and run_in_reactor swallow exceptions #75

hynek opened this issue Feb 6, 2015 · 11 comments
Labels

Comments

@hynek
Copy link

hynek commented Feb 6, 2015

Consider the following code:

from __future__ import absolute_import, division, print_function

from crochet import no_setup, wait_for, run_in_reactor

no_setup()

from twisted.trial import unittest as unittest_twisted
import unittest as unittest_stdlib


class C(object):
    @wait_for(1)
    def wait_for(self):
        raise Exception

    @run_in_reactor
    def run_in_reactor(self):
        raise Exception

    def vanilla(self):
        raise Exception


class TestStdLib(unittest_stdlib.TestCase):
    def test_wait_for(self):
        C().wait_for()

    def test_run_in_reactor(self):
        C().run_in_reactor()

    def test_vanilla(self):
        C().vanilla()


class TestTwistedDefault(unittest_twisted.TestCase):
    def test_wait_for(self):
        C().wait_for()

    def test_run_in_reactor(self):
        C().run_in_reactor()

    def test_vanilla(self):
        C().vanilla()


class TestTwistedSync(unittest_twisted.SynchronousTestCase):
    def test_wait_for(self):
        C().wait_for()

    def test_run_in_reactor(self):
        C().run_in_reactor()

    def test_vanilla(self):
        C().vanilla()

The output of running it with trial on Python 2.7.8 (OS X) is as following:

test_t
  TestStdLib
    test_run_in_reactor ...                                                [OK]
    test_vanilla ...                                                    [ERROR]
    test_wait_for ...                                                   [ERROR]
  TestTwistedDefault
    test_run_in_reactor ...                                             [ERROR]
                                            [ERROR]
    test_vanilla ...                                                    [ERROR]
    test_wait_for ...                                                   [ERROR]
                                                  [ERROR]
  TestTwistedSync
    test_run_in_reactor ...                                                [OK]
    test_vanilla ...                                                    [ERROR]
    test_wait_for ...                                                   [ERROR]

===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/.pyenv/versions/2.7.8/lib/python2.7/unittest/case.py", line 329, in run
    testMethod()
  File "/Users/hynek/Projects/ssce/test_t.py", line 32, in test_vanilla
    C().vanilla()
  File "/Users/hynek/Projects/ssce/test_t.py", line 21, in vanilla
    raise Exception
exceptions.Exception: 

test_t.TestStdLib.test_vanilla
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/.pyenv/versions/2.7.8/lib/python2.7/unittest/case.py", line 329, in run
    testMethod()
  File "/Users/hynek/Projects/ssce/test_t.py", line 26, in test_wait_for
    C().wait_for()
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 461, in wrapper
    return eventual_result.wait(timeout)
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 229, in wait
    result = self._result(timeout)
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 193, in _result
    raise TimeoutError()
crochet._eventloop.TimeoutError: 

test_t.TestStdLib.test_wait_for
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/twisted/internet/defer.py", line 140, in maybeDeferred
    result = f(*args, **kw)
  File "/Users/hynek/Projects/ssce/test_t.py", line 18, in run_in_reactor
    raise Exception
exceptions.Exception: 

test_t.TestTwistedDefault.test_run_in_reactor
test_t.TestTwistedDefault.test_run_in_reactor
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/Projects/ssce/test_t.py", line 43, in test_vanilla
    C().vanilla()
  File "/Users/hynek/Projects/ssce/test_t.py", line 21, in vanilla
    raise Exception
exceptions.Exception: 

test_t.TestTwistedDefault.test_vanilla
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/Projects/ssce/test_t.py", line 37, in test_wait_for
    C().wait_for()
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 461, in wrapper
    return eventual_result.wait(timeout)
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 229, in wait
    result = self._result(timeout)
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 193, in _result
    raise TimeoutError()
crochet._eventloop.TimeoutError: 

test_t.TestTwistedDefault.test_wait_for
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/twisted/internet/defer.py", line 140, in maybeDeferred
    result = f(*args, **kw)
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 458, in run
    return function(*args, **kwargs)
  File "/Users/hynek/Projects/ssce/test_t.py", line 14, in wait_for
    raise Exception
exceptions.Exception: 

test_t.TestTwistedDefault.test_wait_for
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/Projects/ssce/test_t.py", line 54, in test_vanilla
    C().vanilla()
  File "/Users/hynek/Projects/ssce/test_t.py", line 21, in vanilla
    raise Exception
exceptions.Exception: 

test_t.TestTwistedSync.test_vanilla
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/Users/hynek/Projects/ssce/test_t.py", line 48, in test_wait_for
    C().wait_for()
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 461, in wrapper
    return eventual_result.wait(timeout)
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 229, in wait
    result = self._result(timeout)
  File "/Users/hynek/.virtualenvs/sscce/lib/python2.7/site-packages/crochet/_eventloop.py", line 193, in _result
    raise TimeoutError()
crochet._eventloop.TimeoutError: 

test_t.TestTwistedSync.test_wait_for
-------------------------------------------------------------------------------
Ran 9 tests in 3.020s

FAILED (errors=9, successes=2)

The output is the same on pypy.

I hope this is helpful.

@itamarst itamarst added the bug label Feb 6, 2015
@itamarst itamarst added this to the 1.4.0 milestone Feb 6, 2015
@itamarst
Copy link
Owner

itamarst commented Feb 8, 2015

I've never tested crochet on OS X... what does running the test suite tell you?

@hynek
Copy link
Author

hynek commented Feb 8, 2015

Tests pass skipping test_non_posix ... [SKIPPED] with a rather non-sensical skip message of SIGCHLD is a POSIX-specific issue.

@itamarst
Copy link
Owner

itamarst commented Feb 8, 2015

That message could be better, I guess, but that's expected output.

@itamarst
Copy link
Owner

itamarst commented Feb 8, 2015

OK, first problem with this example code is that you're calling no_setup(): that's wrong. Trial doesn't really run the reactor in a useful way, so you need crochet to run it for you.

@itamarst
Copy link
Owner

itamarst commented Feb 8, 2015

Once I switch no_setup() to setup() I get pretty much what is expected: no timeout errors, just Exceptions.

Also note that methods decorated with run_in_reactor are async, so if you want to extract the exception you have to do something like C().run_in_reactor().wait(timeout=1).

@itamarst
Copy link
Owner

itamarst commented Feb 8, 2015

If you change no_setup() to setup() does that fix your issue?

@hynek
Copy link
Author

hynek commented Feb 11, 2015

Yes and no: if I do that, I’ll get a fat traceback that reactor is already running.

If I do neither, I get:

Traceback (most recent call last):
  File "/Users/hynek/Work/txepp/tests/test_sync_wrapper.py", line 35, in test_domain_check
    ssp.domain_check(["test.com"])
  File "/Users/hynek/Work/txepp/.tox/py27/lib/python2.7/site-packages/crochet/_eventloop.py", line 459, in wrapper
    eventual_result = run()
  File "/Users/hynek/Work/txepp/.tox/py27/lib/python2.7/site-packages/crochet/_eventloop.py", line 421, in wrapper
    result = EventualResult(None, self._reactor)
exceptions.AttributeError: 'EventLoop' object has no attribute '_reactor'

@itamarst
Copy link
Owner

How are you running tests - what command line? What version of trial?

@itamarst itamarst modified the milestone: 1.4.0 May 6, 2015
@dpnova
Copy link

dpnova commented Jun 12, 2015

Somewhat seems to be related to what I'm seeing.

I'm actually trying to run tests in trial that test code which is decorated by wait_for.

Without any setup I get the error pasted by @hynek on the 11th Feb.

With no_setup() the decorator blocks regardless as to whether the decorated function returns a deferred or not. When I ctrl-c I get this traceback:

[ERROR]
Traceback (most recent call last):
  File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/mock.py", line 1201, in patched
    return func(*args, **keywargs)
  File "/home/dpn/workspace/inbox-api/inboxadmin/views/tests/test_home.py", line 28, in test_get_url_info
    return get_url_info("http://example.com")
  File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/crochet/_eventloop.py", line 461, in wrapper
    return eventual_result.wait(timeout)
  File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/crochet/_eventloop.py", line 229, in wait
    result = self._result(timeout)
  File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/crochet/_eventloop.py", line 189, in _result
    self._result_set.wait(timeout)
  File "/usr/lib64/python2.7/threading.py", line 621, in wait
    self.__cond.wait(timeout)
  File "/usr/lib64/python2.7/threading.py", line 359, in wait
    _sleep(delay)
exceptions.KeyboardInterrupt: 

If I use setup() I get the following debug traceback:

[ERROR]
Traceback (most recent call last):
Failure: twisted.trial.util.DirtyReactorAggregateError: Reactor was unclean.
DelayedCalls: (set twisted.internet.base.DelayedCall.debug = True to debug)
<DelayedCall 0x7f86ff2c53f8 [0.0817131996155s] called=0 cancelled=0 LoopingCall<0.1>(reapAllProcesses, *(), **{})()

traceback at creation: 

  File "/usr/lib64/python2.7/threading.py", line 783, in __bootstrap
    self.__bootstrap_inner()
      File "/usr/lib64/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
      File "/usr/lib64/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
      File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/crochet/_eventloop.py", line 382, in <lambda>
    target=lambda: self._reactor.run(installSignalHandlers=False),
      File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/twisted/internet/base.py", line 1192, in run
    self.mainLoop()
      File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/twisted/internet/base.py", line 1201, in mainLoop
    self.runUntilCurrent()
      File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/twisted/internet/base.py", line 797, in runUntilCurrent
    f(*a, **kw)
      File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/crochet/_eventloop.py", line 335, in _startReapingProcesses
    lc.start(0.1, False)
      File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/twisted/internet/task.py", line 175, in start
    self._reschedule()
      File "/home/dpn/.virtualenvs/inbox-api/lib/python2.7/site-packages/twisted/internet/task.py", line 243, in _reschedule
    self.call = self.clock.callLater(nextTime - currentTime, self)
>

Going to continue playing..

@itamarst
Copy link
Owner

I suggest not using twisted.trial.unittest.TestCase as base class when when writing crochet related tests, and specifically when you're testing the blocking APIs. Use unittest.TestCase or twisted.trial.unittest.SynchronousTestCase.

@dpnova
Copy link

dpnova commented Jun 12, 2015

Actually @itamarst I totally misread the doc about wrapped_function - that's working as expected with no_setup() now!

But, duly noted about not using the async test case.. thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants