Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow CapacityLimiter(math.inf) #728

Merged
merged 6 commits into from
Oct 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/618.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
You can now create an unbounded :class:`CapacityLimiter` by initializing with :obj:`math.inf`
7 changes: 5 additions & 2 deletions trio/_sync.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import operator
from collections import deque, OrderedDict
import math

import attr
import outcome
Expand Down Expand Up @@ -199,8 +200,10 @@ def total_tokens(self):

@total_tokens.setter
def total_tokens(self, new_total_tokens):
if not isinstance(new_total_tokens, int):
raise TypeError("total_tokens must be an int")
if not isinstance(
new_total_tokens, int
) and new_total_tokens != math.inf:
raise TypeError("total_tokens must be an int or math.inf")
if new_total_tokens < 1:
raise ValueError("total_tokens must be >= 1")
self._total_tokens = new_total_tokens
Expand Down
12 changes: 3 additions & 9 deletions trio/_wait_for_object.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import math
from . import _timeouts
from . import _core
from ._threads import run_sync_in_worker_thread
from ._core._windows_cffi import ffi, kernel32, ErrorCodes, raise_winerror, _handle
from ._sync import CapacityLimiter

__all__ = ["WaitForSingleObject"]


class StubLimiter:
def release_on_behalf_of(self, x):
pass

async def acquire_on_behalf_of(self, x):
pass


async def WaitForSingleObject(obj):
"""Async and cancellable variant of WaitForSingleObject. Windows only.

Expand Down Expand Up @@ -45,7 +39,7 @@ async def WaitForSingleObject(obj):
handle,
cancel_handle,
cancellable=True,
limiter=StubLimiter(),
limiter=CapacityLimiter(math.inf),
)
finally:
# Clean up our cancel handle. In case we get here because this task was
Expand Down
15 changes: 15 additions & 0 deletions trio/tests/test_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ async def test_CapacityLimiter():
c.release_on_behalf_of("value 1")


async def test_CapacityLimiter_inf():
Copy link
Contributor

@jxub jxub Oct 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mixed CamelCase here probably breaks PEP-8: https://pep8.org/#function-names

Edit: There's a similar case in the function below already so I guess this is fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, PEP 8 is a set of guidelines to encourage consistency and readability, not strict rules that Guido wants you to follow mindlessly :-). (He actually got frustrated at the pep8 tool and asked its devs to rename it to "pycodestyle", because he didn't think PEP 8 can be enforced by an automatic tool.) Here, no one is going to get confused by the name into thinking it's anything besides a function, and the name is descriptive, so... works for me.

from math import inf
c = CapacityLimiter(inf)
repr(c) # smoke test
assert c.total_tokens == inf
assert c.borrowed_tokens == 0
assert c.available_tokens == inf
with pytest.raises(RuntimeError):
c.release()
assert c.borrowed_tokens == 0
c.acquire_nowait()
assert c.borrowed_tokens == 1
assert c.available_tokens == inf


async def test_CapacityLimiter_change_total_tokens():
c = CapacityLimiter(2)

Expand Down