-
-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add tracing API, with docs #56
Conversation
I am inclined to approve, but I think @markrwilliams might have some strong opinions about tracing and I'd like to confirm that he's happy with this API as well before committing to it. |
wormhole.debug_set_trace() won't work until glyph/automat#56 lands, but this should let travis do its job in the meantime.
I had another idea for connecting the "entering transition" message with all the "executing an output" messages: what if the log function can return a callable if it wants them? We'd promise to call the function once when entering the transition, but if it returns non-None then we call that function with each output. That would remove the closure in This would make it behave somewhat like |
wormhole.debug_set_trace() won't work until glyph/automat#56 lands, but this should let travis do its job in the meantime.
@warner Thanks for this PR! The approach looks great, but I prefer this:
...to indicating that a tracing call represents an input because its output argument is I'm also cagey about identifying inputs, states, and outputs by their names. Does the code do this so that These concerns are too small to prevent me from merging this PR after change to the tracing API, but I'd be interested in your thoughts. |
Ok, I'll implement the return-a-callable approach. I like that better too. I figured I'd pass strings into the logging callback to make it easier to print concise messages. I could pass the raw objects in, but then:
I have a branch that changes the str() for Outputs and States to be just the name, which might clean up the internal code a bit (removing the Let's think for a minute about the #37/#38 issues: we need a way, from outside the state machine, to refer to States, Inputs, Outputs, and transitions. At the moment, Automat tries very hard to hide these:
so we can currently get at Inputs and States, but not Outputs (and I think States might be an accident). If I'm grokking the Automat philosophy properly, client code has no need to see a State, so they ought to be hidden too. And there's certainly no Transitions don't have a distinct object: they're represented internally by tuples of states and inputs. #37 wants a way for a test class to refer to a transition, which maybe means a pair of States. I can see uses for things like There are multiple ways to get from one state to another (different Inputs, with different Outputs), so you might want to be more precise about your expectations, and refer to Inputs too. Would we want a test to assert something about the outputs? #38 might want something like a tracing function that accumulates transition coverage during a particular sequence of events (on a concrete instance), as So, should we rely on States remaining visible, and write these other APIs to reference them? Should we hide States but then add some sort of debug API that lets you access the underlying MethodicalMachine, from which you could read the MethodicalState object without the AttributeError? The things we expose for #37/#38 should probably influence what we pass to the tracing function for this ticket, if we're offering application code and/or tests the opportunity to compare them against each other. |
(re-pushing this branch as-is, rebased, without the return-a-callable change yet, just to make sure it works on py3.6, now that we have coverage for that). |
instead of passing the tracer an output= that is sometimes None
@warner I'm comfortable with using strings for now. As we discussed offline, I think Automat should expose a read-only view on the underlying It may be the case that none of these APIs end up being public, of course, so I think your suggestion of marking the tracing API as unstable is a good one. Can you add that to |
Ok, will do. I want to update my magic-wormhole code to match the new API, make sure it feels right, then I'll update the docs to caution folks against relying on this API and then land this. |
I don't believe in "provisional" APIs :). Just make the API private. If someone wants to call it, they can; but, as the rule is with any other private API, if you use it, you need to pin your dependency. |
Righto. The new recommended sample code will then look like:
which would make an app at least somewhat future-proof. For my code, I'm only actually calling set_trace when I'm debugging, so using a tolerant |
Ok, travis approves, so I'll land this now. Thanks for all your feedback! |
refs #36
This seems useful for my own debugging purposes, where the logging function is just
print()
.Some questions still in my mind:
__str__
of States/Inputs/Outputs be just the name of the method, and then have the tracer usestr(oldState)
instead ofoldState._name()
? I have a patch to improve the__str__
elsewhere, but I had been planning to make it be e.g."State($name)"
rather than just"$name"
.transition()
to be a tuple like that? And with defining theoutTracer
closure insidetransition()
? It seemed like the easiest way to get a linked tracing function intodoInput()
where the outputs actually get run. If we change the way that outputs get logged, maybe we could avoid doing that, somehow.