From 0894af16578edf993d8cc9fa2eded78853220f64 Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sun, 2 Feb 2025 13:23:54 +0100 Subject: [PATCH 1/7] fix: remove unused variable --- libmei/tools/cpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmei/tools/cpp.py b/libmei/tools/cpp.py index b5e49c00711..653b4c5dbfd 100644 --- a/libmei/tools/cpp.py +++ b/libmei/tools/cpp.py @@ -1159,7 +1159,7 @@ def create_att_module(cpp_ns: str, schema, outdir: Path): else: att_name_lower = att - attdefault, converters = vrv_getattdefault(schema.schema, module, gp, att) + _, converters = vrv_getattdefault(schema.schema, module, gp, att) attsubstr = { "attGroupNameUpper": schema.cc(schema.strpatt(gp)), "attNameUpper": schema.cc(att), From fa73153a76753b8106d59b2da0d3e32c14ed4e99 Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sun, 2 Feb 2025 13:25:11 +0100 Subject: [PATCH 2/7] fix: align pyproject with PEP 621 --- libmei/pyproject.toml | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libmei/pyproject.toml b/libmei/pyproject.toml index 6ed844ba5c9..69170c61a41 100644 --- a/libmei/pyproject.toml +++ b/libmei/pyproject.toml @@ -1,16 +1,21 @@ -[tool.poetry] +[project] name = "libmei" version = "0.1.0" +dependencies = [ + "pyyaml (>=6.0)", + "lxml (>=5.3.0)", +] +requires-python = ">=3.9" description = "" -authors = ["Andrew Hankinson "] +authors = [ + {name = "Andrew Hankinson", email="andrew.hankinson@gmail.com"}, +] readme = "README.md" +license = "MIT" -[tool.poetry.dependencies] -python = "^3.9" -pyyaml = "^6.0" -lxml = "^5.3.0" - +[tool.poetry] +packages = [{include = "poetry_demo"}] [build-system] -requires = ["poetry-core"] +requires = ["poetry-core>=2.0"] build-backend = "poetry.core.masonry.api" From 573ea50a0386d6e8bd4211dd65e7aca7bdb5d31f Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sun, 2 Feb 2025 13:25:22 +0100 Subject: [PATCH 3/7] update poetry lock --- libmei/poetry.lock | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libmei/poetry.lock b/libmei/poetry.lock index 3e2a8d86143..e3504529b21 100644 --- a/libmei/poetry.lock +++ b/libmei/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "lxml" @@ -6,6 +6,7 @@ version = "5.3.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656"}, {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d"}, @@ -160,6 +161,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -217,6 +219,6 @@ files = [ ] [metadata] -lock-version = "2.0" -python-versions = "^3.9" -content-hash = "e436e8a3d588d2880929e2fe7fb823ccc138b476db01782147cd3e7de229f952" +lock-version = "2.1" +python-versions = ">=3.9" +content-hash = "591c209718a5b4b6439b6c9477ee0042013810770530b2e0e330e5df0e551102" From dcb194212588361af055a157a10c2b759790ade6 Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sun, 2 Feb 2025 13:25:36 +0100 Subject: [PATCH 4/7] use secure links --- libmei/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmei/README.md b/libmei/README.md index e3b8c4d7fdf..8de720210d7 100644 --- a/libmei/README.md +++ b/libmei/README.md @@ -1,9 +1,9 @@ LibMEI ------ -LibMEI is a C++ library for reading and writing [MEI](http://music-encoding.org) files +LibMEI is a C++ library for reading and writing [MEI](https://music-encoding.org/) files -It was originally developed by the [Distributed Digital Music Archives and Libraries Lab](http://ddmal.music.mcgill.ca/) at the Schulich School of Music at McGill University, Montréal, Canada +It was originally developed by the [Distributed Digital Music Archives and Libraries Lab](https://ddmal.music.mcgill.ca/) at the Schulich School of Music at McGill University, Montréal, Canada This is a modified version that is used for generating C++ code for Verovio. From baf39cfbef87d16a17024a868d3b2abf5e83889a Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sun, 2 Feb 2025 13:37:40 +0100 Subject: [PATCH 5/7] update readme for poetry 2 --- libmei/README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libmei/README.md b/libmei/README.md index 8de720210d7..e631bf9930a 100644 --- a/libmei/README.md +++ b/libmei/README.md @@ -22,17 +22,29 @@ Compilation & Usage To install you can use Python `poetry` which will create a virtual environment and automatically install the necessary dependencies. The first time you get things set up, from the `libmei` directory run: - $> poetry install +```shell +poetry install +``` This will set up a virtual environment for you. When you want to activate the environment, run - $> poetry shell +```shell +poetry env activate +``` -This allows you to run Python with all the necessary dependencies for running the libmei scripts. +This will show you the command to activate the virtual environment. To generate the code, activate the poetry environment and, from the `libmei` directory, run: - $> python3 tools/parseschema2.py ./mei/mei-verovio_compiled.odd +```shell +python3 tools/parseschema2.py ./mei/mei-verovio_compiled.odd +``` + +If you don't want to activate the virtual environment manually, use: + +```shell +poetry run python3 tools/parseschema2.py ./mei/mei-verovio_compiled.odd +``` Where the positional argument points to an ODD file for which you wish to generate code. From 4fb0465cf0371747c08df6d0dac89e946a7b5f44 Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sun, 2 Feb 2025 13:45:02 +0100 Subject: [PATCH 6/7] add description --- libmei/pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmei/pyproject.toml b/libmei/pyproject.toml index 69170c61a41..c37d3d603ee 100644 --- a/libmei/pyproject.toml +++ b/libmei/pyproject.toml @@ -6,7 +6,7 @@ dependencies = [ "lxml (>=5.3.0)", ] requires-python = ">=3.9" -description = "" +description = "LibMEI is a C++ library for reading and writing MEI files" authors = [ {name = "Andrew Hankinson", email="andrew.hankinson@gmail.com"}, ] @@ -14,7 +14,7 @@ readme = "README.md" license = "MIT" [tool.poetry] -packages = [{include = "poetry_demo"}] +package-mode = false [build-system] requires = ["poetry-core>=2.0"] From c81a94513588840f064d5bb5cd999d28543ae74c Mon Sep 17 00:00:00 2001 From: Klaus Rettinghaus Date: Sun, 2 Feb 2025 18:53:46 +0100 Subject: [PATCH 7/7] introduce ruff --- libmei/pyproject.toml | 3 + libmei/tools/cpp.py | 116 +++++++++++++++-------------------- libmei/tools/parseschema2.py | 4 +- libmei/tools/schema.py | 49 +++++++++------ 4 files changed, 84 insertions(+), 88 deletions(-) diff --git a/libmei/pyproject.toml b/libmei/pyproject.toml index c37d3d603ee..4089084dce7 100644 --- a/libmei/pyproject.toml +++ b/libmei/pyproject.toml @@ -19,3 +19,6 @@ package-mode = false [build-system] requires = ["poetry-core>=2.0"] build-backend = "poetry.core.masonry.api" + +[tool.ruff] +line-length = 120 diff --git a/libmei/tools/cpp.py b/libmei/tools/cpp.py index 653b4c5dbfd..63a0fd8108e 100644 --- a/libmei/tools/cpp.py +++ b/libmei/tools/cpp.py @@ -10,12 +10,9 @@ from schema import MeiSchema -lg = logging.getLogger('schemaparser') +lg = logging.getLogger("schemaparser") -NS_PREFIX_MAP = { - "http://www.w3.org/XML/1998/namespace": "xml", - "http://www.w3.org/1999/xlink": "xlink" -} +NS_PREFIX_MAP = {"http://www.w3.org/XML/1998/namespace": "xml", "http://www.w3.org/1999/xlink": "xlink"} AUTHORS = "Andrew Hankinson, Alastair Porter, and Others" @@ -584,8 +581,7 @@ class AttModule {{ DATATYPES: dict -TEI_RNG_NS = {"tei": "http://www.tei-c.org/ns/1.0", - "rng": "http://relaxng.org/ns/structure/1.0"} +TEI_RNG_NS = {"tei": "http://www.tei-c.org/ns/1.0", "rng": "http://relaxng.org/ns/structure/1.0"} def vrv_member_cc(name: str) -> str: @@ -598,7 +594,7 @@ def vrv_member_cc_upper(name: str) -> str: def vrv_converter_cc(name: str) -> str: - left, right = name.split('_', 1) + left, right = name.split("_", 1) rest = "".join([n[0].upper() + n[1:].lower() for n in right.split("_")]) if left == "data": return rest @@ -668,12 +664,16 @@ def vrv_getatttype(schema, module: str, gp: str, aname: str) -> str: return attype # No override, get it from the schema - definition = schema.xpath("//tei:classSpec[@ident=$gp]/tei:attList/tei:attDef[@ident=$name]", gp=gp, name=aname, namespaces=TEI_RNG_NS) + definition = schema.xpath( + "//tei:classSpec[@ident=$gp]/tei:attList/tei:attDef[@ident=$name]", gp=gp, name=aname, namespaces=TEI_RNG_NS + ) if not definition: return "std::string" # First numbers - el = definition[0].xpath("tei:datatype/tei:dataRef/@name|tei:datatype/rng:data/@type", name=aname, namespaces=TEI_RNG_NS) + el = definition[0].xpath( + "tei:datatype/tei:dataRef/@name|tei:datatype/rng:data/@type", name=aname, namespaces=TEI_RNG_NS + ) if el: if el[0] in ("integer", "positiveInteger", "nonNegativeInteger"): return "int" @@ -681,7 +681,9 @@ def vrv_getatttype(schema, module: str, gp: str, aname: str) -> str: return "double" # The data types - ref = definition[0].xpath("tei:datatype/tei:dataRef/@key|tei:datatype/rng:ref/@name", gp=gp, name=aname, namespaces=TEI_RNG_NS) + ref = definition[0].xpath( + "tei:datatype/tei:dataRef/@key|tei:datatype/rng:ref/@name", gp=gp, name=aname, namespaces=TEI_RNG_NS + ) if ref: return vrv_getformattedtype(f"{ref[0]}") @@ -726,16 +728,16 @@ def vrv_getattdefault(schema, module: str, gp: str, aname: str) -> tuple: def create_docstr(text: str, indent: int = 0) -> str: """ - Format a docstring. Take the first sentence (. followed by a space) - and use it for the brief. Then put the rest of the text after a blank - line if there is text there + Format a docstring. Take the first sentence (. followed by a space) + and use it for the brief. Then put the rest of the text after a blank + line if there is text there """ text = text.strip() dotpos = text.find(". ") if dotpos > 0: - brief = text[:dotpos+1] - content = text[dotpos+2:] + brief = text[: dotpos + 1] + content = text[dotpos + 2 :] else: brief = text content = "" @@ -810,7 +812,7 @@ def create_att_classes(cpp_ns: str, schema, outdir: Path): "attType": att_type, "attDefault": attdefault, "converterRead": converters[0], - "converterWrite": converters[1] + "converterWrite": converters[1], } if len(methods) > 0: @@ -844,7 +846,6 @@ def create_att_classes(cpp_ns: str, schema, outdir: Path): "reads": "".join(reads), "writes": "".join(writes), "checkers": "".join(checkers), - } header_classes.append(ATTCLASS_H.format_map(clsubstr).strip()) impl_classes.append(ATTCLASS_CPP.format_map(clsubstr).strip()) @@ -852,13 +853,13 @@ def create_att_classes(cpp_ns: str, schema, outdir: Path): tplvars = { "includes": "#include ", - 'license': LICENSE.format(authors=AUTHORS), - 'moduleNameCaps': f"ATTS_{module.upper()}", + "license": LICENSE.format(authors=AUTHORS), + "moduleNameCaps": f"ATTS_{module.upper()}", "moduleNameCap": module.capitalize(), "moduleNameLower": f"atts_{module.lower()}", - 'headerElements': "\n\n".join(header_classes), - 'implElements': "\n\n".join(impl_classes), - 'ns': cpp_ns + "headerElements": "\n\n".join(header_classes), + "implElements": "\n\n".join(impl_classes), + "ns": cpp_ns, } with Path(outdir, f"atts_{module.lower()}.h").open("w") as f_att_class_h: @@ -899,16 +900,13 @@ def create_att_datatypes(cpp_ns: str, schema, outdir: Path): "meitype": data_type, "vrvtype": vrv_getformattedtype(data_type), "enumtype": " : int8_t" if len(values) < 64 else "", - "val_prefix": val_prefix + "val_prefix": val_prefix, } att_type_data_types.append(TYPE_START.format_map(type_start_fmt)) vrv_type = vrv_getformattedtype(data_type) vrv_fname = vrv_converter_cc(vrv_type) - converter_start_fmt = { - "type": vrv_type, - "fname": vrv_fname - } + converter_start_fmt = {"type": vrv_type, "fname": vrv_fname} att_converter_header_data_types.append(CONVERTER_METHODS_H.format_map(converter_start_fmt)) att_converter_impl_from_converters.append(CONVERTER_METHOD1_START_CPP.format_map(converter_start_fmt)) @@ -917,11 +915,7 @@ def create_att_datatypes(cpp_ns: str, schema, outdir: Path): for v in values: val: str = re.sub(r"[\.\-\,]", "_", v) val = re.sub(r"\+", "plus", val) - val_fmt = { - "val_prefix": val_prefix, - "value": val, - "string": v - } + val_fmt = {"val_prefix": val_prefix, "value": val, "string": v} att_type_data_types.append(TYPE_VALUE.format_map(val_fmt)) att_converter_impl_from_converters.append(CONVERTER_METHOD1_CPP.format_map(val_fmt)) @@ -929,10 +923,7 @@ def create_att_datatypes(cpp_ns: str, schema, outdir: Path): att_type_data_types.append(TYPE_END.format(val_prefix=val_prefix)) - converter_end_fmt = { - "prefix": val_prefix, - "type": data_type - } + converter_end_fmt = {"prefix": val_prefix, "type": data_type} att_converter_impl_from_converters.append(CONVERTER_METHOD1_END_CPP.format_map(converter_end_fmt)) att_converter_impl_to_converters.append(CONVERTER_METHOD2_END_CPP.format_map(converter_end_fmt)) @@ -950,21 +941,18 @@ def create_att_datatypes(cpp_ns: str, schema, outdir: Path): lg.debug("Skipping %s", list_type) continue - val_prefix = vrv_getformattedvallist(list_type.rsplit('@')[0], list_type.rsplit('@')[1]) + val_prefix = vrv_getformattedvallist(list_type.rsplit("@")[0], list_type.rsplit("@")[1]) type_start_fmt = { "meitype": list_type.replace("@", "\@"), "vrvtype": val_prefix, "enumtype": " : int8_t" if len(values) < 64 else "", - "val_prefix": val_prefix + "val_prefix": val_prefix, } att_type_data_list.append(TYPE_START.format_map(type_start_fmt)) vrv_type = val_prefix vrv_fname = vrv_converter_cc(vrv_type) - converter_start_fmt = { - "type": vrv_type, - "fname": vrv_fname - } + converter_start_fmt = {"type": vrv_type, "fname": vrv_fname} att_converter_header_data_list.append(CONVERTER_METHODS_H.format_map(converter_start_fmt)) att_converter_impl_from_converters.append(CONVERTER_METHOD1_START_CPP.format_map(converter_start_fmt)) att_converter_impl_to_converters.append(CONVERTER_METHOD2_START_CPP.format_map(converter_start_fmt)) @@ -972,11 +960,7 @@ def create_att_datatypes(cpp_ns: str, schema, outdir: Path): for v in values: val: str = re.sub(r"[\.\-\,]", "_", v) val = re.sub(r"\+", "plus", val) - val_fmt = { - "val_prefix": val_prefix, - "value": val, - "string": v - } + val_fmt = {"val_prefix": val_prefix, "value": val, "string": v} att_type_data_list.append(TYPE_VALUE.format_map(val_fmt)) att_converter_impl_from_converters.append(CONVERTER_METHOD1_CPP.format_map(val_fmt)) att_converter_impl_to_converters.append(CONVERTER_METHOD2_CPP.format_map(val_fmt)) @@ -1045,7 +1029,7 @@ def create_element_classes(cpp_ns: str, schema, outdir: Path): "elementNameUpper": schema.cc(element), "attClasses": "".join(element_att_classes), "documentation": docstr.strip(), - "elementName": element + "elementName": element, } element_output.append(ELEMENTCLASS_H.format_map(elvars)) @@ -1062,7 +1046,7 @@ def create_element_classes(cpp_ns: str, schema, outdir: Path): "license": LICENSE.format(authors=AUTHORS), "ns": cpp_ns, "moduleNameCaps": module.upper().replace("-", "_"), - "headerElements": "".join(element_output).strip() + "headerElements": "".join(element_output).strip(), } with Path(outdir, f"{module.lower()}.h").open("w") as f_element_class_h: @@ -1101,22 +1085,22 @@ def create_element_classes(cpp_ns: str, schema, outdir: Path): write_param = "pugi::xml_node element, const std::string &xmlId" consvars = { - 'elementNameUpper': schema.cc(element), - 'elementNameLower': element, - 'attClasses': "".join(element_att_classes), - 'elementRead': "".join(element_read), - 'elementWrite': "".join(element_write), - 'elementReset': "".join(element_reset), - 'readParam': read_param, - 'writeParam': write_param + "elementNameUpper": schema.cc(element), + "elementNameLower": element, + "attClasses": "".join(element_att_classes), + "elementRead": "".join(element_read), + "elementWrite": "".join(element_write), + "elementReset": "".join(element_reset), + "readParam": read_param, + "writeParam": write_param, } element_constructor.append(ELEMENTCLASS_CPP.format_map(consvars)) implvars = { - 'moduleNameLower': module.lower(), - 'elements': "".join(element_constructor), - 'license': LICENSE.format(authors=AUTHORS), - 'ns': cpp_ns + "moduleNameLower": module.lower(), + "elements": "".join(element_constructor), + "license": LICENSE.format(authors=AUTHORS), + "ns": cpp_ns, } with Path(outdir, f"{module.lower()}.cpp").open("w") as f_element_class_cpp: @@ -1144,7 +1128,7 @@ def create_att_module(cpp_ns: str, schema, outdir: Path): set_get_fmt = { "attGroupNameUpper": schema.cc(schema.strpatt(gp)), - "attId": f"ATT_{schema.cc(schema.strpatt(gp)).upper()}" + "attId": f"ATT_{schema.cc(schema.strpatt(gp)).upper()}", } setters.append(SETTERS_GRP_START_CPP.format_map(set_get_fmt)) getters.append(GETTERS_GRP_START_CPP.format_map(set_get_fmt)) @@ -1166,7 +1150,7 @@ def create_att_module(cpp_ns: str, schema, outdir: Path): "attNameLower": att_name_lower, "attNameLowerJoined": vrv_member_cc(att), "converterRead": converters[0], - "converterWrite": converters[1] + "converterWrite": converters[1], } setters.append(SETTERS_GRP_CPP.format_map(attsubstr)) getters.append(GETTERS_GRP_CPP.format_map(attsubstr)) @@ -1285,10 +1269,10 @@ def create_basic_validator(configure: dict, outdir: Path): attrlist.append(att) if attrlist: - fmt_attr = "\", \"".join(attrlist) + fmt_attr = '", "'.join(attrlist) fmt_attr_str = f'{{"{fmt_attr}"}}' else: - fmt_attr_str = '{}' + fmt_attr_str = "{}" fmt_attr_map = f' {{"{elname}", {fmt_attr_str}}},\n' formatted_attr_map.append(fmt_attr_map) diff --git a/libmei/tools/parseschema2.py b/libmei/tools/parseschema2.py index bb9952dfd22..6520ece236a 100644 --- a/libmei/tools/parseschema2.py +++ b/libmei/tools/parseschema2.py @@ -33,7 +33,7 @@ from schema import MeiSchema logging.basicConfig(format="[%(asctime)s] [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)") -log = logging.getLogger('schemaparser') +log = logging.getLogger("schemaparser") def main(configure: dict) -> bool: @@ -53,7 +53,7 @@ def main(configure: dict) -> bool: if __name__ == "__main__": - p = ArgumentParser(usage='%(prog)s [-c config path] [compiled odd path]') + p = ArgumentParser(usage="%(prog)s [-c config path] [compiled odd path]") p.add_argument("compiled", help="A compiled ODD file", type=Path) p.add_argument("-c", "--config", default="./config.yml", help="Path to a config file", type=Path) diff --git a/libmei/tools/schema.py b/libmei/tools/schema.py index dd38620c7d8..21dfc656433 100644 --- a/libmei/tools/schema.py +++ b/libmei/tools/schema.py @@ -5,15 +5,13 @@ from lxml import etree logging.basicConfig(format="[%(asctime)s] [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)") -log = logging.getLogger('schemaparser') +log = logging.getLogger("schemaparser") # globals TEI_NS = {"tei": "http://www.tei-c.org/ns/1.0"} -TEI_RNG_NS = {"tei": "http://www.tei-c.org/ns/1.0", - "rng": "http://relaxng.org/ns/structure/1.0"} -NAMESPACES = {'xml': 'http://www.w3.org/XML/1998/namespace', - 'xlink': 'http://www.w3.org/1999/xlink'} +TEI_RNG_NS = {"tei": "http://www.tei-c.org/ns/1.0", "rng": "http://relaxng.org/ns/structure/1.0"} +NAMESPACES = {"xml": "http://www.w3.org/XML/1998/namespace", "xlink": "http://www.w3.org/1999/xlink"} WHITESPACE_REGEX: Pattern = re.compile(r"[\s\t]+") @@ -86,8 +84,7 @@ def get_attribute_groups(self): """ Retrieve all defined attribute classes from the schema. """ - attribute_groups: list[etree.Element] = self.schema.xpath(".//tei:classSpec[@type='atts']", - namespaces=TEI_NS) + attribute_groups: list[etree.Element] = self.schema.xpath(".//tei:classSpec[@type='atts']", namespaces=TEI_NS) for group in attribute_groups: group_name: str = group.get("ident") @@ -113,40 +110,50 @@ def get_data_types_and_lists(self): """ Parse data types from the schema. """ - compound_alternate = self.schema.xpath(".//tei:macroSpec[@type='dt' and .//tei:alternate[@minOccurs='1' and @maxOccurs='1']]", - namespaces=TEI_RNG_NS) + compound_alternate = self.schema.xpath( + ".//tei:macroSpec[@type='dt' and .//tei:alternate[@minOccurs='1' and @maxOccurs='1']]", + namespaces=TEI_RNG_NS, + ) for ct in compound_alternate: data_type = ct.get("ident") subtypes = ct.findall(".//tei:alternate/tei:macroRef", namespaces=TEI_RNG_NS) for st in subtypes: - subtype = self.schema.xpath(".//tei:macroSpec[@ident=$st_ident]//tei:valList/tei:valItem", - st_ident=st.get("key"), - namespaces=TEI_RNG_NS) + subtype = self.schema.xpath( + ".//tei:macroSpec[@ident=$st_ident]//tei:valList/tei:valItem", + st_ident=st.get("key"), + namespaces=TEI_RNG_NS, + ) for v in subtype: if data_type not in self.data_types: self.data_types[data_type] = [] self.data_types[data_type].append(v.get("ident")) - compound_choice = self.schema.xpath(".//tei:macroSpec[@type='dt' and .//rng:choice]|//tei:dataSpec[.//rng:choice]", - namespaces=TEI_RNG_NS) + compound_choice = self.schema.xpath( + ".//tei:macroSpec[@type='dt' and .//rng:choice]|//tei:dataSpec[.//rng:choice]", namespaces=TEI_RNG_NS + ) for ct in compound_choice: data_type = ct.get("ident") subtypes = ct.xpath(".//rng:choice/rng:ref", namespaces=TEI_RNG_NS) for st in subtypes: - subtype = st.xpath("//tei:macroSpec[@ident=$st_ident]//tei:valList/tei:valItem|//tei:dataSpec[@ident=$st_ident]//tei:valList/tei:valItem", - st_ident=st.get("name"), - namespaces=TEI_RNG_NS) + subtype = st.xpath( + "//tei:macroSpec[@ident=$st_ident]//tei:valList/tei:valItem|//tei:dataSpec[@ident=$st_ident]//tei:valList/tei:valItem", + st_ident=st.get("name"), + namespaces=TEI_RNG_NS, + ) for v in subtype: if data_type not in self.data_types: self.data_types[data_type] = [] self.data_types[data_type].append(v.get("ident")) - types = self.schema.xpath(".//tei:macroSpec[.//tei:valList[@type='closed' or @type='semi']]|//tei:dataSpec[.//tei:valList[@type='closed' or @type='semi']]", namespaces=TEI_RNG_NS) + types = self.schema.xpath( + ".//tei:macroSpec[.//tei:valList[@type='closed' or @type='semi']]|//tei:dataSpec[.//tei:valList[@type='closed' or @type='semi']]", + namespaces=TEI_RNG_NS, + ) for t in types: data_type = t.get("ident") values = t.findall(".//tei:valList/tei:valItem", namespaces=TEI_RNG_NS) @@ -201,7 +208,9 @@ def __get_membership(self, member: etree.Element, resarr: list[str]) -> None: """ Get attribute groups. """ - member_attgroup = self.schema.xpath(".//tei:classSpec[@type='atts'][@ident=$nm]", nm=member.get("key"), namespaces=TEI_NS) + member_attgroup = self.schema.xpath( + ".//tei:classSpec[@type='atts'][@ident=$nm]", nm=member.get("key"), namespaces=TEI_NS + ) if member_attgroup is None: return None @@ -253,4 +262,4 @@ def get_elem_desc(self, elem_name: str) -> str: if desc is None: return "" - return re.sub(WHITESPACE_REGEX, " ", desc.xpath("string()")) \ No newline at end of file + return re.sub(WHITESPACE_REGEX, " ", desc.xpath("string()"))