Skip to content

Commit 73535de

Browse files
committed
chore: Deprecating 'machine.is_<state>' dinamically property in favor of 'machine.state.is_active'; new example of guess the number
1 parent 490d981 commit 73535de

18 files changed

Lines changed: 1495 additions & 22 deletions

README.rst

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,15 @@ True
127127
>>> traffic_light.current_state == traffic_light.yellow
128128
True
129129

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

133-
>>> traffic_light.is_green
132+
>>> traffic_light.green.is_active
134133
False
135134

136-
>>> traffic_light.is_yellow
135+
>>> traffic_light.yellow.is_active
137136
True
138137

139-
>>> traffic_light.is_red
138+
>>> traffic_light.red.is_active
140139
False
141140

142141
Easily iterate over all states:
@@ -161,7 +160,7 @@ Or sending an event with the event name:
161160
Go ahead!
162161
'Running cycle from red to green'
163162

164-
>>> traffic_light.is_green
163+
>>> traffic_light.green.is_active
165164
True
166165

167166
You can't run a transition from an invalid state:
@@ -172,7 +171,7 @@ statemachine.exceptions.TransitionNotAllowed: Can't go when in Green.
172171

173172
Keeping the same state as expected:
174173

175-
>>> traffic_light.is_green
174+
>>> traffic_light.green.is_active
176175
True
177176

178177
And you can pass arbitrary positional or keyword arguments to the event, and
@@ -198,23 +197,23 @@ to the ``StateMachine`` constructor:
198197

199198
>>> traffic_light = TrafficLightMachine(obj)
200199

201-
>>> traffic_light.is_red
200+
>>> traffic_light.red.is_active
202201
True
203202

204203
>>> obj.state
205204
'red'
206205

207206
>>> obj.state = 'green'
208207

209-
>>> traffic_light.is_green
208+
>>> traffic_light.green.is_active
210209
True
211210

212211
>>> traffic_light.slowdown()
213212

214213
>>> obj.state
215214
'yellow'
216215

217-
>>> traffic_light.is_yellow
216+
>>> traffic_light.yellow.is_active
218217
True
219218

220219

@@ -303,6 +302,6 @@ True
303302
>>> control.payments
304303
[4, 6]
305304

