-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d63f455
Showing
7,353 changed files
with
1,463,864 additions
and
0 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
*.pyc | ||
__pycache__/ | ||
venv/ | ||
.env | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Copyright (c) 2014 | ||
Rackspace | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
Metadata-Version: 2.1 | ||
Name: Automat | ||
Version: 24.8.1 | ||
Summary: Self-service finite-state machines for the programmer on the go. | ||
Author-email: Glyph <code@glyph.im> | ||
License: Copyright (c) 2014 | ||
Rackspace | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
|
||
Project-URL: Documentation, https://automat.readthedocs.io/ | ||
Project-URL: Source, https://github.com/glyph/automat/ | ||
Keywords: fsm,state machine,automata | ||
Classifier: Intended Audience :: Developers | ||
Classifier: License :: OSI Approved :: MIT License | ||
Classifier: Operating System :: OS Independent | ||
Classifier: Programming Language :: Python | ||
Classifier: Programming Language :: Python :: 3 | ||
Classifier: Programming Language :: Python :: 3.8 | ||
Classifier: Programming Language :: Python :: 3.9 | ||
Classifier: Programming Language :: Python :: 3.10 | ||
Classifier: Programming Language :: Python :: 3.11 | ||
Classifier: Programming Language :: Python :: 3.12 | ||
Requires-Python: >=3.8 | ||
Description-Content-Type: text/markdown | ||
License-File: LICENSE | ||
Requires-Dist: typing-extensions; python_version < "3.10" | ||
Provides-Extra: visualize | ||
Requires-Dist: graphviz>0.5.1; extra == "visualize" | ||
Requires-Dist: Twisted>=16.1.1; extra == "visualize" | ||
|
||
# Automat # | ||
|
||
[](http://automat.readthedocs.io/en/latest/) | ||
[](https://github.com/glyph/automat/actions/workflows/ci.yml?query=branch%3Atrunk) | ||
[](http://codecov.io/github/glyph/automat?branch=trunk) | ||
|
||
## Self-service finite-state machines for the programmer on the go. ## | ||
|
||
Automat is a library for concise, idiomatic Python expression of finite-state | ||
automata (particularly deterministic finite-state transducers). | ||
|
||
Read more here, or on [Read the Docs](https://automat.readthedocs.io/), or watch the following videos for an overview and presentation | ||
|
||
### Why use state machines? ### | ||
|
||
Sometimes you have to create an object whose behavior varies with its state, | ||
but still wishes to present a consistent interface to its callers. | ||
|
||
For example, let's say you're writing the software for a coffee machine. It | ||
has a lid that can be opened or closed, a chamber for water, a chamber for | ||
coffee beans, and a button for "brew". | ||
|
||
There are a number of possible states for the coffee machine. It might or | ||
might not have water. It might or might not have beans. The lid might be open | ||
or closed. The "brew" button should only actually attempt to brew coffee in | ||
one of these configurations, and the "open lid" button should only work if the | ||
coffee is not, in fact, brewing. | ||
|
||
With diligence and attention to detail, you can implement this correctly using | ||
a collection of attributes on an object; `hasWater`, `hasBeans`, `isLidOpen` | ||
and so on. However, you have to keep all these attributes consistent. As the | ||
coffee maker becomes more complex - perhaps you add an additional chamber for | ||
flavorings so you can make hazelnut coffee, for example - you have to keep | ||
adding more and more checks and more and more reasoning about which | ||
combinations of states are allowed. | ||
|
||
Rather than adding tedious `if` checks to every single method to make sure that | ||
each of these flags are exactly what you expect, you can use a state machine to | ||
ensure that if your code runs at all, it will be run with all the required | ||
values initialized, because they have to be called in the order you declare | ||
them. | ||
|
||
You can read about state machines and their advantages for Python programmers | ||
in more detail [in this excellent article by Jean-Paul | ||
Calderone](https://web.archive.org/web/20160507053658/https://clusterhq.com/2013/12/05/what-is-a-state-machine/). | ||
|
||
### What makes Automat different? ### | ||
|
||
There are | ||
[dozens of libraries on PyPI implementing state machines](https://pypi.org/search/?q=finite+state+machine). | ||
So it behooves me to say why yet another one would be a good idea. | ||
|
||
Automat is designed around this principle: while organizing your code around | ||
state machines is a good idea, your callers don't, and shouldn't have to, care | ||
that you've done so. In Python, the "input" to a stateful system is a method | ||
call; the "output" may be a method call, if you need to invoke a side effect, | ||
or a return value, if you are just performing a computation in memory. Most | ||
other state-machine libraries require you to explicitly create an input object, | ||
provide that object to a generic "input" method, and then receive results, | ||
sometimes in terms of that library's interfaces and sometimes in terms of | ||
classes you define yourself. | ||
|
||
For example, a snippet of the coffee-machine example above might be implemented | ||
as follows in naive Python: | ||
|
||
```python | ||
class CoffeeMachine(object): | ||
def brewButton(self) -> None: | ||
if self.hasWater and self.hasBeans and not self.isLidOpen: | ||
self.heatTheHeatingElement() | ||
# ... | ||
``` | ||
|
||
With Automat, you'd begin with a `typing.Protocol` that describes all of your | ||
inputs: | ||
|
||
```python | ||
from typing import Protocol | ||
|
||
class CoffeeBrewer(Protocol): | ||
def brewButton(self) -> None: | ||
"The user pressed the 'brew' button." | ||
def putInBeans(self) -> None: | ||
"The user put in some beans." | ||
``` | ||
|
||
We'll then need a concrete class to contain the shared core of state shared | ||
among the different states: | ||
|
||
```python | ||
from dataclasses import dataclass | ||
|
||
@dataclass | ||
class BrewerCore: | ||
heatingElement: HeatingElement | ||
``` | ||
|
||
Next, we need to describe our state machine, including all of our states. For | ||
simplicity's sake let's say that the only two states are `noBeans` and | ||
`haveBeans`: | ||
|
||
```python | ||
from automat import TypeMachineBuilder | ||
|
||
builder = TypeMachineBuilder(CoffeeBrewer, BrewerCore) | ||
noBeans = builder.state("noBeans") | ||
haveBeans = builder.state("haveBeans") | ||
``` | ||
|
||
Next we can describe a simple transition; when we put in beans, we move to the | ||
`haveBeans` state, with no other behavior. | ||
|
||
```python | ||
# When we don't have beans, upon putting in beans, we will then have beans | ||
noBeans.upon(CoffeeBrewer.putInBeans).to(haveBeans).returns(None) | ||
``` | ||
|
||
And then another transition that we describe with a decorator, one that *does* | ||
have some behavior, that needs to heat up the heating element to brew the | ||
coffee: | ||
|
||
```python | ||
@haveBeans.upon(CoffeeBrewer.brewButton).to(noBeans) | ||
def heatUp(inputs: CoffeeBrewer, core: BrewerCore) -> None: | ||
""" | ||
When we have beans, upon pressing the brew button, we will then not have | ||
beans any more (as they have been entered into the brewing chamber) and | ||
our output will be heating the heating element. | ||
""" | ||
print("Brewing the coffee...") | ||
core.heatingElement.turnOn() | ||
``` | ||
|
||
Then we finalize the state machine by building it, which gives us a callable | ||
that takes a `BrewerCore` and returns a synthetic `CoffeeBrewer` | ||
|
||
```python | ||
newCoffeeMachine = builder.build() | ||
``` | ||
|
||
```python | ||
>>> coffee = newCoffeeMachine(BrewerCore(HeatingElement())) | ||
>>> machine.putInBeans() | ||
>>> machine.brewButton() | ||
Brewing the coffee... | ||
``` | ||
|
||
All of the *inputs* are provided by calling them like methods, all of the | ||
*output behaviors* are automatically invoked when they are produced according | ||
to the outputs specified to `upon` and all of the states are simply opaque | ||
tokens. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
../../Scripts/automat-visualize.exe,sha256=GsBuJiz0mTe3nKo7tGCTBx06uaE_yqWSmEAWNfmp9jk,108407 | ||
Automat-24.8.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 | ||
Automat-24.8.1.dist-info/LICENSE,sha256=siATAWeNCpN9k4VDgnyhNgcS6zTiPejuPzv_-9TA43Y,1053 | ||
Automat-24.8.1.dist-info/METADATA,sha256=XJIxL4Olb15WCoAdVEcORum39__wiCXQR6LNubERZ6M,8396 | ||
Automat-24.8.1.dist-info/RECORD,, | ||
Automat-24.8.1.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91 | ||
Automat-24.8.1.dist-info/entry_points.txt,sha256=D5Dc6byHpLWAktM443OHbx0ZGl1ZBZtf6rPNlGi7NbQ,62 | ||
Automat-24.8.1.dist-info/top_level.txt,sha256=vg4zAOyhP_3YCmpKZLNgFw1uMF3lC_b6TKsdz7jBSpI,8 | ||
automat/__init__.py,sha256=8yHAuqaxK0mdiOEXHbwe6WaNzaY01k2HMWD_RltPB-U,356 | ||
automat/__pycache__/__init__.cpython-38.pyc,, | ||
automat/__pycache__/_core.cpython-38.pyc,, | ||
automat/__pycache__/_discover.cpython-38.pyc,, | ||
automat/__pycache__/_introspection.cpython-38.pyc,, | ||
automat/__pycache__/_methodical.cpython-38.pyc,, | ||
automat/__pycache__/_runtimeproto.cpython-38.pyc,, | ||
automat/__pycache__/_typed.cpython-38.pyc,, | ||
automat/__pycache__/_visualize.cpython-38.pyc,, | ||
automat/_core.py,sha256=oe4QNlfvmgsnKe_8fyNiOsHsfz5xPArGuXWle9zePp8,6663 | ||
automat/_discover.py,sha256=KRbmm7kxpd-WReDQU4qe6hVKGUKmGBHUjYIkRneO4mc,5197 | ||
automat/_introspection.py,sha256=uF5ymY-GZckyRxvRs7UToPBV_oVV6xHmvlBVey9nv80,1441 | ||
automat/_methodical.py,sha256=YgZXraDe6dvK6w_Y9xfPa0kXCka4ZeGLfcb4IfK4bnI,17243 | ||
automat/_runtimeproto.py,sha256=mJ_4VuEGpLc1u7Ptm5cfaLUq7LGD7KfrvmsAa4LsyuU,1654 | ||
automat/_test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
automat/_test/__pycache__/__init__.cpython-38.pyc,, | ||
automat/_test/__pycache__/test_core.cpython-38.pyc,, | ||
automat/_test/__pycache__/test_discover.cpython-38.pyc,, | ||
automat/_test/__pycache__/test_methodical.cpython-38.pyc,, | ||
automat/_test/__pycache__/test_trace.cpython-38.pyc,, | ||
automat/_test/__pycache__/test_type_based.cpython-38.pyc,, | ||
automat/_test/__pycache__/test_visualize.cpython-38.pyc,, | ||
automat/_test/test_core.py,sha256=PJHNvQ85i8vjH-oF6nPNKB84_noTyl2dQSv_iRl70J8,3481 | ||
automat/_test/test_discover.py,sha256=ROnW7eSLE4T76FVncY2UK05DIYcHZ3TSGGg7kQnbvtw,22067 | ||
automat/_test/test_methodical.py,sha256=SKMMbl-6bjH-QZ1hDFRItCOyKF4SstuA4QvExnVhn7w,20267 | ||
automat/_test/test_trace.py,sha256=tty7P_ctJtk38ZXnpmEy-J9Rn-Hh2AKb_ia6EmtXSQI,3299 | ||
automat/_test/test_type_based.py,sha256=8oZxz3T7zIvyMKg4THg7M85zaHtE4QU9nAegU_OUvko,17872 | ||
automat/_test/test_visualize.py,sha256=HXBPgMAD0OTz_l1Yq0lI3d1vJ_l3sHTH67Jauaf-2sk,14631 | ||
automat/_typed.py,sha256=lMzMgUfX713Xw_W4pr8iyPqcdpRSbu4rEpRlrXAOW2k,24204 | ||
automat/_visualize.py,sha256=DQYig2mBKX-LquPEEy89Y_qyj21tSutAUaFsF1F64ws,6512 | ||
automat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Wheel-Version: 1.0 | ||
Generator: setuptools (72.2.0) | ||
Root-Is-Purelib: true | ||
Tag: py3-none-any | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[console_scripts] | ||
automat-visualize = automat._visualize:tool |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
automat |
Oops, something went wrong.