Skip to content

Commit

Permalink
Merge pull request #61 from ggravlingen/fix_api_return_type
Browse files Browse the repository at this point in the history
Ensure consistent API return type (breaking)
  • Loading branch information
Patrik authored Oct 14, 2017
2 parents f61c75b + 9544a67 commit 4cf0c35
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 39 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sudo: false
matrix:
fast_finish: true
include:
- python: "3.4.2"
- python: "3.4.4"
env: TOXENV=py34
- python: "3.5"
env: TOXENV=py35
Expand All @@ -14,6 +14,8 @@ cache:
directories:
- $HOME/.cache/pip
install:
- pip install --upgrade pip setuptools wheel cython
- pip install -r requirements.txt
- pip install -r requirements_test.txt
- python3 setup.py develop
language: python
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ RUN apt-get update -y && \
RUN mkdir -p /usr/src/app /usr/src/build
WORKDIR /usr/src/build

RUN python3 -m pip install cython
RUN python3 -m pip install --upgrade pip setuptools wheel cython

COPY ./script/install-coap-client.sh install-coap-client.sh
RUN ./install-coap-client.sh

COPY ./script/install-aiocoap.sh install-aiocoap.sh
RUN ./install-aiocoap.sh
COPY requirements.txt requirements.txt
RUN python3 -m pip install -r requirements.txt

WORKDIR /usr/src/app
ENV LANG=C.UTF-8
Expand Down
2 changes: 1 addition & 1 deletion example_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def run():

devices_command = gateway.get_devices()
devices_commands = yield from api(devices_command)
devices = yield from api(*devices_commands)
devices = yield from api(devices_commands)

lights = [dev for dev in devices if dev.has_light_control]

Expand Down
2 changes: 1 addition & 1 deletion example_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def run():

devices_command = gateway.get_devices()
devices_commands = api(devices_command)
devices = api(*devices_commands)
devices = api(devices_commands)

lights = [dev for dev in devices if dev.has_light_control]

Expand Down
16 changes: 4 additions & 12 deletions pytradfri/api/aiocoap_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ def _get_psk(self, host, port):
tinydtls.DTLSSecurityStore = PatchedDTLSSecurityStore


def _patched_datagram_received(self, data, addr):
self.parent._dtls_socket.handleMessage(self.parent._connection, data, 0)


tinydtls.DTLSClientConnection.SingleConnection.datagram_received = \
_patched_datagram_received


@asyncio.coroutine
def api_factory(host, security_code, loop=None):
"""Generate a request method."""
Expand Down Expand Up @@ -75,7 +67,7 @@ def _get_response(msg):
protocol = yield from _get_protocol()
pr = protocol.request(msg)
r = yield from pr.response
return (pr, r)
return pr, r
except ConstructionRenderableError as e:
raise ClientError("There was an error with the request.", e)
except RequestTimedOut as e:
Expand Down Expand Up @@ -119,10 +111,10 @@ def _execute(api_command):
return api_command.result

@asyncio.coroutine
def request(*api_commands):
def request(api_commands):
"""Make a request."""
if len(api_commands) == 1:
result = yield from _execute(api_commands[0])
if not isinstance(api_commands, list):
result = yield from _execute(api_commands)
return result

commands = (_execute(api_command) for api_command in api_commands)
Expand Down
4 changes: 2 additions & 2 deletions pytradfri/api/libcoap_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ def _execute(api_command):
api_command.result = _process_output(return_value, parse_json)
return api_command.result

def request(*api_commands):
def request(api_commands):
"""Make a request."""
if len(api_commands) == 1:
if not isinstance(api_commands, list):
return _execute(api_commands[0])

command_results = []
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
https://github.com/chrysn/aiocoap/archive/0df6a1e44582de99ae944b6a7536d08e2a612e8f.zip
https://github.com/chrysn/aiocoap/archive/3286f48f0b949901c8b5c04c0719dc54ab63d431.zip
DTLSSocket==0.1.3
2 changes: 1 addition & 1 deletion requirements_test.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pytest
pytest>=3.2.3
flake8
14 changes: 0 additions & 14 deletions script/install-aiocoap.sh

This file was deleted.

6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from setuptools import setup, find_packages

VERSION = "2.2.3"
VERSION = "3.0"
DOWNLOAD_URL = \
'https://github.com/ggravlingen/pytradfri/archive/{}.zip'.format(VERSION)

EXTRAS_REQUIRE = {
'async': ['aiocoap >= 0.3']
'async': ['aiocoap >= 0.3', 'DTLSSocket >= 0.1.3']
}

DEP_LINKS = [
"https://github.com/chrysn/aiocoap/archive/0df6a1e44582de99ae944b6a7536d08e2a612e8f.zip#egg=aiocoap-0.3"
"https://github.com/chrysn/aiocoap/archive/3286f48f0b949901c8b5c04c0719dc54ab63d431.zip#egg=aiocoap-0.3"
]

PACKAGES = find_packages(exclude=['tests', 'tests.*'])
Expand Down
80 changes: 80 additions & 0 deletions tests/api/test_aiocoap_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Test API utilities."""
import asyncio
import functools

from pytradfri.api.aiocoap_api import api_factory
from pytradfri.command import Command


def async_test(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
coro = asyncio.coroutine(f)
future = coro(*args, **kwargs)
loop = asyncio.get_event_loop()
loop.run_until_complete(future)
return wrapper


class MockCode:
@property
def is_successful(self):
return True


class MockResponse:
@property
def code(self):
return MockCode()

@property
def payload(self):
return '{}'.encode('utf-8')


class MockProtocol:
@asyncio.coroutine
def mock_response(self):
return MockResponse()

@property
def response(self):
return self.mock_response()


class MockContext:
def request(self, arg):
return MockProtocol()


@asyncio.coroutine
def mock_create_context(loop):
return MockContext()


@async_test
def test_request_returns_single(monkeypatch):
monkeypatch.setattr('aiocoap.Context.create_client_context',
mock_create_context)

api = yield from api_factory('127.0.0.1', 'key')

command = Command('', '')

response = yield from api(command)

assert type(response) != list


@async_test
def test_request_returns_list(monkeypatch):
monkeypatch.setattr('aiocoap.Context.create_client_context',
mock_create_context)

api = yield from api_factory('127.0.0.1', 'key')

command = Command('', '')

response = yield from api([command, command, command])

assert type(response) == list

0 comments on commit 4cf0c35

Please sign in to comment.