definite
Simple finite state machines.
Perfect for representing workflows.
Quickstart
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" !
Installation
pip install definite
Requirements
- Python 3.6+
Testing
$ pytest .
License
New BSD
Metadata
Release files for definite 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| definite-1.0.0.tar.gz | 6.1 kB | Without provenance | Details for definite-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| definite-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for definite-1.0.0-py3-none-any.whl |
Total release size: 12.5 kB
Release files / definite-1.0.0.tar.gz
| Download URL | definite-1.0.0.tar.gz |
|---|---|
| Size | 6.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8cc05c844aca06cb4f83a846515ac34010dd1143e3e5951d9066dffebdbd6a82
|
|
BLAKE2b-256 checksum How to use checksums |
44535a3d67b177d58ee9f2d749ba24b746579e066af0f399dc1a33e57f08d270
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.12 CPython/3.9.9 Darwin/21.5.0
|
Release files / definite-1.0.0-py3-none-any.whl
| Download URL | definite-1.0.0-py3-none-any.whl |
|---|---|
| Size | 6.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dfdb4c074054507981463fe1ef24f1d33c8f08390c68e2bb21d1f9b1cd1faaf2
|
|
BLAKE2b-256 checksum How to use checksums |
966a3da4f304da5ee9228804734f282449fcbfb0b9d9c7e63341028cca7b631b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.12 CPython/3.9.9 Darwin/21.5.0
|
Security for definite 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.