Skip to content

Commit

Permalink
Replace asyncio with anyio
Browse files Browse the repository at this point in the history
statesman is now compatible with Trio
  • Loading branch information
smurfix committed Dec 14, 2023
1 parent 518f7f5 commit bbb6844
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 98 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Our design goals were roughly:

* Utilize type hints extensively as both a documentation and design by contract
tool to provide an expressive, readable API.
* Embrace asyncio as a first class citizen.
* Embrace anyio/asyncio/trio as a first class citizen.
* Implement state machines as plain old Python objects with an easily understood
method and input/output external API surface. Callers shouldn't need to know
or care about FSM minutiae.
Expand Down
13 changes: 1 addition & 12 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pydantic = "^1.7.1"

[tool.poetry.dev-dependencies]
pytest = "^7.2.0"
pytest-asyncio = "^0.20.0"
anyio = "^4.1.0"
devtools = "^0.6.1"
pytest-mock = "^3.10.0"
isort = "^5.8.0"
Expand Down Expand Up @@ -66,4 +66,4 @@ mccabe = ["+*"]
[tool.flakehell.exceptions."statesman_test.py"]
pycodestyle = ["-*"]
pyflakes = ["-*"]
flake8-docstrings = ["-*"]
flake8-docstrings = ["-*"]
15 changes: 10 additions & 5 deletions statesman.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Statesman is a modern state machine library."""
from __future__ import annotations

import asyncio
import anyio
import collections
import contextlib
import datetime
Expand Down Expand Up @@ -163,17 +163,22 @@ def _get_actions(self, type_: Action.Types) -> List[Action]:
return list(filter(lambda c: c.type == type_, self._actions))

async def _run_actions(self, type_: Action.Types, *args, concurrently: bool = True, **kwargs) -> List[Any]:
results = []
if concurrently:
return await asyncio.gather(*(action(*args, **kwargs) for action in self._get_actions(type_)))
async with anyio.create_task_group() as tg:
async def _run(n,p):
results[n] = await p(*args, **kwargs)
for i,action in enumerate(self._get_actions(type_)):
results.append(None)
tg.start_soon(_run,i,action)
else:
results = []
for action in self._get_actions(type_):
result = await action(*args, **kwargs)
results.append(result)
if result is False:
break

return results
return results


class State(BaseModel):
Expand Down Expand Up @@ -1488,4 +1493,4 @@ def _state_entry(
try:
yield obj
finally:
obj._config.state_entry = original
obj._config.state_entry = original
Loading

0 comments on commit bbb6844

Please sign in to comment.