Skip to content

Commit

Permalink
Extend the fields class
Browse files Browse the repository at this point in the history
  • Loading branch information
Josef-Friedrich committed Jan 23, 2024
1 parent a29c715 commit d7fe8bb
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 32 deletions.
203 changes: 189 additions & 14 deletions mscxyz/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
import typing
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from typing import Any, Union

if typing.TYPE_CHECKING:
from mscxyz.score import Score


FieldValue = Union[str, int, float]
FieldsExport = dict[str, FieldValue]


@dataclass
class Field:
name: str
Expand All @@ -32,14 +36,180 @@ class FieldsManager:
score: "Score"

fields = (
# Combined
Field(name="title", description="The combined title", attr_path="meta.title"),
Field(name="abspath", description="", attr_path="abspath"),
Field(name="basename", description="", attr_path="basename"),
Field(name="dirname", description="", attr_path="dirname"),
Field(name="extension", description="", attr_path="extension"),
Field(name="filename", description="", attr_path="filename"),
Field(name="relpath", description="", attr_path="relpath"),
Field(name="relpath_backup", description="", attr_path="relpath_backup"),
Field(
name="subtitle",
description="The combined subtitle",
attr_path="meta.subtitle",
),
Field(
name="composer",
description="The combined composer",
attr_path="meta.composer",
),
Field(
name="lyricist",
description="The combined lyricist",
attr_path="meta.lyricist",
),
# vbox
Field(
name="vbox_title",
description="The title field of the score as it appears in the center of the first vertical frame (VBox).",
attr_path="meta.vbox.title",
),
Field(
name="vbox_subtitle",
description="The subtitle field of the score as it appears in the center of the first vertical frame (VBox).",
attr_path="meta.vbox.subtitle",
),
Field(
name="vbox_composer",
description="The composer field of the score as it appears in the center of the first vertical frame (VBox).",
attr_path="meta.vbox.composer",
),
Field(
name="vbox_lyricist",
description="The lyricist field of the score as it appears in the center of the first vertical frame (VBox).",
attr_path="meta.vbox.lyricist",
),
# metatag
Field(
name="metatag_arranger",
description="The arranger field stored as project properties.",
attr_path="meta.metatag.arranger",
),
Field(
name="metatag_audio_com_url",
description="The audio.com URL field stored as project properties.",
attr_path="meta.metatag.audio_com_url",
),
Field(
name="metatag_composer",
description="The composer field stored as project properties.",
attr_path="meta.metatag.composer",
),
Field(
name="metatag_copyright",
description="The copyright field stored as project properties.",
attr_path="meta.metatag.copyright",
),
Field(
name="metatag_creation_date",
description="The creation date field stored as project properties.",
attr_path="meta.metatag.creation_date",
),
Field(
name="metatag_lyricist",
description="The lyricist field stored as project properties.",
attr_path="meta.metatag.lyricist",
),
Field(
name="metatag_movement_number",
description="The movement number field stored as project properties.",
attr_path="meta.metatag.movement_number",
),
Field(
name="metatag_movement_title",
description="The movement title field stored as project properties.",
attr_path="meta.metatag.movement_title",
),
Field(
name="metatag_msc_version",
description="The MuseScore version field stored as project properties.",
attr_path="meta.metatag.msc_version",
),
Field(
name="metatag_platform",
description="The platform field stored as project properties.",
attr_path="meta.metatag.platform",
),
Field(
name="metatag_poet",
description="The poet field stored as project properties.",
attr_path="meta.metatag.poet",
),
Field(
name="metatag_source",
description="The source field stored as project properties.",
attr_path="meta.metatag.source",
),
Field(
name="metatag_source_revision_id",
description="The source revision ID field stored as project properties.",
attr_path="meta.metatag.source_revision_id",
),
Field(
name="metatag_subtitle",
description="The subtitle field stored as project properties.",
attr_path="meta.metatag.subtitle",
),
Field(
name="metatag_translator",
description="The translator field stored as project properties.",
attr_path="meta.metatag.translator",
),
Field(
name="metatag_work_number",
description="The work number field stored as project properties.",
attr_path="meta.metatag.work_number",
),
Field(
name="metatag_work_title",
description="The work title field stored as project properties.",
attr_path="meta.metatag.work_title",
),
# Readonly
Field(
name="version",
description="The MuseScore version as a floating point number, "
"for example ``2.03``, ``3.01`` or ``4.20``.",
attr_path="version",
),
Field(
name="version_major",
description="The major MuseScore version, for example ``2``, ``3`` or ``4``.",
attr_path="version_major",
),
Field(
name="path",
description="The absolute path of the MuseScore file, for example ``/home/xyz/score.mscz``.",
attr_path="path",
),
Field(
name="backup_file",
description="The absolute path of the backup file. "
"The string ``_bak`` is appended to the file name before the extension.",
attr_path="backup_file",
),
Field(
name="json_file",
description="The absolute path of the JSON file in which the metadata can be exported.",
attr_path="json_file",
),
Field(
name="dirname",
description="The name of the containing directory of the MuseScore file, for "
"example: ``/home/xyz/score_files``.",
attr_path="dirname",
),
Field(
name="filename",
description="The filename of the MuseScore file, for example:"
"``score.mscz``.",
attr_path="filename",
),
Field(
name="basename",
description="The basename of the score file, for example: ``score``.",
attr_path="basename",
),
Field(
name="extension",
description="The extension (``mscx`` or ``mscz``) of the score file.",
attr_path="extension",
),
)

