python 3.8 support #19
4 changed files with 40 additions and 13 deletions
|
@ -1,7 +1,7 @@
|
||||||
sudo: required
|
sudo: required
|
||||||
dist: xenial
|
dist: xenial
|
||||||
language: python
|
language: python
|
||||||
python: "3.7"
|
python: "3.8"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
|
@ -16,7 +16,8 @@ jobs:
|
||||||
|
|
||||||
- &tests
|
- &tests
|
||||||
stage: test
|
stage: test
|
||||||
name: "Unit Tests w/ Python 3.7"
|
name: "Unit Tests w/ Python 3.8"
|
||||||
|
python: "3.8"
|
||||||
before_install:
|
before_install:
|
||||||
- pip install pylint coverage
|
- pip install pylint coverage
|
||||||
- pip install -e .[test]
|
- pip install -e .[test]
|
||||||
|
@ -27,6 +28,10 @@ jobs:
|
||||||
after_success:
|
after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
- <<: *tests
|
||||||
|
name: "Unit Tests w/ Python 3.7"
|
||||||
|
python: "3.7"
|
||||||
|
|
||||||
- <<: *tests
|
- <<: *tests
|
||||||
name: "Unit Tests w/ Python 3.6"
|
name: "Unit Tests w/ Python 3.6"
|
||||||
python: "3.6"
|
python: "3.6"
|
||||||
|
|
|
@ -3,10 +3,11 @@
|
||||||
[![PyPI version](https://badge.fury.io/py/aioupnp.svg)](https://badge.fury.io/py/aioupnp)
|
[![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.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.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
|
# 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
|
## Supported devices
|
||||||
DD-WRT
|
DD-WRT
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -25,6 +25,7 @@ setup(
|
||||||
"License :: OSI Approved :: MIT License",
|
"License :: OSI Approved :: MIT License",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
"Topic :: System :: Networking",
|
"Topic :: System :: Networking",
|
||||||
"Topic :: Communications :: File Sharing"
|
"Topic :: Communications :: File Sharing"
|
||||||
],
|
],
|
||||||
|
@ -35,7 +36,8 @@ setup(
|
||||||
packages=find_packages(exclude=('tests',)),
|
packages=find_packages(exclude=('tests',)),
|
||||||
entry_points={'console_scripts': console_scripts},
|
entry_points={'console_scripts': console_scripts},
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'netifaces', 'defusedxml'
|
'netifaces',
|
||||||
|
'defusedxml'
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
'test': (
|
'test': (
|
||||||
|
|
|
@ -2,6 +2,7 @@ import asyncio
|
||||||
import unittest
|
import unittest
|
||||||
import contextlib
|
import contextlib
|
||||||
import socket
|
import socket
|
||||||
|
from typing import Tuple, Optional, Any
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
from unittest.case import _Outcome
|
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 {}
|
tcp_replies = tcp_replies or {}
|
||||||
|
|
||||||
async def create_connection(protocol_factory, host=None, port=None):
|
async def create_connection(protocol_factory, host=None, port=None):
|
||||||
def write(p: asyncio.Protocol):
|
def get_write(p: asyncio.Protocol):
|
||||||
def _write(data):
|
def _write(data):
|
||||||
sent_tcp_packets.append(data)
|
sent_tcp_packets.append(data)
|
||||||
if data in tcp_replies:
|
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
|
return _write
|
||||||
|
|
||||||
protocol = protocol_factory()
|
protocol = protocol_factory()
|
||||||
transport = asyncio.Transport(extra={'socket': mock.Mock(spec=socket.socket)})
|
write = get_write(protocol)
|
||||||
transport.close = lambda: None
|
|
||||||
transport.write = 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)
|
protocol.connection_made(transport)
|
||||||
return transport, protocol
|
return transport, protocol
|
||||||
|
|
||||||
async def create_datagram_endpoint(proto_lam, sock=None):
|
async def create_datagram_endpoint(proto_lam, sock=None):
|
||||||
def sendto(p: asyncio.DatagramProtocol):
|
def get_sendto(p: asyncio.DatagramProtocol):
|
||||||
def _sendto(data, addr):
|
def _sendto(data, addr):
|
||||||
sent_udp_packets.append(data)
|
sent_udp_packets.append(data)
|
||||||
loop.call_later(udp_delay_reply, p.datagram_received, 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
|
return _sendto
|
||||||
|
|
||||||
protocol = proto_lam()
|
protocol = proto_lam()
|
||||||
transport = asyncio.DatagramTransport(extra={'socket': mock_sock})
|
sendto = get_sendto(protocol)
|
||||||
transport.close = lambda: mock_sock.close()
|
|
||||||
mock_sock.sendto = sendto(protocol)
|
class MockDatagramTransport(asyncio.DatagramTransport):
|
||||||
transport.sendto = mock_sock.sendto
|
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)
|
protocol.connection_made(transport)
|
||||||
return transport, protocol
|
return transport, protocol
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue