diff --git a/dzgui/api/mods.py b/dzgui/api/mods.py index 70ddc5b..c115d11 100644 --- a/dzgui/api/mods.py +++ b/dzgui/api/mods.py @@ -1,6 +1,6 @@ import hashlib import logging -import shlex +import re from concurrent.futures import wait from concurrent.futures import ThreadPoolExecutor @@ -53,39 +53,25 @@ def is_mission(path: Path) -> bool: file = path / "init.c" return file.exists() -def parse_meta(file: Path) -> ModMeta | None: - mod = file / "meta.cpp" - if mod.exists() is False: - return None +def tokenize(file: str) -> dict[Any] | None: + delimiter=r"\s*=\s*" + modmeta = {} try: - with open(file / "meta.cpp", "r") as f: - st = f.read() - lex = shlex.shlex(st) - lex.whitespace += "=;" - v = [] - while True: - tok = lex.get_token() - if not tok: - break - if tok == "protocol" or tok == "publishedid": - ntok = lex.get_token() - elif tok == "timestamp": - # NOTE: some malformed .NET tick conversions result in numbers < 0 - ntok = lex.get_token() - if ntok == "-": - ntok += str(lex.get_token()) - elif tok == "name": - ntok = lex.get_token() - if ntok is not None: - ntok = ntok.split('"')[1] - if ntok is not None: - v.append(ntok) - return ModMeta(*v) + with open(file, "r", encoding="utf-8") as file: + for line in file: + line = line.strip().rstrip(";") + if not line: + continue + els = re.split(delimiter, line, maxsplit=1) + if len(els) == 2: + key, value = els + print(value) + modmeta[key.strip()] = value.strip('"') + return modmeta except Exception as e: logger.critical(e) return None - def get_mod_size(path: Path) -> float: s = 0 for f in path.rglob("*"): @@ -105,12 +91,12 @@ def parse_mods(mods: list[Path]) -> list[Any]: for mod in mods: mod_dir = mod.name symlink = _hash(mod_dir) - meta = parse_meta(mod) + meta = tokenize(mod) if meta is None: continue size = get_mod_size(mod) # NOTE: final col is cell renderer highlight toggle - clean.append([meta.name, symlink, mod_dir, size, False]) + clean.append([meta["name"], symlink, mod_dir, size, False]) clean.sort(key=lambda row: str(row[0]).casefold()) return clean diff --git a/tests/fixtures/cpp/meta1.cpp b/tests/fixtures/cpp/meta1.cpp new file mode 100644 index 0000000..b43c25f --- /dev/null +++ b/tests/fixtures/cpp/meta1.cpp @@ -0,0 +1,5 @@ +protocol = 1; +publishedid = 1234567890; +name = "ModName"; +timestamp = 638278452000000000; +hash = "a1b2c3d4e5f6g7h8i9j0"; diff --git a/tests/fixtures/cpp/meta2.cpp b/tests/fixtures/cpp/meta2.cpp new file mode 100644 index 0000000..4308b4f --- /dev/null +++ b/tests/fixtures/cpp/meta2.cpp @@ -0,0 +1,5 @@ +protocol = 1 +publishedid = 1234567890 +name = "ModName" +timestamp = 638278452000000000 +hash = "a1b2c3d4e5f6g7h8i9j0" diff --git a/tests/fixtures/cpp/meta3.cpp b/tests/fixtures/cpp/meta3.cpp new file mode 100644 index 0000000..2b32c3d --- /dev/null +++ b/tests/fixtures/cpp/meta3.cpp @@ -0,0 +1,5 @@ +protocol=1 +publishedid=1234567890 +name="ModName" +timestamp=638278452000000000 +hash="a1b2c3d4e5f6g7h8i9j0" diff --git a/tests/fixtures/cpp/meta4.cpp b/tests/fixtures/cpp/meta4.cpp new file mode 100644 index 0000000..1a8d18a --- /dev/null +++ b/tests/fixtures/cpp/meta4.cpp @@ -0,0 +1,5 @@ +protocol=1 +publishedid=1234567890 +name=ModName +timestamp=638278452000000000 +hash=a1b2c3d4e5f6g7h8i9j0 diff --git a/tests/fixtures/cpp/meta5.cpp b/tests/fixtures/cpp/meta5.cpp new file mode 100644 index 0000000..bfd7976 --- /dev/null +++ b/tests/fixtures/cpp/meta5.cpp @@ -0,0 +1,5 @@ +protocol=1; +publishedid=1234567890; +name=ModName; +timestamp=638278452000000000; +hash=a1b2c3d4e5f6g7h8i9j0; diff --git a/tests/fixtures/cpp/meta6.cpp b/tests/fixtures/cpp/meta6.cpp new file mode 100644 index 0000000..4991854 --- /dev/null +++ b/tests/fixtures/cpp/meta6.cpp @@ -0,0 +1,5 @@ +protocol=1 +publishedid=1234567890; +name="ModName"; +timestamp=638278452000000000; +hash= a1b2c3d4e5f6g7h8i9j0; diff --git a/tests/fixtures/cpp/test.py b/tests/fixtures/cpp/test.py new file mode 100644 index 0000000..453b6d7 --- /dev/null +++ b/tests/fixtures/cpp/test.py @@ -0,0 +1,3 @@ +from dzgui.api.mods import tokenize + +print(tokenize("meta4.cpp")) diff --git a/tests/test_modmeta.py b/tests/test_modmeta.py new file mode 100644 index 0000000..f2f4ca4 --- /dev/null +++ b/tests/test_modmeta.py @@ -0,0 +1,17 @@ +import pytest +from dzgui.api.mods import tokenize +from tests.fixtures import fixture_path + +@pytest.mark.mods +@pytest.mark.parametrize("fixture", [ + fixture_path("cpp/meta1.cpp"), + fixture_path("cpp/meta2.cpp"), + fixture_path("cpp/meta3.cpp"), + fixture_path("cpp/meta4.cpp"), + fixture_path("cpp/meta5.cpp"), + fixture_path("cpp/meta6.cpp"), + ] +) +def test_modmeta(fixture: str) -> None: + meta = tokenize(fixture) + assert meta["name"] == "ModName"