__fields_by_name: dict[str, Field]
Expand Down Expand Up @@ -113,19 +283,24 @@ def show(self, pre: dict[str, str], post: dict[str, str]) -> None:

# print("{}: {}".format(utils.color(field, field_color), " ".join(line)))

def export_to_dict(self) -> FieldsExport:
output: FieldsExport = {}
for field in self.names:
value = self.get(field)
if value is not None:
if isinstance(value, Path):
value = str(value)
output[field] = value
return output

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)
json.dump(self.export_to_dict(), output, indent=4)
output.close()
return result_path

pass
26 changes: 13 additions & 13 deletions mscxyz/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Score:
"""

path: Path
"""The absolute path of the input file.
"""The absolute path of the MuseScore file, for example ``/home/xyz/score.mscz``.
"""

xml_file: str
Expand All @@ -46,7 +46,7 @@ class Score:
xml: XmlManipulator

version: float
"""The MuseScore version, for example 2.03 or 3.01"""
"""The MuseScore version as a floating point number, for example ``2.03``, ``3.01`` or ``4.20``."""

zip_container: Optional[utils.ZipContainer] = None

Expand Down Expand Up @@ -84,17 +84,18 @@ def xml_string(self) -> str:

@property
def version_major(self) -> int:
"""The major MuseScore version, for example 2 or 3"""
"""The major MuseScore version, for example ``2``, ``3`` or ``4``"""
return int(self.version)

@property
def backup_file(self) -> Path:
"""The path of the backup file."""
"""The absolute path of the backup file.
The string ``_bak`` is appended to the file name before the extension."""
return self.change_path(suffix="bak")

@property
def json_file(self) -> Path:
"""The path of the JSON file in which the metadata is saved."""
"""The absolute path of the JSON file in which the metadata can be exported."""
return self.change_path(extension="json")

@property
Expand All @@ -106,20 +107,19 @@ def dirname(self) -> str:
@property
def filename(self) -> str:
"""The filename of the MuseScore file, for example:
``simple.mscx``."""
``score.mscz``."""
return self.path.name

@property
def extension(self) -> str:
"""The extension (``mscx`` or ``mscz``) of the score file, for
example: ``mscx``."""
return self.filename.split(".")[-1].lower()

@property
def basename(self) -> str:
"""The basename of the score file, for example: ``simple``."""
"""The basename of the score file, for example: ``score``."""
return self.filename.replace("." + self.extension, "")

@property
def extension(self) -> str:
"""The extension (``mscx`` or ``mscz``) of the score file."""
return self.filename.split(".")[-1].lower()

def change_path(
self, suffix: Optional[Any] = None, extension: Optional[str] = None
) -> Path:
Expand Down
68 changes: 63 additions & 5 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,79 @@

from __future__ import annotations

import os
import re

from mscxyz.fields import FieldsManager


class TestClassFieldsManager:
def test_property_names(self, fields: FieldsManager) -> None:
assert fields.names == (
"title",
"abspath",
"basename",
"subtitle",
"composer",
"lyricist",
"vbox_title",
"vbox_subtitle",
"vbox_composer",
"vbox_lyricist",
"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",
"version",
"version_major",
"path",
"backup_file",
"json_file",
"dirname",
"extension",
"filename",
"relpath",
"relpath_backup",
"basename",
"extension",
)

def test_method_export_to_dict(self, fields: FieldsManager) -> None:
result = fields.export_to_dict()
for key in result:
value = result[key]
if isinstance(value, str) and value.startswith(os.path.sep):
value = re.sub(f"^{os.path.sep}.*{os.path.sep}", "/../..", value)
result[key] = value
if "dirname" in result:
result["dirname"] = "dir"
assert result == {
"title": "Title",
"composer": "Composer",
"vbox_title": "Title",
"vbox_composer": "Composer",
"metatag_composer": "Composer",
"metatag_msc_version": "4.20",
"metatag_platform": "Linux",
"metatag_work_title": "Title",
"version": 4.20,
"version_major": 4,
"path": "/../..score.mscz",
"backup_file": "/../..score_bak.mscz",
"json_file": "/../..score.json",
"dirname": "dir",
"basename": "score",
"extension": "mscz",
"filename": "score.mscz",
}

def test_method_get(self, fields: FieldsManager) -> None:
assert fields.get("title") == "Title"

0 comments on commit d7fe8bb

Please sign in to comment.