Simple "state machines" with Python decorators
Project description
# decorstate
[![Build Status](https://travis-ci.org/ahawker/decorstate.svg?branch=master)](https://travis-ci.org/ahawker/decorstate)
[![Test Coverage](https://codeclimate.com/github/ahawker/decorstate/badges/coverage.svg)](https://codeclimate.com/github/ahawker/decorstate/coverage)
[![Code Climate](https://codeclimate.com/github/ahawker/decorstate/badges/gpa.svg)](https://codeclimate.com/github/ahawker/decorstate)
[![Issue Count](https://codeclimate.com/github/ahawker/decorstate/badges/issue_count.svg)](https://codeclimate.com/github/ahawker/decorstate)
[![PyPI Version](https://badge.fury.io/py/decorstate.svg)](https://badge.fury.io/py/decorstate)
[![PyPI Versions](https://img.shields.io/pypi/pyversions/decorstate.svg)](https://pypi.python.org/pypi/decorstate)
[![PyPI Downloads](https://img.shields.io/pypi/dm/decorstate.svg)](https://pypi.python.org/pypi/decorstate)
Build dumb little "state machines" with Python decorators.
### Installation
To install decorstate from [pip](https://pypi.python.org/pypi/pip):
```bash
$ pip install decorstate
```
To install decorstate from source:
```bash
$ git clone git@github.com:ahawker/decorstate.git
$ cd decorstate
$ python setup.py install
```
### Usage
How do I use this pile?
```python
import decorstate
class Switch(object):
state = 'off'
@decorstate.transition('off', 'on')
def on(self, *args, **kwargs):
print 'You turned me on!'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off!'
>>> switch = Switch()
>>> switch.state
'off'
>>> switch.on()
You turned me on!
'on'
>>> switch.off()
You turned me off!
'off'
```
A switch? Really? How lame.
```python
import decorstate
class BrokenSwitch(object):
state = 'off'
@decorstate.transition('off', 'on')
def on(self, *args, **kwargs):
print 'You turned me on!'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off? Nah!'
@off.guard
def off(self, *args, **kwargs):
print 'Ha! I laugh at your feeble attempt!'
>>> broken_switch = BrokenSwitch()
>>> broken_switch.state
'off'
>>> broken_switch.on()
You turned me on!
'on'
>>> broken_switch.off()
Ha! I laugh at your feeble attempt!
'on'
>>> broken_switch.state
'on'
>>> broken_switch.off()
Ha! I laugh at your feeble attempt!
'on'
>>> broken_switch.state
'on'
```
A broken switch? Yawn.
```python
import decorstate
class InstantOffSwitch(object):
state = 'off'
@decorstate.transition('off', 'off')
def on(self, *args, **kwargs):
print 'You turned me on!'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off!'
@on.after
def on(self, *args, **kwargs):
print 'Ha! No light for you!'
>>> instant_off_switch = InstantOffSwitch()
>>> instant_off_switch.state
'off'
>>> instant_off_switch.on()
You turned me on!
Ha! No light for you!
'off'
>>> instant_off_switch.state
'off'
```
Well, that's kinda mean.
```python
import decorstate
import random
class IoTSwitch(object):
state = 'off'
@decorstate.transition('off', 'off')
def on(self, *args, **kwargs):
print 'You turned me on? Maybe...'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off? Maybe...'
@on.guard
def on(self, *args, **kwargs):
return self.coin_flip()
@off.guard
def off(self, *args, **kwargs):
return not self.coin_flip()
@staticmethod
def coin_flip():
return random.randint(1, 2) == 1
>>> iot_switch = IoTSwitch()
>>> iot_switch.state
'off'
>>> iot_switch.on()
'off'
>>> iot_switch.on()
'off'
>>> iot_switch.on()
'off'
>>> iot_switch.on()
You turned me on? Maybe...
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
You turned me off? Maybe...
'off'
```
Hey now, why you hating? Internet powered light switches are next level shit. My living room has its own twitter feed.
### Why?
I was interesting in doing something a bit more complex using the Python [descriptor protocol](https://docs.python.org/2/howto/descriptor.html).
### TODO?
Random thoughts and musing about potential changes/features.
* Consider adding the @machine decorator back as currently, you cannot use the "state", "transition" and "transition_event" attributes until the first transition has been performed since they are lazy created.
* Add event handler that fires only when "entering" a state and not when you perform multiple transitions but stay in the same state.
### License
[Apache 2.0](LICENSE)
[![Build Status](https://travis-ci.org/ahawker/decorstate.svg?branch=master)](https://travis-ci.org/ahawker/decorstate)
[![Test Coverage](https://codeclimate.com/github/ahawker/decorstate/badges/coverage.svg)](https://codeclimate.com/github/ahawker/decorstate/coverage)
[![Code Climate](https://codeclimate.com/github/ahawker/decorstate/badges/gpa.svg)](https://codeclimate.com/github/ahawker/decorstate)
[![Issue Count](https://codeclimate.com/github/ahawker/decorstate/badges/issue_count.svg)](https://codeclimate.com/github/ahawker/decorstate)
[![PyPI Version](https://badge.fury.io/py/decorstate.svg)](https://badge.fury.io/py/decorstate)
[![PyPI Versions](https://img.shields.io/pypi/pyversions/decorstate.svg)](https://pypi.python.org/pypi/decorstate)
[![PyPI Downloads](https://img.shields.io/pypi/dm/decorstate.svg)](https://pypi.python.org/pypi/decorstate)
Build dumb little "state machines" with Python decorators.
### Installation
To install decorstate from [pip](https://pypi.python.org/pypi/pip):
```bash
$ pip install decorstate
```
To install decorstate from source:
```bash
$ git clone git@github.com:ahawker/decorstate.git
$ cd decorstate
$ python setup.py install
```
### Usage
How do I use this pile?
```python
import decorstate
class Switch(object):
state = 'off'
@decorstate.transition('off', 'on')
def on(self, *args, **kwargs):
print 'You turned me on!'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off!'
>>> switch = Switch()
>>> switch.state
'off'
>>> switch.on()
You turned me on!
'on'
>>> switch.off()
You turned me off!
'off'
```
A switch? Really? How lame.
```python
import decorstate
class BrokenSwitch(object):
state = 'off'
@decorstate.transition('off', 'on')
def on(self, *args, **kwargs):
print 'You turned me on!'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off? Nah!'
@off.guard
def off(self, *args, **kwargs):
print 'Ha! I laugh at your feeble attempt!'
>>> broken_switch = BrokenSwitch()
>>> broken_switch.state
'off'
>>> broken_switch.on()
You turned me on!
'on'
>>> broken_switch.off()
Ha! I laugh at your feeble attempt!
'on'
>>> broken_switch.state
'on'
>>> broken_switch.off()
Ha! I laugh at your feeble attempt!
'on'
>>> broken_switch.state
'on'
```
A broken switch? Yawn.
```python
import decorstate
class InstantOffSwitch(object):
state = 'off'
@decorstate.transition('off', 'off')
def on(self, *args, **kwargs):
print 'You turned me on!'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off!'
@on.after
def on(self, *args, **kwargs):
print 'Ha! No light for you!'
>>> instant_off_switch = InstantOffSwitch()
>>> instant_off_switch.state
'off'
>>> instant_off_switch.on()
You turned me on!
Ha! No light for you!
'off'
>>> instant_off_switch.state
'off'
```
Well, that's kinda mean.
```python
import decorstate
import random
class IoTSwitch(object):
state = 'off'
@decorstate.transition('off', 'off')
def on(self, *args, **kwargs):
print 'You turned me on? Maybe...'
@decorstate.transition('on', 'off')
def off(self, *args, **kwargs):
print 'You turned me off? Maybe...'
@on.guard
def on(self, *args, **kwargs):
return self.coin_flip()
@off.guard
def off(self, *args, **kwargs):
return not self.coin_flip()
@staticmethod
def coin_flip():
return random.randint(1, 2) == 1
>>> iot_switch = IoTSwitch()
>>> iot_switch.state
'off'
>>> iot_switch.on()
'off'
>>> iot_switch.on()
'off'
>>> iot_switch.on()
'off'
>>> iot_switch.on()
You turned me on? Maybe...
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
'on'
>>> iot_switch.off()
You turned me off? Maybe...
'off'
```
Hey now, why you hating? Internet powered light switches are next level shit. My living room has its own twitter feed.
### Why?
I was interesting in doing something a bit more complex using the Python [descriptor protocol](https://docs.python.org/2/howto/descriptor.html).
### TODO?
Random thoughts and musing about potential changes/features.
* Consider adding the @machine decorator back as currently, you cannot use the "state", "transition" and "transition_event" attributes until the first transition has been performed since they are lazy created.
* Add event handler that fires only when "entering" a state and not when you perform multiple transitions but stay in the same state.
### License
[Apache 2.0](LICENSE)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
decorstate-0.0.3.tar.gz
(5.7 kB
view details)
Built Distribution
File details
Details for the file decorstate-0.0.3.tar.gz
.
File metadata
- Download URL: decorstate-0.0.3.tar.gz
- Upload date:
- Size: 5.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 285fe86bafd8f99a021926c5083c893e586ba81ba8380d960001d4ec61ed88ba |
|
MD5 | fca48f57cc566de712dc3c54743911f1 |
|
BLAKE2b-256 | 67307ca32fb3b6474e344dc33b53c9a07034514cea1c286c88e4386cc8175194 |
File details
Details for the file decorstate-0.0.3-py2.py3-none-any.whl
.
File metadata
- Download URL: decorstate-0.0.3-py2.py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2b10af7eb77c14cb863786355e11ebe2c6e4030407bd9fb0b8c5ea2747df1e0e |
|
MD5 | 69314806fbd71131449cd39c0ac773eb |
|
BLAKE2b-256 | 62c562632f1de0c317911fb5e5d32a0f1c5b3b049f6fbc2cf20ebd332e60bac7 |