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
Make it possible to create class-based skills #734
Make it possible to create class-based skills #734
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for raising this. Looks interesting!
I have a few questions about your design decisions. Could you please respond to each one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I am understanding more the approach you are taking. However I'm still not happy with it. We should be able to use the same matcher decorators as we do normally.
Let me try to describe the problem you experienced which caused you to fork the API:
- When you create a skill class and import it the matchers are run against the unbound methods and update the method attributes with the matcher info.
- Then you are creating an instance of the class and creating pointers to the bound methods of the instance.
- The existing code then tries to set the
config
attribute on the bound method which fails because you cannot do that. - Your solution is to store the config in
__skill_attrs__
which you are pre-creating in the__init__
method.
Perhaps as an alternative approach you could try this:
- Catch the exception raised when trying to set the config on the method and ignore it.
- Access the config at
skill.__self__.config
in the parser.
Codecov Report
@@ Coverage Diff @@
## master #734 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 29 30 +1
Lines 1901 1934 +33
=====================================
+ Hits 1901 1934 +33
Continue to review full report at Codecov.
|
I have reworked the whole thing (and learned a bit about Python internals while there). Now it works fine with the original decorators, without modifying the decorators themselves; it was much easier than i initially thought. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks even better than I imagined! This is a very nice way to add this functionality.
Could you now add tests and documentation for this.
Also we currently run a setup
function for each skill if it exists. However after this change I think we should encourage people to use the class version going forwards and put their setup code in the __init__
method. So could you please add a deprecation warning message when the setup is called telling people that this will be removed in a future version.
for name in skill_obj.__dir__(): | ||
try: | ||
method = getattr(skill_obj, name) | ||
except Exception: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make this less broad?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, no. Imagine this code:
class MySkill(Skill):
@property
def erroneous_property(self):
return self.sdk_this_skill_uses.get_erroneous_property()
Where get_erroneous_property()
can raise any type of exception. Been there, done that 😞
We can either remove the try/except altogether and ask skill writers to look out for this corner case, or leave the except block this broad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough! Can you please add a pylint disable with this justification in a commend. See here for an example of this.
Should the deprecation warning be an actual |
Also, should the deprecation message appear if a function based skill is used, even if there is no |
We should probably be raising deprecation warnings. No we should only show it if the skill uses it. |
@gergelypolonkai I'm really keen to get this merged. Any chance you can pick it up again? |
I’m a bit lost in the tests, but expect to finish soon. |
e950db5
to
528e6f0
Compare
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Hi @gergelypolonkai. Are you able to pick this up again? |
Most definitely! I really want to finish this, it’s just my $job that intervened. |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
528e6f0
to
3a251b5
Compare
Given i just got my second “stale” message, i hereby ask for some help. I tried to create a test for the class based skills, and for that i have created a |
You should be able to create an opsdroid instance, preferably using the context manager. Then you have a few options. You could either mock out |
* Bump Pyyaml to avoid CVE-2017-18342 * Add SafeLoader to yaml.load * Add test for fix
…oid#807) * Support custom webhook response * Add tests for custom webhook response * Add docs for custom webhook response
…/opsdroid into gergelypolonkai-class-based-skills
Well it has taken a couple of months and some back and forth but it looks like this is ready to merge. Thanks for all the hard work @gergelypolonkai. I've managed to find some time today to sit down and sort out the tests and documentation, I understand how hard it can be to find time to pick these things back up again. Ping me your address via DM on Twitter or Gitter and I'll post you some opsdroid stickers! |
Description
Make it possible to create class-based skills. This can be very useful when the skill needs a helper object, like an SDK for an external API.
Status
UNDER DEVELOPMENT
Type of change
How Has This Been Tested?
I created a very basic skill class for initial testing, but generic tests are still yet to come.
Checklist: