forked from Stvad/CrowdAnki
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow disambiguating duplicated note model UUIDs in collection
The issue of note model UUIDs being cloned along with the note models themselves has been fixed (Stvad#136). However, many users' collections will already contain such duplicated note model UUIDs. Also, if a user clones a note type on another platform, then the UUID will still be duplicated. The disambiguation is run before export and snapshot, since that's when it's most needed to avoid broken `deck.json`s. In the long, run we could perhaps switch to running the code only after syncing (since our "attack surface" would be cloning of note models on other platforms). Running `disambiguate_note_model_uuids` takes 10 ms on a collection with 20 note types (without duplicates), which is IMO an acceptable overhead. The file `disambiguate_uuids.py` could also contain the (far lower priority) disambiguation of deck config UUIDs (see Stvad#135).
- Loading branch information
Showing
3 changed files
with
64 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
from uuid import uuid1 | ||
|
||
from .notifier import AnkiModalNotifier | ||
|
||
def disambiguate_note_model_uuids(collection): | ||
"""Disambiguate duplicate note model UUIDs. | ||
In CrowdAnki ≤ 0.9, cloning a note model with an already assigned | ||
crowdanki_uuid resulted in the clone inheriting the "original's" | ||
crowdanki_uuid. | ||
This has been fixed (#136), but: | ||
1. Users will still have duplicate UUIDs from before the upgrade. | ||
2. Users who create note models on platforms other than Anki with | ||
CrowdAnki installed — for instance on mobile — will still have the | ||
old issue, since cloning note models on those platforms will again | ||
clone UUIDs. | ||
""" | ||
notifier = AnkiModalNotifier() | ||
uuids = [] | ||
full_message = "" | ||
for model in filter(lambda model: "crowdanki_uuid" in model, | ||
sorted(collection.models.all(), key=lambda m: m["id"])): | ||
# We're sorting by note model id, because it almost always | ||
# (see the discussion in the PR for this addition) corresponds | ||
# to the time of creation of the note model, in milliseconds | ||
# since the epoch, so the copies will almost always have | ||
# larger ids than the originals, so we'll hopefully be | ||
# changing the UUIDs of the copies, not the originals. | ||
crowdanki_uuid = model["crowdanki_uuid"] | ||
if crowdanki_uuid in uuids: | ||
new_crowdanki_uuid = str(uuid1()) | ||
model["crowdanki_uuid"] = new_crowdanki_uuid | ||
collection.models.save(model) | ||
message = (f"Replacing duplicate UUID ({crowdanki_uuid}) for note model " | ||
f"“{model['name']}” with new UUID ({new_crowdanki_uuid})!\n") | ||
# Printing in the unlikely case there's a crash later in | ||
# the loop. | ||
print(message) | ||
full_message += message | ||
else: | ||
uuids.append(crowdanki_uuid) | ||
|
||
if full_message: | ||
full_message += ( | ||
"\nFor details, please see " | ||
"https://github.com/Stvad/CrowdAnki/wiki/Workarounds-—-Duplicate-note-model-uuids .\n\n" | ||
"The replacement should be a one-off occurrence. " | ||
"If this message appears frequently, please open an issue!" | ||
) | ||
notifier.info("UUIDs disambiguated", full_message) |