From 1de6f81a85d1cb77049b4a3f080a91e37b124d63 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Thu, 4 Jun 2020 10:20:50 +0400 Subject: [PATCH 1/5] Remove deprecated BlockingTrioPortal --- trio/__init__.py | 5 ----- trio/_threads.py | 19 +----------------- trio/tests/test_threads.py | 40 +++----------------------------------- 3 files changed, 4 insertions(+), 60 deletions(-) diff --git a/trio/__init__.py b/trio/__init__.py index 5339d107eb..50734c71ae 100644 --- a/trio/__init__.py +++ b/trio/__init__.py @@ -54,8 +54,6 @@ Condition, ) -from ._threads import BlockingTrioPortal as _BlockingTrioPortal - from ._highlevel_generic import aclose_forcefully, StapledStream from ._channel import ( @@ -134,9 +132,6 @@ "current_default_worker_thread_limiter": _deprecate.DeprecatedAttribute( to_thread.current_default_thread_limiter, "0.12.0", issue=810, ), - "BlockingTrioPortal": _deprecate.DeprecatedAttribute( - _BlockingTrioPortal, "0.12.0", issue=810, instead=from_thread, - ), # NOTE: when you remove this, you should also remove the file # trio/hazmat.py. For details on why we have both, see: # diff --git a/trio/_threads.py b/trio/_threads.py index 8867388bd7..62c22041f0 100644 --- a/trio/_threads.py +++ b/trio/_threads.py @@ -21,20 +21,6 @@ # Global due to Threading API, thread local storage for trio token TOKEN_LOCAL = threading.local() - -class BlockingTrioPortal: - def __init__(self, trio_token=None): - if trio_token is None: - trio_token = trio.lowlevel.current_trio_token() - self._trio_token = trio_token - - def run(self, afn, *args): - return from_thread_run(afn, *args, trio_token=self._trio_token) - - def run_sync(self, fn, *args): - return from_thread_run_sync(fn, *args, trio_token=self._trio_token) - - _limiter_local = RunVar("limiter") # I pulled this number out of the air; it isn't based on anything. Probably we # should make some kind of measurements to pick a good value. @@ -227,10 +213,7 @@ def _run_fn_as_system_task(cb, fn, *args, trio_token=None): "this thread wasn't created by Trio, pass kwarg trio_token=..." ) - # TODO: This is only necessary for compatibility with BlockingTrioPortal. - # once that is deprecated, this check should no longer be necessary because - # thread local storage (or the absence of) is sufficient to check if trio - # is running in a thread or not. + # Avoid deadlock by making sure we're not called from Trio thread try: trio.lowlevel.current_task() except RuntimeError: diff --git a/trio/tests/test_threads.py b/trio/tests/test_threads.py index a9059fef79..1cb3956def 100644 --- a/trio/tests/test_threads.py +++ b/trio/tests/test_threads.py @@ -12,7 +12,6 @@ current_default_thread_limiter, from_thread_run, from_thread_run_sync, - BlockingTrioPortal, ) from .._core.tests.test_ki import ki_self @@ -539,40 +538,7 @@ def test_run_fn_as_system_task_catched_badly_typed_token(): from_thread_run_sync(_core.current_time, trio_token="Not TrioTokentype") -async def test_do_in_trio_thread_from_trio_thread_legacy(): - # This check specifically confirms that a RuntimeError will be raised if - # the old BlockingTrIoPortal API calls into a trio loop while already - # running inside of one. - portal = BlockingTrioPortal() - +async def test_from_thread_inside_trio_thread(): + trio_token = _core.current_trio_token() with pytest.raises(RuntimeError): - portal.run_sync(lambda: None) # pragma: no branch - - async def foo(): # pragma: no cover - pass - - with pytest.raises(RuntimeError): - portal.run(foo) - - -async def test_BlockingTrioPortal_with_explicit_TrioToken(): - # This tests the deprecated BlockingTrioPortal with a token passed in to - # confirm that both methods of making a portal are supported by - # trio.from_thread - token = _core.current_trio_token() - - def worker_thread(token): - with pytest.raises(RuntimeError): - BlockingTrioPortal() - portal = BlockingTrioPortal(token) - return portal.run_sync(threading.current_thread) - - t = await to_thread_run_sync(worker_thread, token) - assert t == threading.current_thread() - - -def test_BlockingTrioPortal_deprecated_export(recwarn): - import trio - - btp = trio.BlockingTrioPortal - assert btp is BlockingTrioPortal + from_thread_run_sync(lambda: None, trio_token=trio_token) From ddf2483bb831f83327c28dbc09932dcd8c7d67ae Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Thu, 4 Jun 2020 21:51:28 +0400 Subject: [PATCH 2/5] Exclude deprecated exports checks from coverage We don't necessarily always have deprecated exports. --- trio/tests/test_exports.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/trio/tests/test_exports.py b/trio/tests/test_exports.py index 1d49f4765d..510a0987b2 100644 --- a/trio/tests/test_exports.py +++ b/trio/tests/test_exports.py @@ -33,7 +33,8 @@ def test_core_is_properly_reexported(): def public_modules(module): yield module for name, class_ in module.__dict__.items(): - if name.startswith("_"): + # Deprecated classes are exported with a leading underscore + if name.startswith("_"): # pragma: nocover continue if not isinstance(class_, types.ModuleType): continue @@ -118,7 +119,8 @@ def test_classes_are_final(): for name, class_ in module.__dict__.items(): if not isinstance(class_, type): continue - if name.startswith("_"): + # Deprecated classes are exported with a leading underscore + if name.startswith("_"): # pragma: nocover continue # Abstract classes can be subclassed, because that's the whole From 781531feca222ffe82f11a4fc41811c367a690cd Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Tue, 9 Jun 2020 12:01:52 +0400 Subject: [PATCH 3/5] Fix coverage by not passing lambda Otherwise, coverage complains that we did not run the lambda. --- trio/tests/test_threads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trio/tests/test_threads.py b/trio/tests/test_threads.py index 1cb3956def..d7f337e6f6 100644 --- a/trio/tests/test_threads.py +++ b/trio/tests/test_threads.py @@ -541,4 +541,4 @@ def test_run_fn_as_system_task_catched_badly_typed_token(): async def test_from_thread_inside_trio_thread(): trio_token = _core.current_trio_token() with pytest.raises(RuntimeError): - from_thread_run_sync(lambda: None, trio_token=trio_token) + from_thread_run_sync(fn=None, trio_token=trio_token) From f5a219131d8ba61cea6b4d028576a81349d8f5af Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Tue, 9 Jun 2020 12:07:29 +0400 Subject: [PATCH 4/5] Add newsfragment --- newsfragments/1574.removal.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 newsfragments/1574.removal.rst diff --git a/newsfragments/1574.removal.rst b/newsfragments/1574.removal.rst new file mode 100644 index 0000000000..175e607319 --- /dev/null +++ b/newsfragments/1574.removal.rst @@ -0,0 +1 @@ +Remove ``BlockingTrioPortal``: it was deprecated in 0.12.0. From 6866ae048531b96cfaa29307b35222384b25a2e6 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Tue, 9 Jun 2020 13:24:33 +0400 Subject: [PATCH 5/5] Avoid passing None function for future mypy checks --- trio/tests/test_threads.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/trio/tests/test_threads.py b/trio/tests/test_threads.py index d7f337e6f6..8b95eff030 100644 --- a/trio/tests/test_threads.py +++ b/trio/tests/test_threads.py @@ -539,6 +539,9 @@ def test_run_fn_as_system_task_catched_badly_typed_token(): async def test_from_thread_inside_trio_thread(): + def not_called(): # pragma: no cover + assert False + trio_token = _core.current_trio_token() with pytest.raises(RuntimeError): - from_thread_run_sync(fn=None, trio_token=trio_token) + from_thread_run_sync(not_called, trio_token=trio_token)