Loading .pre-commit-config.yaml +1 −1 Original line number Diff line number Diff line Loading @@ -85,4 +85,4 @@ repos: - id: mypy args: [--config=setup.cfg] additional_dependencies: [anyio, trio-typing] exclude: setup\.py exclude: setup\.py|test_.* setup.cfg +11 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ packages = find: setup_requires = setuptools >= 40.6 install_requires = anyio >=1.0 anyio ~=3.0 [options.packages.find] include = Loading Loading @@ -88,6 +88,7 @@ force_single_line = true [mypy] strict = true warn_unused_configs = True warn_unreachable = true implicit_reexport = true follow_imports = skip Loading @@ -109,6 +110,7 @@ per-file-ignores = tests/*.py: D100, C801 **/__init__.py: D104, F401, F403 **/__main__.py: D100, E702 **/_*.py: D ignore = ;[ Missing docstring in public method ] Loading Loading @@ -149,6 +151,14 @@ ignore = ; Prefer B950 implementation E501 ;[ multiple statements on one line (colon) ] E701 ;[ unexpected number of spaces at start of statement line ] ;[ unexpected number of tabs and spaces at start of statement line ] ; Don't want spaces... ET122 ET128 ;[ Line break before binary operator ] ; Not considered current W503 Loading tests/unit/_anyio.py +10 −9 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import sys from functools import wraps from typing import Any from typing import Callable from typing import Coroutine from typing import Tuple from unittest import mock Loading @@ -27,23 +28,23 @@ import anyio py_version = sys.version_info[:2] AnyFunc = Callable[..., Any] Decorator = Callable[[AnyFunc], AnyFunc] AsyncTestFunc = Callable[..., Coroutine[Any, Any, None]] TestFunc = Callable[..., None] def with_anyio(timeout: int = 10) -> Decorator: def with_anyio(timeout: int = 10) -> Callable[[AsyncTestFunc], TestFunc]: """ Create a wrapping decorator to run asynchronous test functions """ def decorator(testfunc: AnyFunc) -> AnyFunc: async def test_async_wrapper(args: Tuple[Any]) -> Any: async with anyio.fail_after(timeout): return await testfunc(*args) def decorator(testfunc: AsyncTestFunc) -> TestFunc: async def test_async_wrapper(tc: TestCase, args: Tuple[mock.Mock]) -> None: with anyio.fail_after(timeout): await testfunc(tc, *args) @wraps(testfunc) def test_wrapper(*args: Any) -> Any: return anyio.run(test_async_wrapper, args) def test_wrapper(*args: mock.Mock) -> None: anyio.run(test_async_wrapper, args) return test_wrapper Loading tests/unit/test_base_client.py +84 −91 Original line number Diff line number Diff line Loading @@ -26,9 +26,13 @@ from wpa_supplicant import errors from wpa_supplicant.client import base @mock.patch("wpa_supplicant.util.connect_unix_datagram", new_callable=anyio_mock.AsyncMock) @mock.patch( "wpa_supplicant.client.base.BaseClient.send_command", new_callable=anyio_mock.AsyncMock, "wpa_supplicant.client.base.connect_unix_datagram", new_callable=anyio_mock.AsyncMock, ) @mock.patch( "wpa_supplicant.client.base.BaseClient.send_command", new_callable=anyio_mock.AsyncMock, ) class ConnectTests(unittest.TestCase): """ Loading Loading @@ -74,12 +78,10 @@ class SendMessageTests(unittest.TestCase): """ def setUp(self): async def _make_client(): return base.BaseClient() self.client = client = anyio.run(_make_client) client.sock = anyio_mock.AsyncMock() client.sock.send.side_effect = len self.client = client = base.BaseClient() client.sock = anyio_mock.AsyncMock(spec=anyio.abc.SocketStream) client.sock.send.return_value = None assert isinstance(client.sock, anyio.abc.SocketStream) @anyio_mock.with_anyio() async def test_simple(self): Loading @@ -87,7 +89,7 @@ class SendMessageTests(unittest.TestCase): Check that a response is processed after a command """ async with self.client as client: client.sock.recv.return_value = b"OK" client.sock.receive.return_value = b"OK" assert await client.send_command("SOME_COMMAND") is None @anyio_mock.with_anyio() Loading @@ -96,7 +98,7 @@ class SendMessageTests(unittest.TestCase): Check that an alternate expected response is processed """ async with self.client as client: client.sock.recv.return_value = b"PONG" client.sock.receive.return_value = b"PONG" assert await client.send_command("PING", expect="PONG") is None @anyio_mock.with_anyio() Loading @@ -105,7 +107,7 @@ class SendMessageTests(unittest.TestCase): Check that an unexpected response raises an UnexpectedResponseError """ async with self.client as client: client.sock.recv.return_value = b"DING" client.sock.receive.return_value = b"DING" with self.assertRaises(errors.UnexpectedResponseError): await client.send_command("PING") with self.assertRaises(errors.UnexpectedResponseError): Loading @@ -117,7 +119,7 @@ class SendMessageTests(unittest.TestCase): Check that a response is passed through a converter if given """ async with self.client as client: client.sock.recv.return_value = b"FOO\nBAR\nBAZ\n" client.sock.receive.return_value = b"FOO\nBAR\nBAZ\n" self.assertListEqual( await client.send_command( "SOME_COMMAND", convert=lambda x: x.splitlines(), Loading @@ -131,7 +133,7 @@ class SendMessageTests(unittest.TestCase): Check that 'convert' overrides 'expect' """ async with self.client as client: client.sock.recv.return_value = b"FOO\nBAR\nBAZ\n" client.sock.receive.return_value = b"FOO\nBAR\nBAZ\n" self.assertListEqual( await client.send_command( "SOME_COMMAND", convert=lambda x: x.splitlines(), expect="PONG", Loading @@ -145,7 +147,7 @@ class SendMessageTests(unittest.TestCase): Check that a response of 'FAIL' causes CommandFailed to be raised """ async with self.client as client: client.sock.recv.return_value = b"FAIL" client.sock.receive.return_value = b"FAIL" with self.assertRaises(errors.CommandFailed): await client.send_command("SOME_COMMAND") Loading @@ -155,27 +157,17 @@ class SendMessageTests(unittest.TestCase): Check that a response of 'UNKNOWN COMMAND' causes ValueError to be raised """ async with self.client as client: client.sock.recv.return_value = b"UNKNOWN COMMAND" client.sock.receive.return_value = b"UNKNOWN COMMAND" with self.assertRaises(ValueError): await client.send_command("SOME_COMMAND") @anyio_mock.with_anyio() async def test_simple_too_large(self): """ Check that MessageTooLargeError is raised if send() reports an incomplete send """ async with self.client as client: client.sock.send.side_effect = lambda b: len(b) / 2 with self.assertRaises(errors.MessageTooLargeError): await client.send_command("SOME_COMMAND") @anyio_mock.with_anyio() async def test_interleaved(self): """ Check that messages are processed alongside replies """ async with self.client as client: client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"<2>SOME-MESSAGE", b"<1>SOME-OTHER-MESSAGE with|args", b"OK", Loading @@ -189,7 +181,7 @@ class SendMessageTests(unittest.TestCase): Check that unexpected replies are logged cleanly """ async with self.client as client: client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"OK", # Response to "ATTACH" b"UNEXPECTED1", b"UNEXPECTED2", Loading @@ -205,20 +197,18 @@ class EventTests(unittest.TestCase): """ def setUp(self): async def _make_client(): return base.BaseClient() self.client = client = anyio.run(_make_client) self.client = client = base.BaseClient() client.sock = anyio_mock.AsyncMock() client.sock.send.side_effect = len client.sock.send.return_value = None @anyio_mock.with_anyio() async def test_simple(self): """ Check that an awaited message is returned when is arrives """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"OK", # Respond to ATTACH b"<2>CTRL-EVENT-EXAMPLE", b"OK", # Respond to DETACH Loading @@ -233,8 +223,9 @@ class EventTests(unittest.TestCase): """ Check that an awaited messages is returned when it arrives between others """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"OK", # Respond to ATTACH b"<1>OTHER-MESSAGE", b"<2>CTRL-EVENT-OTHER", Loading @@ -252,8 +243,9 @@ class EventTests(unittest.TestCase): """ Check that the first of several awaited events is returned """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"OK", # Respond to ATTACH b"<1>OTHER-MESSAGE", b"<2>CTRL-EVENT-OTHER", Loading @@ -274,8 +266,9 @@ class EventTests(unittest.TestCase): """ Check that messages are processed as well as replies """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"<1>OTHER-MESSAGE", b"OK", # Respond to SOME_COMMAND b"OK", # Respond to ATTACH Loading tests/unit/test_interfaces_client.py +6 −11 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ Test cases for wpa_supplicant.client.interfaces.InterfaceClient import unittest from unittest.mock import call import anyio from tests.unit import _anyio as anyio_mock from wpa_supplicant import config from wpa_supplicant.client import interfaces Loading @@ -32,12 +30,9 @@ class MethodsTests(unittest.TestCase): """ def setUp(self): async def _make_client(): return interfaces.InterfaceClient() self.client = client = anyio.run(_make_client) self.client = client = interfaces.InterfaceClient() client.sock = anyio_mock.AsyncMock() client.sock.send.side_effect = len client.sock.send.return_value = None @anyio_mock.with_anyio() async def test_scan(self): Loading @@ -45,7 +40,7 @@ class MethodsTests(unittest.TestCase): Check that a scan command waits for a notification then terminates correctly """ async with self.client as client: client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"OK", # Response to "ATTACH" b"OK", # Response to "SCAN" b"<3>CTRL-EVENT-SCAN-RESULTS", Loading @@ -65,7 +60,7 @@ class MethodsTests(unittest.TestCase): Check that set_network sends values to the daemon and raises TypeError for bad types """ async with self.client as client: client.sock.recv.return_value = b"OK" client.sock.receive.return_value = b"OK" send = client.sock.send with self.subTest("good string"): Loading @@ -79,7 +74,7 @@ class MethodsTests(unittest.TestCase): send.reset_mock() with self.subTest("good enum"): await client.set_network("0", "key_mgmt", config.KeyManagementValue.WPA_PSK) await client.set_network("0", "key_mgmt", config.KeyManagementValue.WPA_PSK) # type: ignore send.assert_called_once_with(b"SET_NETWORK 0 key_mgmt WPA-PSK") send.reset_mock() Loading @@ -106,7 +101,7 @@ class MethodsTests(unittest.TestCase): """ async with self.client as client: send = client.sock.send client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"0", b"OK", b"OK", Loading Loading
.pre-commit-config.yaml +1 −1 Original line number Diff line number Diff line Loading @@ -85,4 +85,4 @@ repos: - id: mypy args: [--config=setup.cfg] additional_dependencies: [anyio, trio-typing] exclude: setup\.py exclude: setup\.py|test_.*
setup.cfg +11 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ packages = find: setup_requires = setuptools >= 40.6 install_requires = anyio >=1.0 anyio ~=3.0 [options.packages.find] include = Loading Loading @@ -88,6 +88,7 @@ force_single_line = true [mypy] strict = true warn_unused_configs = True warn_unreachable = true implicit_reexport = true follow_imports = skip Loading @@ -109,6 +110,7 @@ per-file-ignores = tests/*.py: D100, C801 **/__init__.py: D104, F401, F403 **/__main__.py: D100, E702 **/_*.py: D ignore = ;[ Missing docstring in public method ] Loading Loading @@ -149,6 +151,14 @@ ignore = ; Prefer B950 implementation E501 ;[ multiple statements on one line (colon) ] E701 ;[ unexpected number of spaces at start of statement line ] ;[ unexpected number of tabs and spaces at start of statement line ] ; Don't want spaces... ET122 ET128 ;[ Line break before binary operator ] ; Not considered current W503 Loading
tests/unit/_anyio.py +10 −9 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import sys from functools import wraps from typing import Any from typing import Callable from typing import Coroutine from typing import Tuple from unittest import mock Loading @@ -27,23 +28,23 @@ import anyio py_version = sys.version_info[:2] AnyFunc = Callable[..., Any] Decorator = Callable[[AnyFunc], AnyFunc] AsyncTestFunc = Callable[..., Coroutine[Any, Any, None]] TestFunc = Callable[..., None] def with_anyio(timeout: int = 10) -> Decorator: def with_anyio(timeout: int = 10) -> Callable[[AsyncTestFunc], TestFunc]: """ Create a wrapping decorator to run asynchronous test functions """ def decorator(testfunc: AnyFunc) -> AnyFunc: async def test_async_wrapper(args: Tuple[Any]) -> Any: async with anyio.fail_after(timeout): return await testfunc(*args) def decorator(testfunc: AsyncTestFunc) -> TestFunc: async def test_async_wrapper(tc: TestCase, args: Tuple[mock.Mock]) -> None: with anyio.fail_after(timeout): await testfunc(tc, *args) @wraps(testfunc) def test_wrapper(*args: Any) -> Any: return anyio.run(test_async_wrapper, args) def test_wrapper(*args: mock.Mock) -> None: anyio.run(test_async_wrapper, args) return test_wrapper Loading
tests/unit/test_base_client.py +84 −91 Original line number Diff line number Diff line Loading @@ -26,9 +26,13 @@ from wpa_supplicant import errors from wpa_supplicant.client import base @mock.patch("wpa_supplicant.util.connect_unix_datagram", new_callable=anyio_mock.AsyncMock) @mock.patch( "wpa_supplicant.client.base.BaseClient.send_command", new_callable=anyio_mock.AsyncMock, "wpa_supplicant.client.base.connect_unix_datagram", new_callable=anyio_mock.AsyncMock, ) @mock.patch( "wpa_supplicant.client.base.BaseClient.send_command", new_callable=anyio_mock.AsyncMock, ) class ConnectTests(unittest.TestCase): """ Loading Loading @@ -74,12 +78,10 @@ class SendMessageTests(unittest.TestCase): """ def setUp(self): async def _make_client(): return base.BaseClient() self.client = client = anyio.run(_make_client) client.sock = anyio_mock.AsyncMock() client.sock.send.side_effect = len self.client = client = base.BaseClient() client.sock = anyio_mock.AsyncMock(spec=anyio.abc.SocketStream) client.sock.send.return_value = None assert isinstance(client.sock, anyio.abc.SocketStream) @anyio_mock.with_anyio() async def test_simple(self): Loading @@ -87,7 +89,7 @@ class SendMessageTests(unittest.TestCase): Check that a response is processed after a command """ async with self.client as client: client.sock.recv.return_value = b"OK" client.sock.receive.return_value = b"OK" assert await client.send_command("SOME_COMMAND") is None @anyio_mock.with_anyio() Loading @@ -96,7 +98,7 @@ class SendMessageTests(unittest.TestCase): Check that an alternate expected response is processed """ async with self.client as client: client.sock.recv.return_value = b"PONG" client.sock.receive.return_value = b"PONG" assert await client.send_command("PING", expect="PONG") is None @anyio_mock.with_anyio() Loading @@ -105,7 +107,7 @@ class SendMessageTests(unittest.TestCase): Check that an unexpected response raises an UnexpectedResponseError """ async with self.client as client: client.sock.recv.return_value = b"DING" client.sock.receive.return_value = b"DING" with self.assertRaises(errors.UnexpectedResponseError): await client.send_command("PING") with self.assertRaises(errors.UnexpectedResponseError): Loading @@ -117,7 +119,7 @@ class SendMessageTests(unittest.TestCase): Check that a response is passed through a converter if given """ async with self.client as client: client.sock.recv.return_value = b"FOO\nBAR\nBAZ\n" client.sock.receive.return_value = b"FOO\nBAR\nBAZ\n" self.assertListEqual( await client.send_command( "SOME_COMMAND", convert=lambda x: x.splitlines(), Loading @@ -131,7 +133,7 @@ class SendMessageTests(unittest.TestCase): Check that 'convert' overrides 'expect' """ async with self.client as client: client.sock.recv.return_value = b"FOO\nBAR\nBAZ\n" client.sock.receive.return_value = b"FOO\nBAR\nBAZ\n" self.assertListEqual( await client.send_command( "SOME_COMMAND", convert=lambda x: x.splitlines(), expect="PONG", Loading @@ -145,7 +147,7 @@ class SendMessageTests(unittest.TestCase): Check that a response of 'FAIL' causes CommandFailed to be raised """ async with self.client as client: client.sock.recv.return_value = b"FAIL" client.sock.receive.return_value = b"FAIL" with self.assertRaises(errors.CommandFailed): await client.send_command("SOME_COMMAND") Loading @@ -155,27 +157,17 @@ class SendMessageTests(unittest.TestCase): Check that a response of 'UNKNOWN COMMAND' causes ValueError to be raised """ async with self.client as client: client.sock.recv.return_value = b"UNKNOWN COMMAND" client.sock.receive.return_value = b"UNKNOWN COMMAND" with self.assertRaises(ValueError): await client.send_command("SOME_COMMAND") @anyio_mock.with_anyio() async def test_simple_too_large(self): """ Check that MessageTooLargeError is raised if send() reports an incomplete send """ async with self.client as client: client.sock.send.side_effect = lambda b: len(b) / 2 with self.assertRaises(errors.MessageTooLargeError): await client.send_command("SOME_COMMAND") @anyio_mock.with_anyio() async def test_interleaved(self): """ Check that messages are processed alongside replies """ async with self.client as client: client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"<2>SOME-MESSAGE", b"<1>SOME-OTHER-MESSAGE with|args", b"OK", Loading @@ -189,7 +181,7 @@ class SendMessageTests(unittest.TestCase): Check that unexpected replies are logged cleanly """ async with self.client as client: client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"OK", # Response to "ATTACH" b"UNEXPECTED1", b"UNEXPECTED2", Loading @@ -205,20 +197,18 @@ class EventTests(unittest.TestCase): """ def setUp(self): async def _make_client(): return base.BaseClient() self.client = client = anyio.run(_make_client) self.client = client = base.BaseClient() client.sock = anyio_mock.AsyncMock() client.sock.send.side_effect = len client.sock.send.return_value = None @anyio_mock.with_anyio() async def test_simple(self): """ Check that an awaited message is returned when is arrives """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"OK", # Respond to ATTACH b"<2>CTRL-EVENT-EXAMPLE", b"OK", # Respond to DETACH Loading @@ -233,8 +223,9 @@ class EventTests(unittest.TestCase): """ Check that an awaited messages is returned when it arrives between others """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"OK", # Respond to ATTACH b"<1>OTHER-MESSAGE", b"<2>CTRL-EVENT-OTHER", Loading @@ -252,8 +243,9 @@ class EventTests(unittest.TestCase): """ Check that the first of several awaited events is returned """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"OK", # Respond to ATTACH b"<1>OTHER-MESSAGE", b"<2>CTRL-EVENT-OTHER", Loading @@ -274,8 +266,9 @@ class EventTests(unittest.TestCase): """ Check that messages are processed as well as replies """ async with self.client as client, anyio.fail_after(2): client.sock.recv.side_effect = [ with anyio.fail_after(2): async with self.client as client: client.sock.receive.side_effect = [ b"<1>OTHER-MESSAGE", b"OK", # Respond to SOME_COMMAND b"OK", # Respond to ATTACH Loading
tests/unit/test_interfaces_client.py +6 −11 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ Test cases for wpa_supplicant.client.interfaces.InterfaceClient import unittest from unittest.mock import call import anyio from tests.unit import _anyio as anyio_mock from wpa_supplicant import config from wpa_supplicant.client import interfaces Loading @@ -32,12 +30,9 @@ class MethodsTests(unittest.TestCase): """ def setUp(self): async def _make_client(): return interfaces.InterfaceClient() self.client = client = anyio.run(_make_client) self.client = client = interfaces.InterfaceClient() client.sock = anyio_mock.AsyncMock() client.sock.send.side_effect = len client.sock.send.return_value = None @anyio_mock.with_anyio() async def test_scan(self): Loading @@ -45,7 +40,7 @@ class MethodsTests(unittest.TestCase): Check that a scan command waits for a notification then terminates correctly """ async with self.client as client: client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"OK", # Response to "ATTACH" b"OK", # Response to "SCAN" b"<3>CTRL-EVENT-SCAN-RESULTS", Loading @@ -65,7 +60,7 @@ class MethodsTests(unittest.TestCase): Check that set_network sends values to the daemon and raises TypeError for bad types """ async with self.client as client: client.sock.recv.return_value = b"OK" client.sock.receive.return_value = b"OK" send = client.sock.send with self.subTest("good string"): Loading @@ -79,7 +74,7 @@ class MethodsTests(unittest.TestCase): send.reset_mock() with self.subTest("good enum"): await client.set_network("0", "key_mgmt", config.KeyManagementValue.WPA_PSK) await client.set_network("0", "key_mgmt", config.KeyManagementValue.WPA_PSK) # type: ignore send.assert_called_once_with(b"SET_NETWORK 0 key_mgmt WPA-PSK") send.reset_mock() Loading @@ -106,7 +101,7 @@ class MethodsTests(unittest.TestCase): """ async with self.client as client: send = client.sock.send client.sock.recv.side_effect = [ client.sock.receive.side_effect = [ b"0", b"OK", b"OK", Loading