[Twisted-Python] automat question
Hi, Apologies if there's a better list for this, please let me know where... I've grown to like Glyph's automat package a lot, but in a current project, I have observers that need to know when a machine changes state. What's the best way to let those observers know? cheers, Chris
Automat is designed to make this sort of thing intentionally annoying, as you have discovered:). The idea is that if you want to know this sort of internal state, it’s for a specific reason. That's not a blanket "No" — see for example how automat deals with serialization — but each such interface should be minimal and thoughtfully designed. Otherwise a state machine library just becomes a bunch of complex infrastructure around making an arbitrary series of function calls, and loses all of its helpful formalisms. So probably we do need to make a change to automat if you really need to do this, but first it's important to know what your use-case is. In a lot of cases the answer is "just make an output. Stop trying to make the application see into the guts of the framework." But without knowing it’s impossible to say! -g
Hi,
Apologies if there's a better list for this, please let me know where...
I've grown to like Glyph's automat package a lot, but in a current project, I have observers that need to know when a machine changes state.
What's the best way to let those observers know?
cheers,
Chris
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
I'm not sure we're quite on the same page: I'm not looking to inspect the state, but more be notified when certain edges are traversed. That said: what's the best practice when you want to visualize the current state of a machine? In this case, the machine is for a unit of work in a scheduling app, and the UI has a list of these units where it'd make sense to show the current state. The unit of work also forms the boundary API between the from end object model and the pool/scheduling back end. As such, each side can naturally call inputs methods on the machine, as I believe automat intends, but it's how to get notified by an output? So, the front end may want to say "I no longer need this UoW done, please kill it", the back end then needs to run the code to kill whatever's running the UoW. Likewise, when the backend finishes a UoW, it wants to call either machine.result(...) or machine.error(...) to say what happened, but how do I wire in the front end bit that needs to get called when this happens? cheers, Chris On 07/03/2021 22:34, Glyph wrote:
Automat is designed to make this sort of thing intentionally annoying, as you have discovered:).
The idea is that if you want to know this sort of internal state, it’s for a specific reason. That's not a blanket "No" — see for example how automat deals with serialization — but each such interface should be minimal and thoughtfully designed. Otherwise a state machine library just becomes a bunch of complex infrastructure around making an arbitrary series of function calls, and loses all of its helpful formalisms.
So probably we do need to make a change to automat if you really need to do this, but first it's important to know what your use-case is. In a lot of cases the answer is "just make an output. Stop trying to make the application see into the guts of the framework." But without knowing it’s impossible to say!
-g
Hi,
Apologies if there's a better list for this, please let me know where...
I've grown to like Glyph's automat package a lot, but in a current project, I have observers that need to know when a machine changes state.
What's the best way to let those observers know?
cheers,
Chris
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
On Mar 9, 2021, at 3:18 AM, Chris Withers <chris@withers.org> wrote:
I'm not sure we're quite on the same page: I'm not looking to inspect the state, but more be notified when certain edges are traversed.
The way you get notified when an edge is traversed is you add an output to that edge :). When I was talking about "internal state", what I meant was not the literal current state atom of the machine, but the presence and names of states and edges themselves. Within the abstraction of the state machine, the way you find out that an edge was traversed by having an output run.
That said: what's the best practice when you want to visualize the current state of a machine? In this case, the machine is for a unit of work in a scheduling app, and the UI has a list of these units where it'd make sense to show the current state.
This is definitely a gap. I think today the best way to do this would be to have an event emitted by an output that invokes the serialization code to discover the state and have the UI show that.
The unit of work also forms the boundary API between the from end object model and the pool/scheduling back end. As such, each side can naturally call inputs methods on the machine, as I believe automat intends, but it's how to get notified by an output?
The output can just... call a UI observer?
So, the front end may want to say "I no longer need this UoW done, please kill it", the back end then needs to run the code to kill whatever's running the UoW. Likewise, when the backend finishes a UoW, it wants to call either machine.result(...) or machine.error(...) to say what happened, but how do I wire in the front end bit that needs to get called when this happens?
Again... have outputs. I think there's something you're leaving out about how you want to have some generalized output, but without knowing a bit more it's hard to say how it could help more :). -g
cheers,
Chris
On 07/03/2021 22:34, Glyph wrote:
Automat is designed to make this sort of thing intentionally annoying, as you have discovered:).
The idea is that if you want to know this sort of internal state, it’s for a specific reason. That's not a blanket "No" — see for example how automat deals with serialization — but each such interface should be minimal and thoughtfully designed. Otherwise a state machine library just becomes a bunch of complex infrastructure around making an arbitrary series of function calls, and loses all of its helpful formalisms.
So probably we do need to make a change to automat if you really need to do this, but first it's important to know what your use-case is. In a lot of cases the answer is "just make an output. Stop trying to make the application see into the guts of the framework." But without knowing it’s impossible to say!
-g
Hi,
Apologies if there's a better list for this, please let me know where...
I've grown to like Glyph's automat package a lot, but in a current project, I have observers that need to know when a machine changes state.
What's the best way to let those observers know?
cheers,
Chris
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com <mailto:Twisted-Python@twistedmatrix.com> https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python <https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python>
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com <mailto:Twisted-Python@twistedmatrix.com> https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python <https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python>
On 09/03/2021 18:53, Glyph wrote:
On Mar 9, 2021, at 3:18 AM, Chris Withers <chris@withers.org <mailto:chris@withers.org>> wrote:
I'm not sure we're quite on the same page: I'm not looking to inspect the state, but more be notified when certain edges are traversed.
The way you get notified when an edge is traversed is you add an output to that edge :).
Right, but as best I can tell, outputs in automat have to be defined as part of the state machine class, I need targets only available after class instantiation to be notified.
Again... have outputs. I think there's something you're leaving out about how you want to have some /generalized/ output, but without knowing a bit more it's hard to say how it could help more :).
I think it's what I said above. TBH, I'm probably going to end up writing "yet another state machine class" that does just what I need, but I think that's okay - not everything has to work for every situation :-) cheers, Chris
On Mar 15, 2021, at 1:18 AM, Chris Withers <chris@withers.org> wrote:
On 09/03/2021 18:53, Glyph wrote:
On Mar 9, 2021, at 3:18 AM, Chris Withers <chris@withers.org <mailto:chris@withers.org>> wrote:
I'm not sure we're quite on the same page: I'm not looking to inspect the state, but more be notified when certain edges are traversed. The way you get notified when an edge is traversed is you add an output to that edge :).
Right, but as best I can tell, outputs in automat have to be defined as part of the state machine class, I need targets only available after class instantiation to be notified.
Outputs are just methods, so it sort of depends what you mean by "after class instantiation". You can call whatever you want in an output.
Again... have outputs. I think there's something you're leaving out about how you want to have some /generalized/ output, but without knowing a bit more it's hard to say how it could help more :).
I think it's what I said above. TBH, I'm probably going to end up writing "yet another state machine class" that does just what I need, but I think that's okay - not everything has to work for every situation :-)
It sounds like what you might want here is soemthing for constructing arbitrary machines at runtime, and automat is all about enforcing that your machine is static so that (for example) it can be visualized statically. So yeah in that case, different library. -g
On 15/03/2021 09:34, Glyph wrote:
Right, but as best I can tell, outputs in automat have to be defined as part of the state machine class, I need targets only available after class instantiation to be notified.
Outputs are just methods, so it sort of depends what you mean by "after class instantiation". You can call whatever you want /in/ an output.
Right, but then I'd have to maintain my own list of subscribers and figure out a way to duplicate in that logic in each of the output methods defined on the machine.
Again... have outputs. I think there's something you're leaving out about how you want to have some /generalized/ output, but without knowing a bit more it's hard to say how it could help more :).
I think it's what I said above. TBH, I'm probably going to end up writing "yet another state machine class" that does just what I need, but I think that's okay - not everything has to work for every situation :-)
It sounds like what you /might/ want here is soemthing for constructing arbitrary machines at runtime,
The states and transitions are very rigid.
and automat is all about enforcing that your machine is static so that (for example) it can be visualized statically. So yeah in that case, different library.
Take this example: class LightSwitch(object): _machine = MethodicalMachine() @_machine.state(serialized="on") def on_state(self): "the switch is on" @_machine.state(serialized="off", initial=True) def off_state(self): "the switch is off" @_machine.input() def flip(self): "flip the switch" on_state.upon(flip, enter=off_state, outputs=[]) off_state.upon(flip, enter=on_state, outputs=[]) What I'm looking to do is something along the lines of: aSwitch = LightSwitch() aSwitch.flip.addListener(myCallable) myCallable might well be a deferred that something else is waiting on... Chris
On Mar 16, 2021, at 1:09 AM, Chris Withers <chris@withers.org> wrote:
On 15/03/2021 09:34, Glyph wrote:
Right, but as best I can tell, outputs in automat have to be defined as part of the state machine class, I need targets only available after class instantiation to be notified. Outputs are just methods, so it sort of depends what you mean by "after class instantiation". You can call whatever you want /in/ an output.
Right, but then I'd have to maintain my own list of subscribers and figure out a way to duplicate in that logic in each of the output methods defined on the machine.
Again... have outputs. I think there's something you're leaving out about how you want to have some /generalized/ output, but without knowing a bit more it's hard to say how it could help more :).
I think it's what I said above. TBH, I'm probably going to end up writing "yet another state machine class" that does just what I need, but I think that's okay - not everything has to work for every situation :-) It sounds like what you /might/ want here is soemthing for constructing arbitrary machines at runtime,
The states and transitions are very rigid.
and automat is all about enforcing that your machine is static so that (for example) it can be visualized statically. So yeah in that case, different library.
Take this example:
class LightSwitch(object): _machine = MethodicalMachine()
@_machine.state(serialized="on") def on_state(self): "the switch is on"
@_machine.state(serialized="off", initial=True) def off_state(self): "the switch is off"
@_machine.input() def flip(self): "flip the switch"
on_state.upon(flip, enter=off_state, outputs=[]) off_state.upon(flip, enter=on_state, outputs=[])
What I'm looking to do is something along the lines of:
aSwitch = LightSwitch() aSwitch.flip.addListener(myCallable)
myCallable might well be a deferred that something else is waiting on...
Thanks for the example. My opinion is definitely that this should be an output produced by both edges here, and that output should manage an observer which does this extra functionality. By modeling it as an output, you can see in your visual DFA where observers will be notified; and managing the list of observers is something that might have its own state-controlled lifecycle. You can disagree of course but I think that's a very different design idiom than automat :) -g
participants (2)
-
Chris Withers
-
Glyph