Skip to content

Commit

Permalink
New submodule fields to manage the path template variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Josef-Friedrich committed Jan 23, 2024
1 parent d7e80ce commit a29c715
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 20 deletions.
131 changes: 131 additions & 0 deletions mscxyz/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""Provide fields ($variable) for the path templates."""

from __future__ import annotations

import json
import typing
from dataclasses import dataclass
from pathlib import Path
from typing import Any

if typing.TYPE_CHECKING:
from mscxyz.score import Score


@dataclass
class Field:
name: str
"""
``name`` will become ``$name`` in the path templates
"""

description: str
"""
Some description text for the documentation.
"""

attr_path: str
"""``meta.title`` accesses ``score.meta.title``"""


class FieldsManager:
score: "Score"

fields = (
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"),
)

__fields_by_name: dict[str, Field]

def __init__(self, score: "Score") -> None:
self.score = score
self.__fields_by_name = {}
for field in self.fields:
if field.name in self.__fields_by_name:
raise Exception("Duplicate field name")
self.__fields_by_name[field.name] = field

@property
def names(self) -> tuple[str, ...]:
return tuple(self.__fields_by_name.keys())

def __access_attr(self, attr_path: str) -> Any | None:
attrs = attr_path.split(".")
value = self.score
for attr in attrs:
value = getattr(value, attr)
if value is None:
break

return value

def get(self, name: str) -> Any | None:
field = self.__fields_by_name[name]
return self.__access_attr(field.attr_path)

def show(self, pre: dict[str, str], post: dict[str, str]) -> None:
pass
# 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.color("“{}”".format(post[field]), "yellow"))

# print("{}: {}".format(utils.color(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

pass
9 changes: 9 additions & 0 deletions mscxyz/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from mscxyz import utils
from mscxyz.export import Export
from mscxyz.fields import FieldsManager
from mscxyz.lyrics import Lyrics
from mscxyz.meta import Meta
from mscxyz.settings import get_args
Expand Down Expand Up @@ -51,6 +52,8 @@ class Score:

__xml_string_initial: Optional[str] = None

__fields: Optional[FieldsManager] = None

__export: Optional[Export] = None

__lyrics: Optional[Lyrics] = None
Expand Down Expand Up @@ -128,6 +131,12 @@ def export(self) -> Export:
self.__export = Export(self)
return self.__export

@property
def fields(self) -> FieldsManager:
if self.__fields is None:
self.__fields = FieldsManager(self)
return self.__fields

@property
def lyrics(self) -> Lyrics:
if self.__lyrics is None:
Expand Down
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pytest

from mscxyz import Score
from mscxyz.fields import FieldsManager
from tests import helper


Expand Down Expand Up @@ -52,6 +53,12 @@ def score() -> Score:
return helper.get_score("score.mscz", version=4)


@pytest.fixture(autouse=True)
def fields() -> FieldsManager:
"""Instantiate a Score object from the file simple.mscz (version 4)."""
return helper.get_fields("score.mscz", version=4)


@pytest.fixture(autouse=True)
def score_path() -> Path:
return helper.get_path("score.mscz", version=4)
Expand Down
5 changes: 5 additions & 0 deletions tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from mscxyz import Score
from mscxyz.cli import execute
from mscxyz.fields import FieldsManager
from mscxyz.lyrics import Lyrics
from mscxyz.meta import Meta
from mscxyz.style import Style
Expand Down Expand Up @@ -78,6 +79,10 @@ def get_meta(filename: str, version: int = 2) -> Meta:
return get_score(filename, version).meta


def get_fields(filename: str, version: int = 2) -> FieldsManager:
return get_score(filename, version).fields


def get_lyrics(filename: str, version: int = 2) -> Lyrics:
return get_score(filename, version).lyrics

Expand Down
22 changes: 22 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Test submodule “rename.py”."""

from __future__ import annotations

from mscxyz.fields import FieldsManager


class TestClassFieldsManager:
def test_property_names(self, fields: FieldsManager) -> None:
assert fields.names == (
"title",
"abspath",
"basename",
"dirname",
"extension",
"filename",
"relpath",
"relpath_backup",
)

def test_method_get(self, fields: FieldsManager) -> None:
assert fields.get("title") == "Title"
20 changes: 0 additions & 20 deletions tests/test_xml.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
"""Test submodule “utils.py”."""
from __future__ import annotations


from pathlib import Path


import pytest

from mscxyz import utils
<<<<<<< HEAD
from mscxyz.xml import Xml

=======
from mscxyz.xml import XmlManipulator
>>>>>>> 9fb215c9f72f452ad9cd1b8b1ff22f6f54643c9b
from tests import helper


xml_file = helper.get_file("simple.mscx", 4)

root = helper.get_xml_root("score.mscz", 4)
Expand Down Expand Up @@ -103,17 +95,6 @@ def test_method_xpathall_safe() -> None:
assert len(element) == 16


<<<<<<< HEAD
def test_write(tmp_path: Path) -> None:
dest = tmp_path / "test.xml"
element = Xml.parse("<root><a><b/><c/></a><d><e/></d></root>")
xml.write(dest, element)
result: str = utils.read_file(dest)
assert result == (
'<?xml version="1.0" encoding="UTF-8"?>\n'
"<root><a><b/><c/></a><d><e/></d></root>\n"
)
=======
# crUd: Update #################################################################


Expand Down Expand Up @@ -169,4 +150,3 @@ def test_with_text(self, custom_xml: XmlManipulator) -> None:

def test_navigate_in_tree(self, custom_xml: XmlManipulator) -> None:
assert "<root><a><c/></a>" in custom_xml.remove_tags("./a/b").tostring()
>>>>>>> 9fb215c9f72f452ad9cd1b8b1ff22f6f54643c9b

0 comments on commit a29c715

Please sign in to comment.