-
Notifications
You must be signed in to change notification settings - Fork 12
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
Migrate config to standard anki scheme (fixing 91 and 73) #96
base: main
Are you sure you want to change the base?
Conversation
Migrate config to the standard anki scheme - load with the anki function (support config-meta scheme) - monitor changes from inside the anki and update internal data (do not overwrite these changes with defaults)
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 for the PR! A few comments from me:
-
This changes the semantics of
self.config
. Previously it was adefaultdict
in which aKeyError
would not be thrown on an attempt to access a key which did not exist but now it is only adict
. Is this intentional and have you confirmed this change is safe? -
The proposed solution here will mean that any existing
config_saved.json
will be totally discarded. In order to try and be backwards compatible, we should first check for the existence of this file and if it exists thenaddonManager.writeConfig
it, at least for the next few releases then the check can be ripped out. -
This introduces a race condition where if config is updated from within the addon and then config is updated from within the Anki UI, the config from within the addon will be wiped out. Additionally, any config changes made from within the addon will not be visible in the Anki UI until
save
is called. -
It looks like the config updated callback passes the new config as an arg, we can use this for some cleaner code to avoid having intercept things with a lambda to ignore the args then calling
getConfig
again. Just usingself.update
as the callback could take care of this and also my point above about the race condition but not the point about changes not appearing in the UI. To fix everything and keep old behaviour would get kind of complicated but IMO we should go for the simplest thing here and rip out all the caching and thatsave
method and fully rely on Anki for the config, no maintaining of aself.config
copy. -
Now that we have stopped using them, could you remove the extra imports, namely:
from collections import defaultdict
from json import dump, load
from os.path import dirname, exists, join, realpath
Solution for installing in separate plugin directory
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.
Hey, I appreciate the effort here. I'm thinking this is not the right way forwards.
I think almost all the pitfalls we are looking at can be avoided by removing the self.config
variable and instead going through this procedure:
- On init, check if old
config_saved.json
exists, if it doesn't then we are done (firstRun
doesn't matter here). - If it does exist then load it,
.update
themw.addonManager.getConfig(__name__)
config with it then immediatelymw.addonManager.writeConfig(__name__, updated_config)
it. - If all this worked then move
config_saved.json
toconfig_saved.json.bak
.
def _get_old_addon_config_file() -> Path: | ||
apath = Path(mw.pm.addonFolder()) | ||
# This is mainly for tests, since 'current-module-dir is mocked, but we cannot mock/patch this function, | ||
# it is called at the import time, by main.py, ugh | ||
if exists(apath): | ||
ret = apath.resolve(strict=True) / '1752008591/config_saved.json' | ||
else: | ||
ret = None | ||
|
||
return ret |
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.
- it looks like
mw.addonManager.addonsFolder(__name__)
does what you want here? - if this can return
None
then the type hint should indicate that - we shouldn't be mixing old
os.path
stuff with the newpathlib
stuff - it feels wrong that this could return
None
if the path doesn't exist in one case but return a path that doesn't exist in another case, why do both? I think you can get rid of this function entirely.
self._load_config() | ||
mw.addonManager.setConfigUpdatedAction(__name__, lambda *_: self._config_updated_handler()) | ||
|
||
if self.config['firstRun']: |
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.
But now this forces everyone who updates to have firstRun
trigger to true, but it isn't necessarily their first runs.
spath = _get_old_addon_config_file() | ||
|
||
if spath and spath.is_file(): | ||
# Old MacDonald had a farm. E-I-E-I-O. |
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.
what?
showInfo( 'Configuration from the old "Chinese Support 3" was imported.\n\n' | ||
'This is a one-time post install action, if you update the configuration in the original addon, ' | ||
'it will not be synchronized.\n\n' | ||
'It is recommended to disable the old addon.') |
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 don't understand this, since there is an update there is no addon which needs to be disabled. I think this message should be removed entirely. We can perform this completely unbeknownst to the user.
for k in ['enabledModels', 'speech', 'target', 'max_examples', 'fields']: | ||
self.config[k] = config_saved[k] |
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.
No need to manually copy select fields, just copy all of it.
@@ -36,6 +36,7 @@ | |||
if config['firstRun']: | |||
dictionary.create_indices() | |||
config['firstRun'] = False | |||
config.save() # need for correct meta.json handling |
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.
We shouldn't need this. Our view of the config shouldn't get out of sync with the Anki view.
Hopefully fix #91 and fix #73
Migrate config to the standard anki scheme