From c29c35d8d1b590bdf01d9ae00de5d149736ab302 Mon Sep 17 00:00:00 2001 From: Josef Friedrich Date: Sat, 27 Jan 2024 11:26:00 +0100 Subject: [PATCH] Clean up meta --- README.rst | 74 +--------- docs/cli.rst | 74 +--------- mscxyz/cli.py | 48 +------ mscxyz/fields.py | 4 + mscxyz/meta.py | 319 +++---------------------------------------- tests/test_fields.py | 10 ++ tests/test_meta.py | 317 ++++-------------------------------------- 7 files changed, 71 insertions(+), 775 deletions(-) diff --git a/README.rst b/README.rst index 9edc0d1..d86b3ec 100644 --- a/README.rst +++ b/README.rst @@ -314,9 +314,9 @@ CLI Usage [-l ] [-y] [-S DESTINATION_FIELD FORMAT_STRING] [--metatag ] [--vbox ] - [--combined ] [-x LYRICS_EXTRACT] - [-r LYRICS_REMAP] [-F] [--rename] [-f RENAME_FORMAT] - [-A] [-a] [-n] [-K FIELDS] [-t RENAME_TARGET] [-L] + [-x LYRICS_EXTRACT] [-r LYRICS_REMAP] [-F] [--rename] + [-f RENAME_FORMAT] [-A] [-a] [-n] [-K FIELDS] + [-t RENAME_TARGET] [-L] [-g | --mscz | --mscx] [-s ] [--clean] [-Y ] [--s3] [--s4] [--list-fonts] [--text-font ] @@ -419,34 +419,6 @@ CLI Usage - composer (1. vbox_composer 2. metatag_composer) - lyricist (1. vbox_lyricist 2. metatag_lyricist) - You have access to all this metadata fields through following fields: - - - combined_composer - - combined_lyricist - - combined_subtitle - - combined_title - - metatag_arranger - - metatag_audio_com_url - - metatag_composer - - metatag_copyright - - metatag_creation_date - - metatag_lyricist - - metatag_movement_number - - metatag_movement_title - - metatag_msc_version - - metatag_platform - - metatag_poet - - metatag_source - - metatag_source_revision_id - - metatag_subtitle - - metatag_translator - - metatag_work_number - - metatag_work_title - - vbox_composer - - vbox_lyricist - - vbox_subtitle - - vbox_title - -c META_CLEAN, --clean-meta META_CLEAN Clean the meta data fields. Possible values: „all“ or a comma separated list of fields, for example: @@ -484,10 +456,6 @@ CLI Usage --vbox , --vbox-meta Define the metadata in VBox elements. Available fields: composer, lyricist, subtitle, title. - --combined , --combined-meta - Define the metadata combined in one step for MetaTag and - VBox elements. Available fields: composer, lyricist, - subtitle, title. lyrics: -x LYRICS_EXTRACT, --extract LYRICS_EXTRACT, --extract-lyrics LYRICS_EXTRACT @@ -508,42 +476,6 @@ CLI Usage rename: Rename the “*.msc[zx]” files.Fields and functions you can use in the format string (-f, --format): - Fields - ====== - - - combined_composer - - combined_lyricist - - combined_subtitle - - combined_title - - metatag_arranger - - metatag_audio_com_url - - metatag_composer - - metatag_copyright - - metatag_creation_date - - metatag_lyricist - - metatag_movement_number - - metatag_movement_title - - metatag_msc_version - - metatag_platform - - metatag_poet - - metatag_source - - metatag_source_revision_id - - metatag_subtitle - - metatag_translator - - metatag_work_number - - metatag_work_title - - readonly_abspath - - readonly_basename - - readonly_dirname - - readonly_extension - - readonly_filename - - readonly_relpath - - readonly_relpath_backup - - vbox_composer - - vbox_lyricist - - vbox_subtitle - - vbox_title - Functions ========= diff --git a/docs/cli.rst b/docs/cli.rst index 26c7864..1c5953b 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -12,9 +12,9 @@ Comande line interface [-l ] [-y] [-S DESTINATION_FIELD FORMAT_STRING] [--metatag ] [--vbox ] - [--combined ] [-x LYRICS_EXTRACT] - [-r LYRICS_REMAP] [-F] [--rename] [-f RENAME_FORMAT] - [-A] [-a] [-n] [-K FIELDS] [-t RENAME_TARGET] [-L] + [-x LYRICS_EXTRACT] [-r LYRICS_REMAP] [-F] [--rename] + [-f RENAME_FORMAT] [-A] [-a] [-n] [-K FIELDS] + [-t RENAME_TARGET] [-L] [-g | --mscz | --mscx] [-s ] [--clean] [-Y ] [--s3] [--s4] [--list-fonts] [--text-font ] @@ -117,34 +117,6 @@ Comande line interface - composer (1. vbox_composer 2. metatag_composer) - lyricist (1. vbox_lyricist 2. metatag_lyricist) - You have access to all this metadata fields through following fields: - - - combined_composer - - combined_lyricist - - combined_subtitle - - combined_title - - metatag_arranger - - metatag_audio_com_url - - metatag_composer - - metatag_copyright - - metatag_creation_date - - metatag_lyricist - - metatag_movement_number - - metatag_movement_title - - metatag_msc_version - - metatag_platform - - metatag_poet - - metatag_source - - metatag_source_revision_id - - metatag_subtitle - - metatag_translator - - metatag_work_number - - metatag_work_title - - vbox_composer - - vbox_lyricist - - vbox_subtitle - - vbox_title - -c META_CLEAN, --clean-meta META_CLEAN Clean the meta data fields. Possible values: „all“ or a comma separated list of fields, for example: @@ -182,10 +154,6 @@ Comande line interface --vbox , --vbox-meta Define the metadata in VBox elements. Available fields: composer, lyricist, subtitle, title. - --combined , --combined-meta - Define the metadata combined in one step for MetaTag and - VBox elements. Available fields: composer, lyricist, - subtitle, title. lyrics: -x LYRICS_EXTRACT, --extract LYRICS_EXTRACT, --extract-lyrics LYRICS_EXTRACT @@ -206,42 +174,6 @@ Comande line interface rename: Rename the “*.msc[zx]” files.Fields and functions you can use in the format string (-f, --format): - Fields - ====== - - - combined_composer - - combined_lyricist - - combined_subtitle - - combined_title - - metatag_arranger - - metatag_audio_com_url - - metatag_composer - - metatag_copyright - - metatag_creation_date - - metatag_lyricist - - metatag_movement_number - - metatag_movement_title - - metatag_msc_version - - metatag_platform - - metatag_poet - - metatag_source - - metatag_source_revision_id - - metatag_subtitle - - metatag_translator - - metatag_work_number - - metatag_work_title - - readonly_abspath - - readonly_basename - - readonly_dirname - - readonly_extension - - readonly_filename - - readonly_relpath - - readonly_relpath_backup - - vbox_composer - - vbox_lyricist - - vbox_subtitle - - vbox_title - Functions ========= diff --git a/mscxyz/cli.py b/mscxyz/cli.py index f24b550..7ec725d 100644 --- a/mscxyz/cli.py +++ b/mscxyz/cli.py @@ -13,7 +13,7 @@ import mscxyz.export from mscxyz import utils -from mscxyz.meta import Combined, Interface, InterfaceReadWrite, Metatag, Vbox +from mscxyz.meta import Metatag, Vbox from mscxyz.rename import rename from mscxyz.score import Score from mscxyz.settings import parse_args @@ -28,13 +28,6 @@ def __inch(value: str) -> float: return Dimension(value).to("in") -def __itemized_fields(fields: Sequence[str], prefix: str = "", suffix: str = "") -> str: - out: list[str] = [] - for field in fields: - out.append(prefix + "- " + field + suffix) - return "\n".join(out) - - def __embed_fields( fields: Sequence[str], prefix: str = " Available fields: ", suffix: str = "." ) -> str: @@ -240,11 +233,8 @@ def _split_lines(self, text: typing.Text, width: int) -> typing.List[str]: - subtitle (1. vbox_subtitle 2. metatag_movement_title) - composer (1. vbox_composer 2. metatag_composer) - lyricist (1. vbox_lyricist 2. metatag_lyricist) - - You have access to all this metadata fields through following fields:""" - ) - + "\n\n" - + __itemized_fields(InterfaceReadWrite.get_all_fields(), prefix=" "), + """ + ), ) group_meta.add_argument( @@ -341,17 +331,6 @@ def _split_lines(self, text: typing.Text, width: int) -> typing.List[str]: help="Define the metadata in VBox elements." + __embed_fields(Vbox.fields), ) -group_meta.add_argument( - "--combined", - "--combined-meta", - nargs=2, - action="append", - metavar=("", ""), - dest="meta_combined", - help="Define the metadata combined in one step for MetaTag and VBox elements." - + __embed_fields(Combined.fields), -) - ############################################################################### # lyrics ############################################################################### @@ -401,10 +380,7 @@ def _split_lines(self, text: typing.Text, width: int) -> typing.List[str]: "Rename the “*.msc[zx]” files." "Fields and functions you can use in the format " "string (-f, --format):\n\n" - "Fields\n======\n\n{}\n\n" - "Functions\n=========\n\n{}".format( - __itemized_fields(Interface.get_all_fields(), prefix=" "), tmep.get_doc() - ), + "Functions\n=========\n\n{}".format(tmep.get_doc()), ) group_rename.add_argument( @@ -766,7 +742,6 @@ def list_styles(version: int) -> None: if ( args.meta_metatag or args.meta_vbox - or args.meta_combined or args.meta_set or args.meta_clean or args.meta_dist @@ -800,26 +775,15 @@ def list_styles(version: int) -> None: ) setattr(score.meta.vbox, field, value) - if args.meta_combined: - for a in args.meta_combined: - field = a[0] - value = a[1] - if field not in Combined.fields: - raise ValueError( - f"Unknown field {field}. " - f"Possible fields: {', '.join(Combined.fields)}" - ) - setattr(score.meta.combined, field, value) - if args.meta_set: for a in args.meta_set: - score.meta.set_field(destination_field=a[0], format_string=a[1]) + score.fields.set(a[0], a[1]) if args.meta_clean: score.fields.clean(args.meta_clean) if args.meta_json: - score.meta.export_json() + score.fields.export_json() if args.meta_dist: for a in args.meta_dist: diff --git a/mscxyz/fields.py b/mscxyz/fields.py index 41965ae..1dada28 100644 --- a/mscxyz/fields.py +++ b/mscxyz/fields.py @@ -9,6 +9,8 @@ from pathlib import Path from typing import Any, Iterator, Mapping, Sequence, Union +import tmep + from mscxyz.meta import FormatStringNoFieldError, UnmatchedFormatStringError from mscxyz.settings import DefaultArguments from mscxyz.utils import Color, colorize @@ -310,6 +312,8 @@ def set(self, name: str, value: Any) -> None: obj = getattr(obj, attr) if obj is None: raise Exception(f"Cannot set attribute {field.attr_path}") + if value is not None and isinstance(value, str) and "$" in value: + value = tmep.parse(value, self.export_to_dict()) setattr(obj, last, value) def diff(self, args: DefaultArguments) -> None: diff --git a/mscxyz/meta.py b/mscxyz/meta.py index b2e17e0..e38d0ec 100644 --- a/mscxyz/meta.py +++ b/mscxyz/meta.py @@ -2,18 +2,12 @@ from __future__ import annotations -import json import re import typing -from pathlib import Path -from typing import Any import tmep from lxml.etree import _Element -from mscxyz import utils -from mscxyz.settings import get_args - if typing.TYPE_CHECKING: from mscxyz.score import Score @@ -634,204 +628,6 @@ def clean(self) -> None: setattr(self, field, None) -class Combined: - """Combines the metadata fields of the embedded ``metaTag`` and ``VBox`` elements.""" - - fields = ( - "composer", - "lyricist", - "subtitle", - "title", - ) - - score: "Score" - - xml_root: _Element - - metatag: Metatag - - vbox: Vbox - - def __init__(self, score: "Score") -> None: - self.score = score - self.xml_root = self.score.xml_root - self.metatag = Metatag(self.score) - self.vbox = Vbox(self.score) - - def _pick_value(self, *values: str | None) -> str | None: - for value in values: - if value: - return value - return None - - @property - def title(self) -> str | None: - return self._pick_value(self.vbox.title, self.metatag.work_title) - - @title.setter - def title(self, value: str | None) -> None: - self.vbox.title = self.metatag.work_title = value - - @property - def subtitle(self) -> str | None: - return self._pick_value(self.vbox.subtitle, self.metatag.movement_title) - - @subtitle.setter - def subtitle(self, value: str | None) -> None: - self.vbox.subtitle = self.metatag.movement_title = value - - @property - def composer(self) -> str | None: - return self._pick_value(self.vbox.composer, self.metatag.composer) - - @composer.setter - def composer(self, value: str | None) -> None: - self.vbox.composer = self.metatag.composer = value - - @property - def lyricist(self) -> str | None: - return self._pick_value(self.vbox.lyricist, self.metatag.lyricist) - - @lyricist.setter - def lyricist(self, value: str | None) -> None: - self.vbox.lyricist = self.metatag.lyricist = value - - -class InterfaceReadWrite: - objects = ("metatag", "vbox", "combined") - - score: "Score" - - metatag: Metatag - - vbox: Vbox - - combined: Combined - - fields: list[str] - - def __init__(self, score: "Score") -> None: - self.score = score - self.metatag = Metatag(self.score) - self.vbox = Vbox(self.score) - self.combined = Combined(self.score) - self.fields = self.get_all_fields() - - @staticmethod - def get_all_fields() -> list[str]: - fields: list[str] = [] - for field in Metatag.fields: - fields.append("metatag_" + field) - for field in Vbox.fields: - fields.append("vbox_" + field) - for field in Combined.fields: - fields.append("combined_" + field) - return sorted(fields) - - @staticmethod - def __split(field: str) -> dict[str, str | Any]: - match = re.search(r"([^_]*)_(.*)", field) - if not match: - raise ValueError("Field “" + field + "” can’t be splitted!") - matches = match.groups() - - if matches[0] not in InterfaceReadWrite.objects: - raise ValueError(matches[0] + ": Not a supported object!") - return {"object": matches[0], "field": matches[1]} - - def export_to_dict(self) -> dict[str, str]: - return export_to_dict(self, self.fields) - - def __getattr__(self, field: str) -> Any: - parts = self.__split(field) - obj = getattr(self, parts["object"]) - return getattr(obj, parts["field"]) - - def __setattr__(self, field: str, value: str) -> None: - if field in ("fields", "metatag", "objects", "vbox", "combined", "score"): - self.__dict__[field] = value - else: - parts = self.__split(field) - obj = getattr(self, parts["object"]) - return setattr(obj, parts["field"], value) - - -class InterfaceReadOnly: - fields = [ - "readonly_abspath", - "readonly_basename", - "readonly_dirname", - "readonly_extension", - "readonly_filename", - "readonly_relpath", - "readonly_relpath_backup", - ] - - score: Score - - def __init__(self, score: Score) -> None: - self.score = score - - @property - def readonly_abspath(self) -> str: - return str(self.score.path) - - @property - def readonly_basename(self) -> str: - return self.score.basename - - @property - def readonly_dirname(self) -> str: - return self.score.dirname - - @property - def readonly_extension(self) -> str: - return self.score.extension - - @property - def readonly_filename(self) -> str: - return self.score.filename - - @property - def readonly_relpath(self) -> str: - return str(self.score.path) - - @property - def readonly_relpath_backup(self) -> str: - return str(self.score.backup_file) - - -class Interface: - score: "Score" - - def __init__(self, score: "Score") -> None: - self.score = score - self.read_only = InterfaceReadOnly(self.score) - self.read_write = InterfaceReadWrite(self.score) - self.fields: list[str] = self.get_all_fields() - - @staticmethod - def get_all_fields() -> list[str]: - return sorted(InterfaceReadOnly.fields + InterfaceReadWrite.get_all_fields()) - - def export_to_dict(self) -> dict[str, str]: - return export_to_dict(self, self.fields) - - def __getattr__(self, field: str) -> Any: - if re.match(r"^readonly_", field): - return getattr(self.read_only, field) - else: - return getattr(self.read_write, field) - - def __setattr__(self, field: str, value: str) -> None: - if field in ("score", "read_only", "read_write", "fields"): - self.__dict__[field] = value - elif not re.match(r"^readonly_", field): - return setattr(self.read_write, field, value) - else: - raise ReadOnlyFieldError(field) - - class Meta: score: "Score" @@ -839,36 +635,23 @@ class Meta: vbox: Vbox - combined: Combined - - interface_read_write: InterfaceReadWrite - - interface: Interface - def __init__(self, score: "Score") -> None: self.score = score self.metatag = Metatag(self.score) self.vbox = Vbox(self.score) - self.combined = Combined(self.score) - self.interface_read_write = InterfaceReadWrite(self.score) - self.interface = Interface(self.score) def sync_fields(self) -> None: - self.combined.title = self.combined.title - self.combined.subtitle = self.combined.subtitle - self.combined.composer = self.combined.composer - self.combined.lyricist = self.combined.lyricist + self.title = self.title + self.subtitle = self.subtitle + self.composer = self.composer + self.lyricist = self.lyricist def write_to_log_file(self, log_file: str, format_string: str) -> None: log = open(log_file, "w") log.write(tmep.parse(format_string, self.score.fields.export_to_dict()) + "\n") log.close() - def set_field(self, destination_field: str, format_string: str) -> None: - field_value = tmep.parse(format_string, self.interface.export_to_dict()) - setattr(self.interface, destination_field, field_value) - def clean(self) -> None: """ Clean all metadata fields of the object. @@ -880,83 +663,23 @@ def delete_duplicates(self) -> None: """ Delete duplicates in the metadata. - This method checks if the ``combined_lyricist`` and ``combined_composer`` are the same, - and if so, it sets ``combined_lyricist`` to an empty string. - - It also checks if ``combined_title`` is empty but ``combined_subtitle`` is not, - and if so, it sets ``combined_title`` to ``combined_subtitle``. - - Finally, it checks if ``combined_subtitle`` is the same as ``combined_title``, - and if so, it sets ``combined_subtitle`` to an empty string. - """ - iface: Interface = self.interface - if iface.combined_lyricist == iface.combined_composer: - iface.combined_lyricist = "" - - if not iface.combined_title and iface.combined_subtitle: - iface.combined_title = iface.combined_subtitle - - if iface.combined_subtitle == iface.combined_title: - iface.combined_subtitle = "" - - def show(self, pre: dict[str, str], post: dict[str, str]) -> None: - args = get_args() - - fields = list(self.interface.fields) - - if args.general_verbose < 1: - fields.remove("readonly_abspath") - fields.remove("readonly_dirname") - fields.remove("readonly_extension") - fields.remove("readonly_filename") - fields.remove("readonly_relpath") - - if args.general_verbose < 2: - fields.remove("readonly_relpath_backup") - - for field in fields: - field_color: utils.Color - if ( - args.general_verbose == 0 - and (field in pre and pre[field] or field in post and post[field]) - ) or args.general_verbose > 0: - if re.match(r"^combined_", field): - field_color = "green" - elif re.match(r"^metatag_", field): - field_color = "blue" - elif re.match(r"^readonly_", field): - field_color = "red" - elif re.match(r"^vbox_", field): - field_color = "cyan" - else: - field_color = "white" - - line: list[str] = [] - if pre[field]: - line.append("“{}”".format(pre[field])) - - if pre[field] != post[field]: - line.append("->") - line.append(utils.colorize("“{}”".format(post[field]), "yellow")) - - print( - "{}: {}".format(utils.colorize(field, field_color), " ".join(line)) - ) - - def export_json(self) -> Path: - """ - Export the data as a JSON file. - - :return: The path to the exported JSON file. - """ - data: dict[str, str] = {} - result_path: Path = self.score.json_file - for field in self.interface.fields: - data[field] = self.interface.__getattr__(field) - output = open(result_path, "w") - json.dump(data, output, indent=4) - output.close() - return result_path + This method checks if the ``lyricist`` and ``composer`` are the same, + and if so, it sets ``lyricist`` to an empty string. + + It also checks if ``title`` is empty but ``subtitle`` is not, + and if so, it sets ``title`` to ``subtitle``. + + Finally, it checks if ``subtitle`` is the same as ``title``, + and if so, it sets ``subtitle`` to an empty string. + """ + if self.lyricist == self.composer: + self.lyricist = None + + if not self.title and self.subtitle: + self.title = self.subtitle + + if self.subtitle == self.title: + self.subtitle = None def reload(self, save: bool = False) -> Meta: """ diff --git a/tests/test_fields.py b/tests/test_fields.py index 78c8bfe..c02824e 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -4,7 +4,9 @@ import os import re +from pathlib import Path +from mscxyz import utils from mscxyz.fields import FieldsManager @@ -47,6 +49,14 @@ def test_property_names(self, fields: FieldsManager) -> None: "extension", ) + def test_method_export_json(self, fields: FieldsManager) -> None: + result_path: Path = fields.export_json() + assert result_path.exists() + + json: str = utils.read_file(result_path) + assert '"composer": "Composer"' in json + assert '"basename": "score"' in json + def test_method_export_to_dict(self, fields: FieldsManager) -> None: result = fields.export_to_dict() for key in result: diff --git a/tests/test_meta.py b/tests/test_meta.py index 4df26b6..71802f7 100644 --- a/tests/test_meta.py +++ b/tests/test_meta.py @@ -2,16 +2,12 @@ from __future__ import annotations -import os from pathlib import Path import pytest from mscxyz import meta, supported_versions, utils from mscxyz.meta import ( - Interface, - InterfaceReadOnly, - InterfaceReadWrite, Meta, Metatag, Vbox, @@ -23,10 +19,6 @@ from tests.helper import Cli -def reload(src: Score | str | Path) -> Interface: - return helper.reload(src).meta.interface - - class TestExceptions: def test_read_only_field_error(self) -> None: with pytest.raises(meta.ReadOnlyFieldError) as e: @@ -70,190 +62,6 @@ class Data: assert export_to_dict(data, ("a")) == {"a": "a"} -class TestClassUnifiedInterface: - def setup_method(self) -> None: - self.fields = [ - "combined_composer", - "combined_lyricist", - "combined_subtitle", - "combined_title", - "metatag_arranger", - "metatag_audio_com_url", - "metatag_composer", - "metatag_copyright", - "metatag_creation_date", - "metatag_lyricist", - "metatag_movement_number", - "metatag_movement_title", - "metatag_msc_version", - "metatag_platform", - "metatag_poet", - "metatag_source", - "metatag_source_revision_id", - "metatag_subtitle", - "metatag_translator", - "metatag_work_number", - "metatag_work_title", - "vbox_composer", - "vbox_lyricist", - "vbox_subtitle", - "vbox_title", - ] - - def _init_class( - self, filename: str, version: int = 2 - ) -> tuple[InterfaceReadWrite, Score, str]: - tmp = helper.get_file(filename, version) - score = Score(tmp) - interface = InterfaceReadWrite(score) - return interface, score, tmp - - def _test_subclasses(self, version: int) -> None: - interface, _, _ = self._init_class("simple.mscx", version) - assert interface.metatag - assert interface.vbox - assert interface.combined - - def test_subclasses(self) -> None: - self._test_subclasses(version=2) - self._test_subclasses(version=3) - - def _test_get_simple(self, version: int) -> None: - interface, _, _ = self._init_class("simple.mscx", version) - assert interface.vbox_title == "Title" - assert interface.metatag_work_title == "Title" - - def test_get_simple(self) -> None: - self._test_get_simple(version=2) - self._test_get_simple(version=3) - - def _test_get_all_values(self, version: int) -> None: - interface, _, _ = self._init_class("meta-all-values.mscx", version) - - assert interface.combined_composer == "vbox_composer" - assert interface.combined_lyricist == "vbox_lyricist" - assert interface.combined_subtitle == "vbox_subtitle" - assert interface.combined_title == "vbox_title" - - for field in self.fields[4:]: - assert getattr(interface, field) == field - - @pytest.mark.skip(reason="Test needs to be rewritten") - def test_get_all_values(self) -> None: - self._test_get_all_values(version=2) - self._test_get_all_values(version=3) - - def _test_set_all_values(self, version: int) -> None: - interface, score, tmp = self._init_class("meta-all-values.mscx", version) - - for field in self.fields: - setattr(interface, field, field + "_test") - assert getattr(interface, field) == field + "_test" - - score.save() - score = Score(tmp) - interface = InterfaceReadWrite(score) - - assert interface.combined_composer == "vbox_composer_test" - assert interface.combined_lyricist == "vbox_lyricist_test" - assert interface.combined_subtitle == "vbox_subtitle_test" - assert interface.combined_title == "vbox_title_test" - - for field in self.fields[4:]: - assert getattr(interface, field) == field + "_test" - - @pytest.mark.skip(reason="Test needs to be rewritten") - def test_set_all_values(self) -> None: - self._test_set_all_values(version=2) - self._test_set_all_values(version=3) - - def test_method_get_all_fields(self) -> None: - fields = InterfaceReadWrite.get_all_fields() - assert fields == self.fields - - def _test_method_export_to_dict(self, version: int) -> None: - interface, _, _ = self._init_class("meta-all-values.mscx", version) - result = interface.export_to_dict() - assert result == { - "combined_composer": "vbox_composer", - "combined_lyricist": "vbox_lyricist", - "combined_subtitle": "vbox_subtitle", - "combined_title": "vbox_title", - "metatag_arranger": "metatag_arranger", - "metatag_audio_com_url": "", - "metatag_composer": "metatag_composer", - "metatag_copyright": "metatag_copyright", - "metatag_creation_date": "metatag_creation_date", - "metatag_lyricist": "metatag_lyricist", - "metatag_movement_number": "metatag_movement_number", - "metatag_movement_title": "metatag_movement_title", - "metatag_msc_version": "", - "metatag_platform": "metatag_platform", - "metatag_poet": "metatag_poet", - "metatag_source": "metatag_source", - "metatag_source_revision_id": "", - "metatag_subtitle": "", - "metatag_translator": "metatag_translator", - "metatag_work_number": "metatag_work_number", - "metatag_work_title": "metatag_work_title", - "vbox_composer": "vbox_composer", - "vbox_lyricist": "vbox_lyricist", - "vbox_subtitle": "vbox_subtitle", - "vbox_title": "vbox_title", - } - - def test_method_export_to_dict(self) -> None: - self._test_method_export_to_dict(version=2) - self._test_method_export_to_dict(version=3) - - def _test_attribute_fields(self, version: int) -> None: - interface, _, _ = self._init_class("meta-all-values.mscx", version) - assert interface.fields == self.fields - - def test_attribute_fields(self) -> None: - self._test_attribute_fields(version=2) - self._test_attribute_fields(version=3) - - -class TestClassInterfaceReadOnly: - def setup_method(self) -> None: - self.fields = ( - "readonly_basename", - "readonly_dirname", - "readonly_extension", - "readonly_filename", - "readonly_relpath", - "readonly_relpath_backup", - ) - self.tmp = helper.get_file("simple.mscx") - self.xml_tree = Score(self.tmp) - self.interface = InterfaceReadOnly(self.xml_tree) - - def test_exception(self) -> None: - with pytest.raises(AttributeError): - self.interface.readonly_relpath = "lol" # type: ignore - - def test_field_readonly_basename(self) -> None: - assert self.interface.readonly_basename == "simple" - - def test_field_readonly_dirname(self) -> None: - assert self.interface.readonly_dirname == os.path.dirname(self.tmp) - - def test_field_readonly_extension(self) -> None: - assert self.interface.readonly_extension == "mscx" - - def test_field_readonly_filename(self) -> None: - assert self.interface.readonly_filename == "simple.mscx" - - def test_field_readonly_relpath(self) -> None: - assert self.interface.readonly_relpath == self.tmp - - def test_field_readonly_relpath_backup(self) -> None: - assert self.interface.readonly_relpath_backup == self.tmp.replace( - ".mscx", "_bak.mscx" - ) - - def get_meta_tag(filename: str, version: int) -> Metatag: score = helper.get_score(filename, version) return score.meta.metatag @@ -559,49 +367,17 @@ def test_option_vbox() -> None: assert v.title == "t" -def test_option_combined() -> None: - score = Cli( - "--combined", - "composer", - "c", - # - "--combined", - "lyricist", - "l", - # - "--combined", - "subtitle", - "s", - # - "--combined", - "title", - "t", - ).score() - - m = score.meta.metatag - assert m.composer == "c" - assert m.lyricist == "l" - assert m.movement_title == "s" - assert m.work_title == "t" - - v = score.meta.vbox - assert v.composer == "c" - assert v.lyricist == "l" - assert v.subtitle == "s" - assert v.title == "t" - - class TestOptionSetField: def test_simple_string(self) -> None: - c = ( + s = ( Cli("--set-field", "vbox_title", "test") .append_score("meta-all-values.mscz") - .execute() + .score() ) - assert c.post.meta.interface.vbox_title == "test" + assert s.meta.vbox.title == "test" def test_multiple_times(self) -> None: - c = ( + s = ( Cli( "--set-field", "vbox_title", @@ -611,23 +387,23 @@ def test_multiple_times(self) -> None: "vc", ) .append_score("meta-all-values.mscz") - .execute() + .score() ) - i = c.post.meta.interface - assert i.vbox_title == "vt" - assert i.vbox_composer == "vc" + + assert s.meta.vbox.title == "vt" + assert s.meta.vbox.composer == "vc" def test_with_templating(self) -> None: - c = ( + s = ( Cli( "--set-field", "vbox_title", "$vbox_title ($vbox_composer)", ) .append_score("meta-all-values.mscz") - .execute() + .score() ) - assert c.post.meta.interface.vbox_title == "vbox_title (vbox_composer)" + assert s.meta.vbox.title == "vbox_title (vbox_composer)" def test_option_log(tmp_path: Path) -> None: @@ -638,21 +414,19 @@ def test_option_log(tmp_path: Path) -> None: class TestOptionDeleteDuplicates: def test_normal(self) -> None: - c = Cli("--delete-duplicates").append_score("meta-duplicates.mscz").execute() - i = c.post.meta.interface - assert not i.combined_lyricist - assert not i.combined_subtitle + s = Cli("--delete-duplicates").append_score("meta-duplicates.mscz").score() + assert not s.meta.lyricist + assert not s.meta.subtitle def test_move_subtitle(self) -> None: - c = ( + s = ( Cli("--delete-duplicates") .append_score("meta-duplicates-move-subtitle.mscz") - .execute() + .score() ) - i = c.post.meta.interface - assert not i.combined_lyricist - assert not i.combined_subtitle - assert i.combined_title == "Title" + assert not s.meta.lyricist + assert not s.meta.subtitle + assert s.meta.title == "Title" def test_option_synchronize() -> None: @@ -690,7 +464,7 @@ def test_option_json() -> None: score = (Cli("--json").append_score("meta-all-values.mscz").execute()).score() json = score.json_file assert json.exists() - assert '"readonly_basename": "meta-all-values"' in utils.read_file(json) + assert '"basename": "meta-all-values"' in utils.read_file(json) class TestClassMeta: @@ -729,54 +503,11 @@ def test_method_clean_metadata(self) -> None: assert self.meta.lyricist is None def test_method_delete_duplicates(self) -> None: - self.meta.interface.combined_lyricist = "test" - self.meta.interface.combined_composer = "test" - assert self.meta.interface.combined_lyricist == "test" + self.meta.lyricist = "test" + self.meta.composer = "test" + assert self.meta.lyricist == "test" self.meta.delete_duplicates() - assert self.meta.interface.combined_lyricist is None - - def test_method_show(self, capsys: pytest.CaptureFixture[str]) -> None: - self.meta.show({"combined_title": "pre"}, {"combined_title": "post"}) - capture = capsys.readouterr() - assert capture.out == "combined_title: “pre” -> “post”\n" - - def test_method_export_json(self) -> None: - result_path: Path = self.meta.export_json() - assert result_path.exists() - - json: str = utils.read_file(result_path) - # json = ( - # '{\n "combined_composer": "vbox_composer",\n' - # ' "combined_lyricist": "vbox_lyricist",\n' - # ' "combined_subtitle": "vbox_subtitle",\n' - # ' "combined_title": "vbox_title",\n' - # ' "metatag_arranger": "metatag_arranger",\n' - # ' "metatag_composer": "metatag_composer",\n' - # ' "metatag_copyright": "metatag_copyright",\n' - # ' "metatag_creation_date": "metatag_creation_date",\n' - # ' "metatag_lyricist": "metatag_lyricist",\n' - # ' "metatag_movement_number": "metatag_movement_number",\n' - # ' "metatag_movement_title": "metatag_movement_title",\n' - # ' "metatag_platform": "metatag_platform",\n' - # ' "metatag_poet": "metatag_poet",\n' - # ' "metatag_source": "metatag_source",\n' - # ' "metatag_translator": "metatag_translator",\n' - # ' "metatag_work_number": "metatag_work_number",\n' - # ' "metatag_work_title": "metatag_work_title",\n' - # ' "readonly_abspath": "/tmp/tmp1rv5ybvu/meta-all-values.mscx",\n' - # ' "readonly_basename": "meta-all-values",\n' - # ' "readonly_dirname": "/tmp/tmp1rv5ybvu",\n' - # ' "readonly_extension": "mscx",\n' - # ' "readonly_filename": "meta-all-values.mscx",\n' - # ' "readonly_relpath": "/tmp/tmp1rv5ybvu/meta-all-values.mscx",\n' - # ' "readonly_relpath_backup": "/tmp/tmp1rv5ybvu/meta-all-values_bak.mscx",\n' - # ' "vbox_composer": "vbox_composer",\n' - # ' "vbox_lyricist": "vbox_lyricist",\n' - # ' "vbox_subtitle": "vbox_subtitle",\n' - # ' "vbox_title": "vbox_title"\n}' - # ) - assert '{\n "combined_composer": "vbox_composer",\n' in json - assert '"readonly_basename": "meta-all-values"' in json + assert self.meta.lyricist is None def test_property_title(self, score: Score) -> None: assert score.meta.title == "Title"