Skip to content

Commit

Permalink
Fixes pull.simple.RunOnce by correctly deciding to call sync/async po…
Browse files Browse the repository at this point in the history
…ll()
  • Loading branch information
HazardDede committed Apr 29, 2020
1 parent caff206 commit 3c02adb
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 42 deletions.
10 changes: 8 additions & 2 deletions pnp/plugins/pull/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import time
from datetime import datetime

import asyncio
from box import Box

from . import PullBase, Polling, AsyncPullBase
Expand Down Expand Up @@ -122,13 +123,18 @@ def __init__(self, poll=None, **kwargs):

@property
def can_exit(self) -> bool:
return True
return True # pragma: no cover

async def async_pull(self) -> None:
if not self.wrapped:
self.notify({}) # Just notify about an empty dict
else:
self.notify(self.wrapped.poll())
if self.wrapped.supports_async_poll:
res = await self.wrapped.async_poll()
else:
loop = asyncio.get_event_loop()
res = await loop.run_in_executor(None, self.wrapped.poll)
self.notify(res)


class Repeat(AsyncPullBase):
Expand Down
Empty file added tests/dummies/__init__.py
Empty file.
36 changes: 36 additions & 0 deletions tests/dummies/polling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from pnp.plugins.pull import Polling, AsyncPolling, PullBase


class SyncPollingDummy(Polling):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def poll(self):
return 42


class AsyncPollingDummy(AsyncPolling):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def poll(self):
raise Exception("Don't call the sync version of pull")

async def async_poll(self):
return 42


class ErrorPollingDummy(Polling):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def poll(self):
raise Exception("Crash on purpose!")


class NoPollingDummy(PullBase):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def poll(self):
raise Exception("Do not call me!")
65 changes: 65 additions & 0 deletions tests/plugins/pull/test_simple_run_once.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import time

import pytest

from pnp.plugins.pull.simple import RunOnce
from . import make_runner, start_runner


def test_init_with_no_poll():
with pytest.raises(TypeError, match="The component to wrap has to be a polling component"):
RunOnce(name='pytest', poll={'plugin': 'tests.dummies.polling.NoPollingDummy'})


def test_pull_without_wrapped_poll():
events = []
def callback(plugin, payload):
events.append(payload)

dut = RunOnce(name='pytest')
runner = make_runner(dut, callback)
with start_runner(runner):
time.sleep(0.01)

assert events == [{}]


@pytest.mark.asyncio
async def test_async_pull_without_wrapped_poll():
events = []
def callback(plugin, payload):
events.append(payload)

dut = RunOnce(name='pytest')
runner = make_runner(dut, callback)
with start_runner(runner):
time.sleep(0.01)

assert events == [{}]


@pytest.mark.asyncio
async def test_async_pull_with_sync_wrapped_poll():
events = []
def callback(plugin, payload):
events.append(payload)

dut = RunOnce(name='pytest', poll={'plugin': 'tests.dummies.polling.SyncPollingDummy'})
runner = make_runner(dut, callback)
with start_runner(runner):
time.sleep(0.01)

assert events == [42]


@pytest.mark.asyncio
async def test_async_pull_with_async_wrapped_poll():
events = []
def callback(plugin, payload):
events.append(payload)

dut = RunOnce(name='pytest', poll={'plugin': 'tests.dummies.polling.AsyncPollingDummy'})
dut.on_payload = callback
await dut.async_pull()

assert events == [42]
46 changes: 6 additions & 40 deletions tests/plugins/pull/test_trigger_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,10 @@
import pytest
import requests

from pnp.plugins.pull import trigger, PullBase
from pnp.plugins.pull import AsyncPolling, Polling

from pnp.plugins.pull import trigger
from . import make_runner, start_runner


class DummyPoll(Polling):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def poll(self):
return 42


class AsyncDummyPoll(AsyncPolling):
def __init__(self, **kwargs):
super().__init__(**kwargs)

async def async_poll(self):
return 42


class ErrorneousDummyPoll(Polling):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def poll(self):
raise Exception("Crash on purpose!")


class NonPollingDummy(PullBase):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def poll(self):
raise Exception("Do not call me!")


def get_free_tcp_port():
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp.bind(('', 0))
Expand All @@ -52,7 +18,7 @@ def get_free_tcp_port():

def test_init_endpoint():
free_port = get_free_tcp_port()
wrapped = {'plugin': 'tests.plugins.pull.test_trigger_web.DummyPoll'}
wrapped = {'plugin': 'tests.dummies.polling.SyncPollingDummy'}
dut = trigger.Web(name='pytest', port=free_port, poll=wrapped)
assert dut.endpoint == '/trigger'
dut = trigger.Web(name='pytest', port=free_port, poll=wrapped, endpoint='trigger')
Expand All @@ -67,16 +33,16 @@ def test_init_endpoint():

def test_init_non_polling_pull():
free_port = get_free_tcp_port()
wrapped = {'plugin': 'tests.plugins.pull.test_trigger_web.NonPollingDummy'}
wrapped = {'plugin': 'tests.dummies.polling.NoPollingDummy'}
with pytest.raises(TypeError) as tex:
trigger.Web(name='pytest', port=free_port, poll=wrapped)

assert "The component to wrap has to be a polling component" in str(tex)


@pytest.mark.parametrize("wrapped", [
{'plugin': 'tests.plugins.pull.test_trigger_web.DummyPoll'},
{'plugin': 'tests.plugins.pull.test_trigger_web.AsyncDummyPoll'}
{'plugin': 'tests.dummies.polling.SyncPollingDummy'},
{'plugin': 'tests.dummies.polling.AsyncPollingDummy'}
])
def test_pull(wrapped):
events = []
Expand All @@ -103,7 +69,7 @@ def callback(plugin, payload):

def test_pull_for_error():
free_port = get_free_tcp_port()
wrapped = {'plugin': 'tests.plugins.pull.test_trigger_web.ErrorneousDummyPoll'}
wrapped = {'plugin': 'tests.dummies.polling.ErrorPollingDummy'}

dut = trigger.Web(name='pytest', port=free_port, poll=wrapped)
runner = make_runner(dut, lambda: None)
Expand Down

0 comments on commit 3c02adb

Please sign in to comment.