From d70618864ae1a2a0c3b39d5f0125b219de40edf9 Mon Sep 17 00:00:00 2001 From: Jack Robison Date: Fri, 25 Oct 2019 14:50:33 -0400 Subject: [PATCH] test python 3.8 support --- .travis.yml | 9 +++++++-- README.md | 3 ++- setup.py | 4 +++- tests/__init__.py | 37 ++++++++++++++++++++++++++++--------- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index db357b9..13bb672 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: required dist: xenial language: python -python: "3.7" +python: "3.8" jobs: include: @@ -16,7 +16,8 @@ jobs: - &tests stage: test - name: "Unit Tests w/ Python 3.7" + name: "Unit Tests w/ Python 3.8" + python: "3.8" before_install: - pip install pylint coverage - pip install -e .[test] @@ -27,6 +28,10 @@ jobs: after_success: - bash <(curl -s https://codecov.io/bash) + - <<: *tests + name: "Unit Tests w/ Python 3.7" + python: "3.7" + - <<: *tests name: "Unit Tests w/ Python 3.6" python: "3.6" diff --git a/README.md b/README.md index 5420311..4757f0e 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,11 @@ [![PyPI version](https://badge.fury.io/py/aioupnp.svg)](https://badge.fury.io/py/aioupnp) [![Python 3.6](https://img.shields.io/badge/python-3.6-blue.svg)](https://www.python.org/downloads/release/python-360/) [![Python 3.7](https://img.shields.io/badge/python-3.7-blue.svg)](https://www.python.org/downloads/release/python-370/) +[![Python 3.8](https://img.shields.io/badge/python-3.8-blue.svg)](https://www.python.org/downloads/release/python-380/) # UPnP for asyncio -`aioupnp` is a python 3.6/7 library and command line tool to interact with UPnP gateways using asyncio. `aioupnp` requires the `netifaces` module. +`aioupnp` is a python 3.6-8 library and command line tool to interact with UPnP gateways using asyncio. `aioupnp` requires the `netifaces` module. ## Supported devices DD-WRT diff --git a/setup.py b/setup.py index 9eff28d..145fcb4 100644 --- a/setup.py +++ b/setup.py @@ -25,6 +25,7 @@ setup( "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: System :: Networking", "Topic :: Communications :: File Sharing" ], @@ -35,7 +36,8 @@ setup( packages=find_packages(exclude=('tests',)), entry_points={'console_scripts': console_scripts}, install_requires=[ - 'netifaces', 'defusedxml' + 'netifaces', + 'defusedxml' ], extras_require={ 'test': ( diff --git a/tests/__init__.py b/tests/__init__.py index 62f39b9..27ad4f5 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -2,6 +2,7 @@ import asyncio import unittest import contextlib import socket +from typing import Tuple, Optional, Any from unittest import mock from unittest.case import _Outcome @@ -25,7 +26,7 @@ def mock_tcp_and_udp(loop, udp_expected_addr=None, udp_replies=None, udp_delay_r tcp_replies = tcp_replies or {} async def create_connection(protocol_factory, host=None, port=None): - def write(p: asyncio.Protocol): + def get_write(p: asyncio.Protocol): def _write(data): sent_tcp_packets.append(data) if data in tcp_replies: @@ -41,14 +42,21 @@ def mock_tcp_and_udp(loop, udp_expected_addr=None, udp_replies=None, udp_delay_r return _write protocol = protocol_factory() - transport = asyncio.Transport(extra={'socket': mock.Mock(spec=socket.socket)}) - transport.close = lambda: None - transport.write = write(protocol) + write = get_write(protocol) + + class MockTransport(asyncio.Transport): + def close(self): + return + + def write(self, data): + write(data) + + transport = MockTransport(extra={'socket': mock.Mock(spec=socket.socket)}) protocol.connection_made(transport) return transport, protocol async def create_datagram_endpoint(proto_lam, sock=None): - def sendto(p: asyncio.DatagramProtocol): + def get_sendto(p: asyncio.DatagramProtocol): def _sendto(data, addr): sent_udp_packets.append(data) loop.call_later(udp_delay_reply, p.datagram_received, data, @@ -63,10 +71,21 @@ def mock_tcp_and_udp(loop, udp_expected_addr=None, udp_replies=None, udp_delay_r return _sendto protocol = proto_lam() - transport = asyncio.DatagramTransport(extra={'socket': mock_sock}) - transport.close = lambda: mock_sock.close() - mock_sock.sendto = sendto(protocol) - transport.sendto = mock_sock.sendto + sendto = get_sendto(protocol) + + class MockDatagramTransport(asyncio.DatagramTransport): + def __init__(self, sock): + super().__init__(extra={'socket': sock}) + self._sock = sock + + def close(self): + self._sock.close() + return + + def sendto(self, data: Any, addr: Optional[Tuple[str, int]] = ...) -> None: + sendto(data, addr) + + transport = MockDatagramTransport(mock_sock) protocol.connection_made(transport) return transport, protocol