Unfortunately, I dont have a video. But take a look at https://mycroft.ai/documentation/skills/conversational-context/ as well.
When working with context there are two main findings I would like to share:
I use json to pass parameters from the method where the context is created, the the method where the context is used.
Dont use the @removes_context() decorator on methods where you use the set_context() inside the method
Ad 1) If you look at the example in the link above, you will see that self.set_context() takes a context name and a string as parameters, e.g: self.set_context(‘PythonPerson’, python). In may case, I have created an “Undo” context, that currently are able to delete a task that was created earlier. However, to delete it I need the exact identification on the task, which is a composite key, consisting of a task ID, a list ID and a tasklist ID. All three parameters are needed to uniquely identify the task. And these three parameters are a part of my context, even if Mycroft will not talk about them. Furthermore, to make an undo method, that can handle all kinds of undo operations comming in later releases, I add even more parameters to the context, like what to undo, and what mycroft should say after undoing. I need to pass all these parameters as a string in the set_context(context, string). I do that by converting the parameters to json, and parsing them serialized. Since the context is passed over the messagebus, it must be passed as a string.
I did not investigate this too much, but I found that in this construction:
The context A would be removed, but the context B would not be set. I don’t use the remove decorator if a context is added within the method. In my case, i use a “return early” pattern, which means that I may return successfully before adding a task to a list. Therefore I need the self.set_context() in the code after the task was added, I cannot use the @set_context() decorator.
If you want to see exactly what the code does, You can attach a Python debugger to the running instance.
However, Pycharm and its debugger may create files or install packages that may interfere with Mycroft, only do this if you understand what you are doing.
I use Pycharm community edition for debugging, it will add some files to the skills directory, which may prevent automatic update of the skill later, if used within Mycroft. You may want to make a backup copy before doing this, and restore it after.
In short, what I do:
- Start mycroft
- Open the Pycharm project in /opt/mycroft/skills/skill-the-cows-lists
- In Pycharm settings, set virtualenv to mycroft (requirements (imports) should be fulfilled after this)
- Put in breakpoints in
__init__.py where you want the debugger to stop
- On Ubuntu, allow ptrace (temporarely): echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
- Select run->attach to local process, attach to the process ending with mycroft/skills/main.py. The console should write Connected to pydev debugger
- Speak to mycroft to hit the method where your breakpoint is
- happy debugging
As an alternative, you may also run my unittests using Pycharm (or something else). This can (must be) done outside /opt/mycroft/skills/skill-the-cows-lists. So download skill-the-cows-lists to some folder.
Before the test can be run:
Create a file called test.cfg in the test sub-direstory, and add the RTM api_key and secret, like this:
Edit the file test_cow_rest.py, and change AUTH_TEST = False to AUTH_TEST = True
Change to virtualenv mycroft to fulfill requirements
Run the unittests in test_cow_rest.py
It will write an authentication link in the console. Click on the link, and authenticate in a browser. After authentication in the browser hit return in the unitest console.
The test should succeed
Edit the file test_cow_rest.py, and reset AUTH_TEST = True back to AUTH_TEST = False
After this both test_cow_rest.py and test__init__.py can be run, or debugged, to better see what the code does.