From ae205dad7909a1a81cb1b8dc1929285c7226ab6e Mon Sep 17 00:00:00 2001 From: Travis Abendshien <46939827+CyanVoxel@users.noreply.github.com> Date: Wed, 29 Jan 2025 17:06:56 -0800 Subject: [PATCH 1/2] fix: apply JSON user edits to built-in tag names and shorthands --- tagstudio/src/core/library/alchemy/library.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tagstudio/src/core/library/alchemy/library.py b/tagstudio/src/core/library/alchemy/library.py index f2d1c7b56..62212b515 100644 --- a/tagstudio/src/core/library/alchemy/library.py +++ b/tagstudio/src/core/library/alchemy/library.py @@ -199,6 +199,8 @@ def migrate_json_to_sqlite(self, json_lib: JsonLibrary): updated_tag = self.get_tag(tag.id) if not updated_tag: continue + updated_tag.name = tag.name + updated_tag.shorthand = tag.shorthand updated_tag.color_namespace = color_namespace updated_tag.color_slug = color_slug self.update_tag(updated_tag) # NOTE: This just calls add_tag? From e56cd323678256a2d881cd54701d6411f283bb8f Mon Sep 17 00:00:00 2001 From: Travis Abendshien <46939827+CyanVoxel@users.noreply.github.com> Date: Wed, 29 Jan 2025 17:07:36 -0800 Subject: [PATCH 2/2] fix: test for tag name parity when migrating from JSON --- tagstudio/resources/translations/en.json | 1 + tagstudio/src/qt/widgets/migration_modal.py | 59 ++++++++++++++++++--- tagstudio/tests/test_json_migration.py | 2 + 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/tagstudio/resources/translations/en.json b/tagstudio/resources/translations/en.json index ae48b3b65..6bfaf2714 100644 --- a/tagstudio/resources/translations/en.json +++ b/tagstudio/resources/translations/en.json @@ -129,6 +129,7 @@ "json_migration.heading.fields": "Fields:", "json_migration.heading.file_extension_list": "File Extension List:", "json_migration.heading.match": "Matched", + "json_migration.heading.names": "Names:", "json_migration.heading.parent_tags": "Parent Tags:", "json_migration.heading.paths": "Paths:", "json_migration.heading.shorthands": "Shorthands:", diff --git a/tagstudio/src/qt/widgets/migration_modal.py b/tagstudio/src/qt/widgets/migration_modal.py index cc16ef74f..b8b3f4a13 100644 --- a/tagstudio/src/qt/widgets/migration_modal.py +++ b/tagstudio/src/qt/widgets/migration_modal.py @@ -67,6 +67,7 @@ def __init__(self, path: Path): self.field_parity: bool = False self.path_parity: bool = False + self.name_parity: bool = False self.shorthand_parity: bool = False self.subtag_parity: bool = False self.alias_parity: bool = False @@ -116,6 +117,7 @@ def init_page_convert(self) -> None: entries_text: str = Translations["json_migration.heading.entires"] tags_text: str = Translations["json_migration.heading.tags"] + names_text: str = tab + Translations["json_migration.heading.names"] shorthand_text: str = tab + Translations["json_migration.heading.shorthands"] parent_tags_text: str = tab + Translations["json_migration.heading.parent_tags"] aliases_text: str = tab + Translations["json_migration.heading.aliases"] @@ -130,12 +132,13 @@ def init_page_convert(self) -> None: self.path_row: int = 1 self.fields_row: int = 2 self.tags_row: int = 3 - self.shorthands_row: int = 4 - self.parent_tags_row: int = 5 - self.aliases_row: int = 6 - self.colors_row: int = 7 - self.ext_row: int = 8 - self.ext_type_row: int = 9 + self.names_row: int = 4 + self.shorthands_row: int = 5 + self.parent_tags_row: int = 6 + self.aliases_row: int = 7 + self.colors_row: int = 8 + self.ext_row: int = 9 + self.ext_type_row: int = 10 old_lib_container: QWidget = QWidget() old_lib_layout: QVBoxLayout = QVBoxLayout(old_lib_container) @@ -152,6 +155,7 @@ def init_page_convert(self) -> None: self.old_content_layout.addWidget(QLabel(path_parity_text), self.path_row, 0) self.old_content_layout.addWidget(QLabel(field_parity_text), self.fields_row, 0) self.old_content_layout.addWidget(QLabel(tags_text), self.tags_row, 0) + self.old_content_layout.addWidget(QLabel(names_text), self.names_row, 0) self.old_content_layout.addWidget(QLabel(shorthand_text), self.shorthands_row, 0) self.old_content_layout.addWidget(QLabel(parent_tags_text), self.parent_tags_row, 0) self.old_content_layout.addWidget(QLabel(aliases_text), self.aliases_row, 0) @@ -167,6 +171,8 @@ def init_page_convert(self) -> None: old_field_value.setAlignment(Qt.AlignmentFlag.AlignRight) old_tag_count: QLabel = QLabel() old_tag_count.setAlignment(Qt.AlignmentFlag.AlignRight) + old_name_value: QLabel = QLabel() + old_name_value.setAlignment(Qt.AlignmentFlag.AlignRight) old_shorthand_count: QLabel = QLabel() old_shorthand_count.setAlignment(Qt.AlignmentFlag.AlignRight) old_subtag_value: QLabel = QLabel() @@ -184,6 +190,7 @@ def init_page_convert(self) -> None: self.old_content_layout.addWidget(old_path_value, self.path_row, 1) self.old_content_layout.addWidget(old_field_value, self.fields_row, 1) self.old_content_layout.addWidget(old_tag_count, self.tags_row, 1) + self.old_content_layout.addWidget(old_name_value, self.names_row, 1) self.old_content_layout.addWidget(old_shorthand_count, self.shorthands_row, 1) self.old_content_layout.addWidget(old_subtag_value, self.parent_tags_row, 1) self.old_content_layout.addWidget(old_alias_value, self.aliases_row, 1) @@ -193,6 +200,7 @@ def init_page_convert(self) -> None: self.old_content_layout.addWidget(QLabel(), self.path_row, 2) self.old_content_layout.addWidget(QLabel(), self.fields_row, 2) + self.old_content_layout.addWidget(QLabel(), self.names_row, 2) self.old_content_layout.addWidget(QLabel(), self.shorthands_row, 2) self.old_content_layout.addWidget(QLabel(), self.parent_tags_row, 2) self.old_content_layout.addWidget(QLabel(), self.aliases_row, 2) @@ -215,6 +223,7 @@ def init_page_convert(self) -> None: self.new_content_layout.addWidget(QLabel(path_parity_text), self.path_row, 0) self.new_content_layout.addWidget(QLabel(field_parity_text), self.fields_row, 0) self.new_content_layout.addWidget(QLabel(tags_text), self.tags_row, 0) + self.new_content_layout.addWidget(QLabel(names_text), self.names_row, 0) self.new_content_layout.addWidget(QLabel(shorthand_text), self.shorthands_row, 0) self.new_content_layout.addWidget(QLabel(parent_tags_text), self.parent_tags_row, 0) self.new_content_layout.addWidget(QLabel(aliases_text), self.aliases_row, 0) @@ -230,6 +239,8 @@ def init_page_convert(self) -> None: field_parity_value.setAlignment(Qt.AlignmentFlag.AlignRight) new_tag_count: QLabel = QLabel() new_tag_count.setAlignment(Qt.AlignmentFlag.AlignRight) + new_name_value: QLabel = QLabel() + new_name_value.setAlignment(Qt.AlignmentFlag.AlignRight) new_shorthand_count: QLabel = QLabel() new_shorthand_count.setAlignment(Qt.AlignmentFlag.AlignRight) subtag_parity_value: QLabel = QLabel() @@ -247,6 +258,7 @@ def init_page_convert(self) -> None: self.new_content_layout.addWidget(path_parity_value, self.path_row, 1) self.new_content_layout.addWidget(field_parity_value, self.fields_row, 1) self.new_content_layout.addWidget(new_tag_count, self.tags_row, 1) + self.new_content_layout.addWidget(new_name_value, self.names_row, 1) self.new_content_layout.addWidget(new_shorthand_count, self.shorthands_row, 1) self.new_content_layout.addWidget(subtag_parity_value, self.parent_tags_row, 1) self.new_content_layout.addWidget(alias_parity_value, self.aliases_row, 1) @@ -259,6 +271,7 @@ def init_page_convert(self) -> None: self.new_content_layout.addWidget(QLabel(), self.fields_row, 2) self.new_content_layout.addWidget(QLabel(), self.shorthands_row, 2) self.new_content_layout.addWidget(QLabel(), self.tags_row, 2) + self.new_content_layout.addWidget(QLabel(), self.names_row, 2) self.new_content_layout.addWidget(QLabel(), self.parent_tags_row, 2) self.new_content_layout.addWidget(QLabel(), self.aliases_row, 2) self.new_content_layout.addWidget(QLabel(), self.colors_row, 2) @@ -400,6 +413,7 @@ def migration_iterator(self): check_set = set() check_set.add(self.check_field_parity()) check_set.add(self.check_path_parity()) + check_set.add(self.check_name_parity()) check_set.add(self.check_shorthand_parity()) check_set.add(self.check_subtag_parity()) check_set.add(self.check_alias_parity()) @@ -425,6 +439,7 @@ def update_parity_ui(self): """Update all parity values UI.""" self.update_parity_value(self.fields_row, self.field_parity) self.update_parity_value(self.path_row, self.path_parity) + self.update_parity_value(self.names_row, self.name_parity) self.update_parity_value(self.shorthands_row, self.shorthand_parity) self.update_parity_value(self.parent_tags_row, self.subtag_parity) self.update_parity_value(self.aliases_row, self.alias_parity) @@ -688,6 +703,38 @@ def check_alias_parity(self) -> bool: self.alias_parity = True return self.alias_parity + def check_name_parity(self) -> bool: + """Check if all JSON tag names match the new SQL tag names.""" + sql_name: str = None + json_name: str = None + + def sanitize(value): + """Return value or convert a "not" value into None.""" + return value if value else None + + for tag in self.sql_lib.tags: + tag_id = tag.id # Tag IDs start at 0 + sql_name = sanitize(tag.name) + json_name = sanitize(self.json_lib.get_tag(tag_id).name) + + logger.info( + "[Name Parity]", + tag_id=tag_id, + json_shorthand=json_name, + sql_shorthand=sql_name, + ) + + if sql_name != json_name: + self.discrepancies.append( + f"[Name Parity][Tag ID: {tag_id}]:" + f"\nOLD (JSON):{json_name}\nNEW (SQL):{sql_name}" + ) + self.name_parity = False + return self.name_parity + + self.name_parity = True + return self.name_parity + def check_shorthand_parity(self) -> bool: """Check if all JSON shorthands match the new SQL shorthands.""" sql_shorthand: str = None diff --git a/tagstudio/tests/test_json_migration.py b/tagstudio/tests/test_json_migration.py index c8ad58e6c..c2bb25e99 100644 --- a/tagstudio/tests/test_json_migration.py +++ b/tagstudio/tests/test_json_migration.py @@ -30,6 +30,8 @@ def test_json_migration(): # Tags ===================================================================== # Count assert len(modal.json_lib.tags) == len(modal.sql_lib.tags) + # Name Parity + assert modal.check_name_parity() # Shorthand Parity assert modal.check_shorthand_parity() # Subtag/Parent Tag Parity