-
-
Notifications
You must be signed in to change notification settings - Fork 402
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
reload: Reloading packaged modules doesn't work correctly #1056
Comments
I have reproduced this on python 2.7, 3.4, and 3.5. |
Is there a workaround for this issue? It's making it impossible to use Sopel in production environments. I'm considering merging my out of tree modules into the Sopel source code to prevent it. It isn't limited to reloads, reconnecting to the server after a network problem causes this issue as well so you have absolutely no idea of the moment when your bot will go haywire. |
I guess my bot is blessedly connected to a stable ZNC instance on the same host, so I've never observed this issue after a reconnection (because Sopel never has to reconnect). Frankly, I'm surprised that a bug like this even made it into a stable release. But we also have other things that should have been caught before release, such as #1136 or (arguably) #1080. Sopel might do with more stringent testing, and more code review, but that would require more maintainers to step up. I'd be willing to help out with that, and with testing releases in advance if the project started having pre-release builds. (@maxpowa and @embolalia, I can write up some thoughts on development/release process in separate issue, or find a time when we can chat on IRC, if you're interested.) |
I agree on the points about more stringent testing & code review, something in that direction would be running our tests on commits and PR branches. Unfortunately I don't have permission to set up travis on this repo, but if @embolalia or @elad661 were to, there's already a basic test suite that could be improved upon (it has around 50% coverage, not including modules, at the time of this comment). |
This is a blocker for starting #1291. |
Is there some kind of a flowchart or a textual explanation of how the reloading mechanism works? I'd like to understand the ideology of how this is supposed to work, and perhaps try to contribute. |
I'd have to make one, I think. AFAIK there's no real documentation except the code & comments therein. But the idea is pretty simple, just register callables and module shutdown functions on load & unregister them on unload. Reload = unload followed immediately by load. The issue is that existing triggers don't get removed for packaged modules, probably because the loader is only looking at a single file, the one |
I'd love to, but how could I?
This results in: |
Oh, sorry about that. Github masks the source fork when commits are referenced like that, and I didn't push the branch to this repo yet. Add |
The test on Python 2.7.12 was successful, I reloaded the module a couple of times via On 2.7.3 the installation itself fails with
|
It was quite satisfying to finally fix, too. :-) There's still testing to be done regarding how the new reloading code handles updated methods (seems to work), removed methods (not tested yet), and added methods (ditto), whether in the I'm not sure how far back Sopel's 2.7 support is meant to go, but I don't think that error should happen. |
Something like this in
This way |
|
What prevents this update from being part of the current release? Is there something I could to do make it happen? The tests above were successful and I would love to be able to upgrade my Sopel instances to this version. |
Depending on how you're installing Sopel, you can run tag v6.5.3 with PR #1314 applied to it until the next official release. There are a bunch of fixes I want to get done before 6.6.0, and since most of them have already been broken for ages there's no particular reason to rush and push out a new release every time something's fixed. (I'm also hoping to get a chance to work with #1053's author, because it touches reloading too.) |
sopel-irl#1314 used recursion to reload nested modules. However, in Python 2 (maybe python 3 as well), this approach leads to odd behavior with callables being unloaded/reloaded twice. The loop detects my_module.my_callable and my_callable as two separate modules to reload. The first time it detects it, the rule is added to bot._callables as a string. I combined patched dgw branch 1056-no-dupes onto 1056-fix-with-recursion, to provide a more optimal solution to issue sopel-irc#1056.
Force-reload all sub-modules of packages recursively. See sopel-irc#1056.
sopel-irl#1314 used recursion to reload nested modules. However, in Python 2 (maybe python 3 as well), this approach leads to odd behavior with callables being unloaded/reloaded twice. The loop detects my_module.my_callable and my_callable as two separate modules to reload. The first time it detects it, the rule is added to bot._callables as a string. I combined patched dgw branch 1056-no-dupes onto 1056-fix-with-recursion, to provide a more optimal solution to issue sopel-irc#1056.
Force-reload all sub-modules of packages recursively. See sopel-irc#1056.
sopel-irl#1314 used recursion to reload nested modules. However, in Python 2 (maybe python 3 as well), this approach leads to odd behavior with callables being unloaded/reloaded twice. The loop detects my_module.my_callable and my_callable as two separate modules to reload. The first time it detects it, the rule is added to bot._callables as a string. I combined patched dgw branch 1056-no-dupes onto 1056-fix-with-recursion, to provide a more optimal solution to issue sopel-irc#1056.
wolfram alpha module module is affected as well. A .reload will make it respond +1 times |
@Duckle29 Of course. The wolfram module is based on the cookiecutter template. The replacement weather and imdb modules @RustyBower put up will be affected, too, I expect. Did you try #1314 at all? I could hold the release of 6.6.0 for a day or two if you want to test it out. |
I just tested against #1314 and it is definitely causing all my modules to respond n+1 times |
@RustyBower Merging #1314 causes all your modules to repeat? That can't be right… though I haven't tested it in some time, it did help when I was working on it myself. |
nvm, @dgw seemed to have pinned it down |
I hijacked @maxpowa's OP to list the remaining known issues, rather than closing this and opening a new ticket, so all the discussion of this very complex problem will remain in (mostly) one place. |
sopel-irl#1314 used recursion to reload nested modules. However, in Python 2 (maybe python 3 as well), this approach leads to odd behavior with callables being unloaded/reloaded twice. The loop detects my_module.my_callable and my_callable as two separate modules to reload. The first time it detects it, the rule is added to bot._callables as a string. I combined patched dgw branch 1056-no-dupes onto 1056-fix-with-recursion, to provide a more optimal solution to issue sopel-irc#1056.
sopel-irl#1314 used recursion to reload nested modules. However, in Python 2 (maybe python 3 as well), this approach leads to odd behavior with callables being unloaded/reloaded twice. The loop detects my_module.my_callable and my_callable as two separate modules to reload. The first time it detects it, the rule is added to bot._callables as a string. I combined patched dgw branch 1056-no-dupes onto 1056-fix-with-recursion, to provide a more optimal solution to issue sopel-irc#1056.
Cannot get def setup(bot):
global interval_count
interval_count = 0
@sopel.module.interval(1)
def interval_callable(bot, extra='a'):
global interval_count
interval_count += 1
bot.say('extra: {}; count: {}'.format(extra, interval_count), '#sopel-dev') This Clearing all |
@HumorBaby It's looking more and more like #1053 won't ever get merged, because its author has been silent for quite a while now. If you want to adopt some elements from that (cherry-pick or whatever), feel free. I'm sure @calebj wouldn't mind if you pulled in some stuff with his name on the commit. |
Force-reload all sub-modules of packages recursively. See sopel-irc#1056.
Just a note here: the [at]interval thing and the JobScheduler have been fixed in Sopel 7.x. |
Punting this to 8.0: We need tools that aren't available in older Python versions to fix this, and 8.0 will drop support for all the versions that block implementing saner reload. |
De-milestoning for the same reason as #871: No further changes to the plugin system are planned during 8.x development. |
Remaining known issues with reloading module packages:
@interval
might still be duplicated on reloadThese are based on further discussion of this in #1399 and elsewhere (IRC).
Original comment (mostly fixed) from @maxpowa appears below. — @dgw
Doesn't reload the actual module and only reloads the__init__.py
. Probably needs some tweaks toloader.py
andreload.py
. Because it only reloads the__init__.py
, when the module loads after the reload, there will be two instances of the package running. Problem exists with bothsopel_modules
namespace packages and packages in~/.sopel/modules
.The text was updated successfully, but these errors were encountered: