Skip to content

Commit 057b53b

Browse files
authored
feat: Examples gallery; Deprecating 'State.identifier' (#303)
1 parent 0c49371 commit 057b53b

45 files changed

Lines changed: 1443 additions & 39 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTING.rst

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,39 @@ Ready to contribute? Here's how to set up `python-statemachine` for local develo
7676

7777
Now you can make your changes locally.
7878

79-
5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox::
79+
5. When you're done making changes, check that your changes pass flake8 and the tests, including
80+
testing other Python versions with tox::
8081

8182
$ flake8 statemachine tests
82-
$ python setup.py test or py.test
83+
$ py.test
8384
$ tox
8485

8586
To get flake8 and tox, just pip install them into your virtualenv.
8687

88+
6. To build the documentation locally, run::
89+
90+
$ sphinx-build docs docs/_build/html
91+
92+
Now you can serve the local documentation using a webserver, like the built-in included
93+
with python::
94+
95+
$ python -m http.server --directory docs/_build/html
96+
97+
And access your browser at http://localhost:8000/
98+
99+
If you're specially writting documentation, I strongly recommend using ``sphinx-autobuild``
100+
as it improves the workflow watching for file changes and with live reloading::
101+
102+
$ sphinx-autobuild docs docs/_build/html --re-ignore "auto_examples/.*"
103+
104+
Sometimes you need a full fresh of the files being build for docs, you can use::
105+
106+
$ rm -rf docs/_build/ docs/auto_examples
107+
87108
.. note::
88109

89-
In order to get the tox working for all versions, I usually run pyenv enabling shell for those versions:
110+
In order to get the tox working for all versions, I usually run pyenv enabling shell for
111+
those versions::
90112

91113
$ pyenv shell 3.8.1/envs/python-statemachine 3.7.6 3.6.10 3.5.9 2.7.17
92114

README.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ Define your state machine:
8888
... message = ". " + message if message else ""
8989
... return "Running {} from {} to {}{}".format(
9090
... event_data.event,
91-
... event_data.transition.source.identifier,
92-
... event_data.transition.destination.identifier,
91+
... event_data.transition.source.id,
92+
... event_data.transition.destination.id,
9393
... message,
9494
... )
9595
...
@@ -111,13 +111,13 @@ Then start sending events:
111111

112112
You can inspect about the current state:
113113

114-
>>> traffic_light.current_state.identifier
114+
>>> traffic_light.current_state.id
115115
'yellow'
116116

117117
Or get a complete state repr for debugging purposes:
118118

119119
>>> traffic_light.current_state
120-
State('Yellow', identifier='yellow', value='yellow', initial=False, final=False)
120+
State('Yellow', id='yellow', value='yellow', initial=False, final=False)
121121

122122
The ``State`` instance can also be checked by equality:
123123

@@ -127,7 +127,7 @@ True
127127
>>> traffic_light.current_state == traffic_light.yellow
128128
True
129129

130-
But for your convenience, a dynamically property ``is_<state.identifier>`` is created for each state,
130+
But for your convenience, a dynamically property ``is_<state.id>`` is created for each state,
131131
so you can easily check if a machine is at a specific state at any time:
132132

133133
>>> traffic_light.is_green
@@ -141,7 +141,7 @@ False
141141

142142
Easily iterate over all states:
143143

144-
>>> [s.identifier for s in traffic_light.states]
144+
>>> [s.id for s in traffic_light.states]
145145
['green', 'red', 'yellow']
146146

147147
Or over events:
@@ -276,7 +276,7 @@ You can use this machine as follows.
276276
>>> control.receive_payment(4)
277277
[4]
278278

279-
>>> control.current_state.identifier
279+
>>> control.current_state.id
280280
'waiting_for_payment'
281281

282282
>>> control.process_order()
@@ -287,7 +287,7 @@ statemachine.exceptions.TransitionNotAllowed: Can't process_order when in Waitin
287287
>>> control.receive_payment(6)
288288
[4, 6]
289289

290-
>>> control.current_state.identifier
290+
>>> control.current_state.id
291291
'processing'
292292

293293
>>> control.process_order()

docs/_static/custom_machine.css

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* div.sphx-glr-download {
2+
height: 0px;
3+
visibility: hidden;
4+
} */
5+
6+
.sphx-glr-thumbnails {
7+
grid-template-columns: repeat(auto-fill, minmax(600px, 1fr)) !important;
8+
}
9+
10+
.sphx-glr-thumbcontainer {
11+
min-height: 320px !important;
12+
margin: 20px !important;
13+
justify-content: center;
14+
}
15+
.sphx-glr-thumbcontainer .figure {
16+
width: 600px !important;
17+
}
18+
.sphx-glr-thumbcontainer img {
19+
max-height: 250px !important;
20+
max-width: 600px !important;
21+
width: 100% !important;
22+
}
23+
.sphx-glr-thumbcontainer a.internal {
24+
padding: 20px 10px 0 !important;
25+
}
26+
27+
28+
/* Gallery Donwload buttons */
29+
div.sphx-glr-download a {
30+
color: #404040 !important;
31+
background-color: #f3f6f6 !important;
32+
background-image: none;
33+
border-radius: 4px;
34+
border: none;
35+
color: #404040 !important;
36+
display: inline-block;
37+
font-weight: bold;
38+
padding: 1ex;
39+
text-align: center;
40+
}
41+
42+
div.sphx-glr-download code.download {
43+
display: inline-block;
44+
white-space: normal;
45+
word-break: normal;
46+
overflow-wrap: break-word;
47+
/* border and background are given by the enclosing 'a' */
48+
border: none;
49+
background: none;
50+
}
51+
52+
div.sphx-glr-download a:hover {
53+
box-shadow: none;
54+
text-decoration: none;
55+
background-image: none;
56+
background-color: #e5ebeb !important;
57+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {
7+
"collapsed": false
8+
},
9+
"outputs": [],
10+
"source": [
11+
"%matplotlib inline"
12+
]
13+
},
14+
{
15+
"cell_type": "markdown",
16+
"metadata": {},
17+
"source": [
18+
"\n# All actions machine\n\nA StateMachine that exercices all possible `Actions` and `Guards`.\n"
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"metadata": {
25+
"collapsed": false
26+
},
27+
"outputs": [],
28+
"source": [
29+
"import mock\n\nfrom statemachine import StateMachine, State\n\n\nclass AllActionsMachine(StateMachine):\n\n initial = State(\"Initial\", initial=True)\n final = State(\"Final\", final=True)\n\n go = initial.to(\n final,\n validators=[\"validation_1\", \"validation_2\"],\n conditions=[\"condition_1\", \"condition_2\"],\n unless=[\"unless_1\", \"unless_2\"],\n on_execute=[\"on_execute_1\", \"on_execute_2\"],\n before=[\"before_go_inline_1\", \"before_go_inline_2\"],\n after=[\"after_go_inline_1\", \"after_go_inline_2\"],\n )\n\n def __init__(self, *args, **kwargs):\n self.spy = mock.Mock(side_effect=lambda x: x)\n super(AllActionsMachine, self).__init__(*args, **kwargs)\n\n # validations and conditions\n\n def validation_1(self):\n # this method may raise an exception\n return self.spy(\"validation_1\")\n\n def validation_2(self):\n # this method may raise an exception\n return self.spy(\"validation_2\")\n\n def condition_1(self):\n self.spy(\"condition_1\")\n return True\n\n def condition_2(self):\n self.spy(\"condition_2\")\n return True\n\n def unless_1(self):\n self.spy(\"unless_1\")\n return False\n\n def unless_2(self):\n self.spy(\"unless_2\")\n return False\n\n # generics state\n\n def on_enter_state(self):\n return self.spy(\"on_enter_state\")\n\n def on_exit_state(self):\n return self.spy(\"on_exit_state\")\n\n # generics transition\n\n def before_transition(self):\n return self.spy(\"before_transition\")\n\n def after_transition(self):\n return self.spy(\"after_transition\")\n\n # before / after specific\n\n def on_execute_1(self):\n return self.spy(\"on_execute_1\")\n\n def on_execute_2(self):\n return self.spy(\"on_execute_2\")\n\n def before_go_inline_1(self):\n return self.spy(\"before_go_inline_1\")\n\n def before_go_inline_2(self):\n return self.spy(\"before_go_inline_2\")\n\n def before_go(self):\n return self.spy(\"before_go\")\n\n def on_go(self):\n return self.spy(\"on_go\")\n\n def after_go_inline_1(self):\n return self.spy(\"after_go_inline_1\")\n\n def after_go_inline_2(self):\n return self.spy(\"after_go_inline_2\")\n\n def after_go(self):\n return self.spy(\"after_go\")\n\n # enter / exit specific\n\n def on_enter_initial(self):\n return self.spy(\"on_enter_initial\")\n\n def on_exit_initial(self):\n return self.spy(\"on_exit_initial\")\n\n def on_enter_final(self):\n return self.spy(\"on_enter_final\")\n\n def on_exit_final(self):\n \"hopefully this will not be called\"\n return self.spy(\"on_exit_final\")"
30+
]
31+
}
32+
],
33+
"metadata": {
34+
"kernelspec": {
35+
"display_name": "Python 3",
36+
"language": "python",
37+
"name": "python3"
38+
},
39+
"language_info": {
40+
"codemirror_mode": {
41+
"name": "ipython",
42+
"version": 3
43+
},
44+
"file_extension": ".py",
45+
"mimetype": "text/x-python",
46+
"name": "python",
47+
"nbconvert_exporter": "python",
48+
"pygments_lexer": "ipython3",
49+
"version": "3.8.1"
50+
}
51+
},
52+
"nbformat": 4,
53+
"nbformat_minor": 0
54+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
All actions machine
3+
-------------------
4+
5+
A StateMachine that exercices all possible :ref:`Actions` and :ref:`Guards`.
6+
7+
"""
8+
9+
import mock
10+
11+
from statemachine import StateMachine, State
12+
13+
14+
class AllActionsMachine(StateMachine):
15+
16+
initial = State("Initial", initial=True)
17+
final = State("Final", final=True)
18+
19+
go = initial.to(
20+
final,
21+
validators=["validation_1", "validation_2"],
22+
conditions=["condition_1", "condition_2"],
23+
unless=["unless_1", "unless_2"],
24+
on_execute=["on_execute_1", "on_execute_2"],
25+
before=["before_go_inline_1", "before_go_inline_2"],
26+
after=["after_go_inline_1", "after_go_inline_2"],
27+
)
28+
29+
def __init__(self, *args, **kwargs):
30+
self.spy = mock.Mock(side_effect=lambda x: x)
31+
super(AllActionsMachine, self).__init__(*args, **kwargs)
32+
33+
# validations and conditions
34+
35+
def validation_1(self):
36+
# this method may raise an exception
37+
return self.spy("validation_1")
38+
39+
def validation_2(self):
40+
# this method may raise an exception
41+
return self.spy("validation_2")
42+
43+
def condition_1(self):
44+
self.spy("condition_1")
45+
return True
46+
47+
def condition_2(self):
48+
self.spy("condition_2")
49+
return True
50+
51+
def unless_1(self):
52+
self.spy("unless_1")
53+
return False
54+
55+
def unless_2(self):
56+
self.spy("unless_2")
57+
return False
58+
59+
# generics state
60+
61+
def on_enter_state(self):
62+
return self.spy("on_enter_state")
63+
64+
def on_exit_state(self):
65+
return self.spy("on_exit_state")
66+
67+
# generics transition
68+
69+
def before_transition(self):
70+
return self.spy("before_transition")
71+
72+
def after_transition(self):
73+
return self.spy("after_transition")
74+
75+
# before / after specific
76+
77+
def on_execute_1(self):
78+
return self.spy("on_execute_1")
79+
80+
def on_execute_2(self):
81+
return self.spy("on_execute_2")
82+
83+
def before_go_inline_1(self):
84+
return self.spy("before_go_inline_1")
85+
86+
def before_go_inline_2(self):
87+
return self.spy("before_go_inline_2")
88+
89+
def before_go(self):
90+
return self.spy("before_go")
91+
92+
def on_go(self):
93+
return self.spy("on_go")
94+
95+
def after_go_inline_1(self):
96+
return self.spy("after_go_inline_1")
97+
98+
def after_go_inline_2(self):
99+
return self.spy("after_go_inline_2")
100+
101+
def after_go(self):
102+
return self.spy("after_go")
103+
104+
# enter / exit specific
105+
106+
def on_enter_initial(self):
107+
return self.spy("on_enter_initial")
108+
109+
def on_exit_initial(self):
110+
return self.spy("on_exit_initial")
111+
112+
def on_enter_final(self):
113+
return self.spy("on_enter_final")
114+
115+
def on_exit_final(self):
116+
"hopefully this will not be called"
117+
return self.spy("on_exit_final")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2132b4efc59380ceee5e938f475144a6

0 commit comments

Comments
 (0)