From: Tom Christie Date: Sun, 8 Dec 2019 19:52:46 +0000 (+0000) Subject: Drop 'fork' (#619) X-Git-Tag: 0.9.4~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eba29da632c3a0fce55a54fc18cd6b147db43726;p=thirdparty%2Fhttpx.git Drop 'fork' (#619) --- diff --git a/httpx/concurrency/asyncio.py b/httpx/concurrency/asyncio.py index 51006959..39bccdc9 100644 --- a/httpx/concurrency/asyncio.py +++ b/httpx/concurrency/asyncio.py @@ -268,28 +268,6 @@ class AsyncioBackend(ConcurrencyBackend): finally: self._loop = loop - async def fork( - self, - coroutine1: typing.Callable, - args1: typing.Sequence, - coroutine2: typing.Callable, - args2: typing.Sequence, - ) -> None: - task1 = self.loop.create_task(coroutine1(*args1)) - task2 = self.loop.create_task(coroutine2(*args2)) - - try: - await asyncio.gather(task1, task2) - finally: - pending: typing.Set[asyncio.Future[typing.Any]] # Please mypy. - _, pending = await asyncio.wait({task1, task2}, timeout=0) - for task in pending: - task.cancel() - try: - await task - except asyncio.CancelledError: - pass - def get_semaphore(self, limits: PoolLimits) -> BasePoolSemaphore: return PoolSemaphore(limits) diff --git a/httpx/concurrency/auto.py b/httpx/concurrency/auto.py index ed85806e..3b57e567 100644 --- a/httpx/concurrency/auto.py +++ b/httpx/concurrency/auto.py @@ -51,12 +51,3 @@ class AutoBackend(ConcurrencyBackend): def create_event(self) -> BaseEvent: return self.backend.create_event() - - async def fork( - self, - coroutine1: typing.Callable, - args1: typing.Sequence, - coroutine2: typing.Callable, - args2: typing.Sequence, - ) -> None: - return await self.backend.fork(coroutine1, args1, coroutine2, args2) diff --git a/httpx/concurrency/base.py b/httpx/concurrency/base.py index 27ce9c89..a735c87e 100644 --- a/httpx/concurrency/base.py +++ b/httpx/concurrency/base.py @@ -120,21 +120,3 @@ class ConcurrencyBackend: def create_event(self) -> BaseEvent: raise NotImplementedError() # pragma: no cover - - async def fork( - self, - coroutine1: typing.Callable, - args1: typing.Sequence, - coroutine2: typing.Callable, - args2: typing.Sequence, - ) -> None: - """ - Run two coroutines concurrently. - - This should start 'coroutine1' with '*args1' and 'coroutine2' with '*args2', - and wait for them to finish. - - In case one of the coroutines raises an exception, cancel the other one then - raise. If the other coroutine had also raised an exception, ignore it. - """ - raise NotImplementedError() # pragma: no cover diff --git a/httpx/concurrency/trio.py b/httpx/concurrency/trio.py index 7604e965..4fa30019 100644 --- a/httpx/concurrency/trio.py +++ b/httpx/concurrency/trio.py @@ -168,22 +168,6 @@ class TrioBackend(ConcurrencyBackend): functools.partial(coroutine, **kwargs) if kwargs else coroutine, *args ) - async def fork( - self, - coroutine1: typing.Callable, - args1: typing.Sequence, - coroutine2: typing.Callable, - args2: typing.Sequence, - ) -> None: - try: - async with trio.open_nursery() as nursery: - nursery.start_soon(coroutine1, *args1) - nursery.start_soon(coroutine2, *args2) - except trio.MultiError as exc: - # In practice, we don't actually care about raising both - # exceptions, so let's raise either indeterminantly. - raise exc.exceptions[0] - def get_semaphore(self, limits: PoolLimits) -> BasePoolSemaphore: return PoolSemaphore(limits) diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py index 3e3d6403..a9b23dc3 100644 --- a/tests/test_concurrency.py +++ b/tests/test_concurrency.py @@ -8,7 +8,7 @@ from httpx.concurrency.asyncio import AsyncioBackend from httpx.concurrency.base import lookup_backend from httpx.concurrency.trio import TrioBackend from httpx.config import SSLConfig -from tests.concurrency import get_cipher, run_concurrently, sleep +from tests.concurrency import get_cipher, run_concurrently async def read_response(stream, timeout: Timeout, should_contain: bytes) -> bytes: @@ -99,53 +99,6 @@ async def test_concurrent_read(server, backend): await stream.close() -async def test_fork(backend): - backend = lookup_backend(backend) - ok_counter = 0 - - async def ok(delay: int) -> None: - nonlocal ok_counter - await sleep(backend, delay) - ok_counter += 1 - - async def fail(message: str, delay: int) -> None: - await sleep(backend, delay) - raise RuntimeError(message) - - await backend.fork(ok, [0], ok, [0]) - assert ok_counter == 2 - - with pytest.raises(RuntimeError, match="Oops"): - await backend.fork(ok, [0], fail, ["Oops", 0.01]) - - assert ok_counter == 3 - - with pytest.raises(RuntimeError, match="Oops"): - await backend.fork(ok, [0.01], fail, ["Oops", 0]) - - assert ok_counter == 3 - - with pytest.raises(RuntimeError, match="Oops"): - await backend.fork(fail, ["Oops", 0.01], ok, [0]) - - assert ok_counter == 4 - - with pytest.raises(RuntimeError, match="Oops"): - await backend.fork(fail, ["Oops", 0], ok, [0.01]) - - assert ok_counter == 4 - - with pytest.raises(RuntimeError, match="My bad"): - await backend.fork(fail, ["My bad", 0], fail, ["Oops", 0.01]) - - with pytest.raises(RuntimeError, match="Oops"): - await backend.fork(fail, ["My bad", 0.01], fail, ["Oops", 0]) - - # No 'match', since we can't know which will be raised first. - with pytest.raises(RuntimeError): - await backend.fork(fail, ["My bad", 0], fail, ["Oops", 0]) - - def test_lookup_backend(): assert isinstance(lookup_backend("asyncio"), AsyncioBackend) assert isinstance(lookup_backend("trio"), TrioBackend)