306-
>>> control.is_completed
305+
>>> control.completed.is_active
307306
True
308307

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
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# Guess the number machine\n\nAn StateMachine for the well know game.\n\nWell leave the machine imagine a number and also play the game. Why not?\n"
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"metadata": {
25+
"collapsed": false
26+
},
27+
"outputs": [],
28+
"source": [
29+
"import random\nfrom statemachine import StateMachine, State\n\n\nclass GuessTheNumberMachine(StateMachine):\n\n start = State(\"Start\", initial=True)\n low = State(\"Low\")\n high = State(\"High\")\n won = State(\"Won\", final=True)\n lose = State(\"Lose\", final=True)\n\n guess = (\n lose.from_(low, high, conditions=\"max_guesses_reached\")\n | won.from_(low, high, conditions=\"guess_is_equal\")\n | low.from_(low, high, start, conditions=\"guess_is_lower\")\n | high.from_(low, high, start, conditions=\"guess_is_higher\")\n )\n\n def __init__(self, max_attempts=5, lower=1, higher=5, seed=42):\n self.max_attempts = max_attempts\n self.lower = lower\n self.higher = higher\n self.guesses = 0\n\n # lets play a not so random game, or our tests will be crazy\n random.seed(seed)\n self.number = random.randint(self.lower, self.higher)\n super(GuessTheNumberMachine, self).__init__()\n\n def max_guesses_reached(self):\n return self.guesses >= self.max_attempts\n\n def before_guess(self, number):\n self.guesses += 1\n print(\"You guess is {}...\".format(number))\n\n def guess_is_lower(self, number):\n return number < self.number\n\n def guess_is_higher(self, number):\n return number > self.number\n\n def guess_is_equal(self, number):\n return self.number == number\n\n def on_enter_start(self):\n print(\"(psss.. don't tell anyone the number is {})\".format(self.number))\n print(\"I'm thinking of a number between {} and {}. Can you guess what it is?\".format(\n self.lower, self.higher\n ))\n\n def on_enter_low(self):\n print(\"Too low. Try again.\")\n\n def on_enter_high(self):\n print(\"Too high. Try again.\")\n\n def on_enter_won(self):\n print(\"Congratulations, you guessed the number in {} guesses!\".format(self.guesses))\n\n def on_enter_lose(self):\n print(\"Oh, no! You've spent all your {} attempts!\".format(self.guesses))"
30+
]
31+
},
32+
{
33+
"cell_type": "markdown",
34+
"metadata": {},
35+
"source": [
36+
"## Playing\n\n\n"
37+
]
38+
},
39+
{
40+
"cell_type": "code",
41+
"execution_count": null,
42+
"metadata": {
43+
"collapsed": false
44+
},
45+
"outputs": [],
46+
"source": [
47+
"sm = GuessTheNumberMachine(seed=103)"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": null,
53+
"metadata": {
54+
"collapsed": false
55+
},
56+
"outputs": [],
57+
"source": [
58+
"sm.guess(random.randint(1, 5))"
59+
]
60+
},
61+
{
62+
"cell_type": "code",
63+
"execution_count": null,
64+
"metadata": {
65+
"collapsed": false
66+
},
67+
"outputs": [],
68+
"source": [
69+
"sm"
70+
]
71+
},
72+
{
73+
"cell_type": "code",
74+
"execution_count": null,
75+
"metadata": {
76+
"collapsed": false
77+
},
78+
"outputs": [],
79+
"source": [
80+
"sm.guess(random.randint(1, 5))"
81+
]
82+
},
83+
{
84+
"cell_type": "code",
85+
"execution_count": null,
86+
"metadata": {
87+
"collapsed": false
88+
},
89+
"outputs": [],
90+
"source": [
91+
"sm.guess(random.randint(1, 5))\n\n\nsm"
92+
]
93+
},
94+
{
95+
"cell_type": "code",
96+
"execution_count": null,
97+
"metadata": {
98+
"collapsed": false
99+
},
100+
"outputs": [],
101+
"source": [
102+
"sm.guess(random.randint(1, 5))"
103+
]
104+
},
105+
{
106+
"cell_type": "code",
107+
"execution_count": null,
108+
"metadata": {
109+
"collapsed": false
110+
},
111+
"outputs": [],
112+
"source": [
113+
"sm.guess(random.randint(1, 5))"
114+
]
115+
},
116+
{
117+
"cell_type": "code",
118+
"execution_count": null,
119+
"metadata": {
120+
"collapsed": false
121+
},
122+
"outputs": [],
123+
"source": [
124+
"sm"
125+
]
126+
},
127+
{
128+
"cell_type": "code",
129+
"execution_count": null,
130+
"metadata": {
131+
"collapsed": false
132+
},
133+
"outputs": [],
134+
"source": [
135+
"try:\n sm.guess(random.randint(1, 5))\nexcept Exception as e:\n print(e)"
136+
]
137+
}
138+
],
139+
"metadata": {
140+
"kernelspec": {
141+
"display_name": "Python 3",
142+
"language": "python",
143+
"name": "python3"
144+
},
145+
"language_info": {
146+
"codemirror_mode": {
147+
"name": "ipython",
148+
"version": 3
149+
},
150+
"file_extension": ".py",
151+
"mimetype": "text/x-python",
152+
"name": "python",
153+
"nbconvert_exporter": "python",
154+
"pygments_lexer": "ipython3",
155+
"version": "3.8.1"
156+
}
157+
},
158+
"nbformat": 4,
159+
"nbformat_minor": 0
160+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
"""
2+
Guess the number machine
3+
========================
4+
5+
An StateMachine for the well know game.
6+
7+
Well leave the machine imagine a number and also play the game. Why not?
8+
9+
"""
10+
11+
import random
12+
from statemachine import StateMachine, State
13+
14+
15+
class GuessTheNumberMachine(StateMachine):
16+
17+
start = State("Start", initial=True)
18+
low = State("Low")
19+
high = State("High")
20+
won = State("Won", final=True)
21+
lose = State("Lose", final=True)
22+
23+
guess = (
24+
lose.from_(low, high, conditions="max_guesses_reached")
25+
| won.from_(low, high, conditions="guess_is_equal")
26+
| low.from_(low, high, start, conditions="guess_is_lower")
27+
| high.from_(low, high, start, conditions="guess_is_higher")
28+
)
29+
30+
def __init__(self, max_attempts=5, lower=1, higher=5, seed=42):
31+
self.max_attempts = max_attempts
32+
self.lower = lower
33+
self.higher = higher
34+
self.guesses = 0
35+
36+
# lets play a not so random game, or our tests will be crazy
37+
random.seed(seed)
38+
self.number = random.randint(self.lower, self.higher)
39+
super(GuessTheNumberMachine, self).__init__()
40+
41+
def max_guesses_reached(self):
42+
return self.guesses >= self.max_attempts
43+
44+
def before_guess(self, number):
45+
self.guesses += 1
46+
print("You guess is {}...".format(number))
47+
48+
def guess_is_lower(self, number):
49+
return number < self.number
50+
51+
def guess_is_higher(self, number):
52+
return number > self.number
53+
54+
def guess_is_equal(self, number):
55+
return self.number == number
56+
57+
def on_enter_start(self):
58+
print("(psss.. don't tell anyone the number is {})".format(self.number))
59+
print("I'm thinking of a number between {} and {}. Can you guess what it is?".format(
60+
self.lower, self.higher
61+
))
62+
63+
def on_enter_low(self):
64+
print("Too low. Try again.")
65+
66+
def on_enter_high(self):
67+
print("Too high. Try again.")
68+
69+
def on_enter_won(self):
70+
print("Congratulations, you guessed the number in {} guesses!".format(self.guesses))
71+
72+
def on_enter_lose(self):
73+
print("Oh, no! You've spent all your {} attempts!".format(self.guesses))
74+
75+
76+
# %%
77+
# Playing
78+
# -------
79+
#
80+
81+
sm = GuessTheNumberMachine(seed=103)
82+
83+
# %%
84+
85+
sm.guess(random.randint(1, 5))
86+
87+
# %%
88+
89+
sm
90+
91+
# %%
92+
93+
sm.guess(random.randint(1, 5))
94+
95+
# %%
96+
97+
sm.guess(random.randint(1, 5))
98+
99+
100+
sm
101+
102+
# %%
103+
104+
# %%
105+
106+
sm.guess(random.randint(1, 5))
107+
108+
# %%
109+
110+
sm.guess(random.randint(1, 5))
111+
112+
# %%
113+
114+
sm
115+
116+
# %%
117+
118+
try:
119+
sm.guess(random.randint(1, 5))
120+
except Exception as e:
121+
print(e)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
d252d207b9591be207fb9068be9c856d

0 commit comments

Comments
 (0)