简单的有限状态机。
项目描述
确定
简单的有限状态机。
非常适合表示工作流程。
快速入门
from definite import FSM
# You define all the valid states, as well as what their allowed
# transitions are.
class Workflow(FSM):
allowed_transitions = {
"draft": ["awaiting_review", "rejected"],
"awaiting_review": ["draft", "reviewed", "rejected"],
"reviewed": ["published", "rejected"],
"published": None,
"rejected": ["draft"],
}
default_state = "draft"
# Right away, you can use the states/transitions as-is to enforce changes.
workflow = Workflow()
workflow.current_state() # "draft"
workflow.transition_to("awaiting_review")
workflow.transition_to("reviewed")
workflow.is_allowed("published") # True
# Invalid/disallowed transitions will throw an exception.
workflow.current_state() # "reviewed"
# ...which can only go to "published" or "rejected", but...
workflow.transition_to("awaiting_review")
# Traceback (most recent call last):
# ...
# workflow.TransitionNotAllowed: "reviewed" cannot transition to "awaiting_review"
# Additionally, you can set up extra code to fire on given state changes.
class Workflow(FSM):
# Same transitions & default state.
allowed_transitions = {
"draft": ["awaiting_review", "rejected"],
"awaiting_review": ["draft", "reviewed", "rejected"],
"reviewed": ["published", "rejected"],
"published": None,
"rejected": ["draft"],
}
default_state = "draft"
# Define a `handle_<state_name>` method on the class.
def handle_awaiting_review(self, new_state):
spell_check_results = check_spelling(self.obj.content)
msg = (
f"{self.obj.title} ready for review. "
f"{len(spell_check_results)} spelling errors."
)
send_email(to=editor_email, message=msg)
def handle_published(self, new_state):
self.obj.pub_date = datetime.datetime.utcnow()
self.obj.save()
# You can also setup code that fires on **ANY** valid transition with the
# special `handle_any` method.
def handle_any(self, new_state):
self.obj.state = new_state
self.obj.save()
# We can pull in any Python object, like a database-backed model, that we
# want to associate with our FSM.
from news.models import NewsPost
news_post = NewsPost.objects.create(
title="Hello world!",
content="This iz our frist post!",
state="draft",
)
# We start mostly the same, but this time pass an `obj` kwarg!
workflow = Workflow(obj=news_post)
# If you wanted to be explicit, you could also pass along the `initial_state`:
workflow = Workflow(
obj=news_post,
initial_state=news_post.state
)
workflow.current_state() # "draft"
# But when we trigger this change...
workflow.transition_to("awaiting_review")
# ...it triggers the spell check & the email we defined above, as well as
# hitting the `handle_any` method & updating the `state` field in the DB.
news_post.refresh_from_db()
news_post.state # "awaiting_review" !
安装
pip install 确定包
要求
- Python 3.6+
测试
$ pytest .
许可证
新BSD
项目详情
下载文件
下载适合您平台的文件。如果您不确定要选择哪个,请了解更多关于安装包的信息。
源分布
definite-1.0.0.tar.gz (6.1 kB 查看哈希)
构建分布
definite-1.0.0-py3-none-any.whl (6.4 kB 查看哈希)