diff --git a/docs/changes.md b/docs/changes.md index dff3c09..3814aad 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -7,6 +7,7 @@ You can now activate abcjs responsive mode in {class}`~pyabc2.abcjs.widget.ABCJSWidget`, but non-responsive is still the default. +* Update for changes in ({pull}`104`). ## v0.1.2 (2026-02-03) diff --git a/pyabc2/sources/bill_black_tunefolders.py b/pyabc2/sources/bill_black_tunefolders.py index 9247dcf..7a37944 100644 --- a/pyabc2/sources/bill_black_tunefolders.py +++ b/pyabc2/sources/bill_black_tunefolders.py @@ -69,12 +69,9 @@ def url_to_file(self, url: str) -> Path: key="bbmg", title="BB's Mostly Gems", folder="12", - subfolders=[ - "12-AE", - "12-FJ", - "12-KQ", - "12-RST", - "12-UY", + urls=[ + f"{ITTL}tunefolders/12/12-AM-ABC.rtf", + f"{ITTL}tunefolders/12/12-NY-ABC.rtf", ], ), Collection( @@ -82,64 +79,51 @@ def url_to_file(self, url: str) -> Path: title="Bulmer & Sharpley", folder="13", subfolders=[ - "13-hps", - "13-jigs", - "13-misc", - "13-p&s", - "13-reels", - "13-sjigs", + "131", + "132", + "133", + "134", ], ), Collection( key="car", title="Carolan Tunes", folder="14", + subfolders=[ + "14-AL", + "14-MY", + ], ), Collection( key="cre", title="Ceol Rince na hÉireann", folder="18", subfolders=[ - "18-hornpipes", - "18-jigs", - "18-polkas_slides", - "18-reels", - "18-slipjigs", + "181", + "182", + "183", + "184", + "185", ], ), Collection( key="dmi", title="Dance Music of Ireland", folder="21", - subfolders=[ - "hps", - "jigs", - "reels", - "slipjigs", - ], ), Collection( key="dmwc", title="Dance Music of Willie Clancy", folder="22", - subfolders=[ - "22-hps", - "22-jigs", - "22-misc", - "22-reels", - "22-sjigs", - ], ), Collection( key="foinn", title="Foinn Seisiún", folder="25", subfolders=[ - "hps", - "jigs", - "misc", - "p&s", - "reels", + "251", + "252", + "253", ], ), Collection( @@ -147,12 +131,8 @@ def url_to_file(self, url: str) -> Path: title="Johnny O'Leary of Sliabh Luachra", folder="31", subfolders=[ - "31-hps", - "31-jigs", - "31-misc", - "31-polkas", - "31-reels", - "31-slides", + "31-AI", + "31-JY", ], ), Collection( @@ -160,11 +140,8 @@ def url_to_file(self, url: str) -> Path: title="Levey Collection", folder="33", subfolders=[ - "33-hps", - "33-jigs", - "33-marches", - "33-reels", - "33-sjigs", + "331", + "332", ], ), Collection( @@ -182,14 +159,24 @@ def url_to_file(self, url: str) -> Path: key="moi", title="Music of Ireland", folder="49", - subfolders=[ - "491-airs", - "492-hps", - "493-jigs", - "494-misc", - "495-reels", - "496-sjigs", - "497-arr", + urls=[ + f"{ITTL}tunefolders/49/491-airs/491-AE/491-AE-ABC.rtf", + f"{ITTL}tunefolders/49/491-airs/491-FK/491-FK-ABC.rtf", + f"{ITTL}tunefolders/49/491-airs/491-LQ/491-LQ-ABC.rtf", + f"{ITTL}tunefolders/49/491-airs/491-RST/491-RST-ABC.rtf", + f"{ITTL}tunefolders/49/491-airs/491-WZ/491-WZ-ABC.rtf", + f"{ITTL}tunefolders/49/492-hps/492-AM/492-AM-ABC.rtf", + f"{ITTL}tunefolders/49/492-hps/492-NY/492-NY-ABC.rtf", + f"{ITTL}tunefolders/49/493-jigs/493-AH/493-AH-ABC.rtf", + f"{ITTL}tunefolders/49/493-jigs/493-IP/493-IP-ABC.rtf", + f"{ITTL}tunefolders/49/493-jigs/493-RY/493-RY-ABC.rtf", + f"{ITTL}tunefolders/49/494-misc/494-ABC.rtf", + f"{ITTL}tunefolders/49/495-reels/495-AF/495-AF-ABC.rtf", + f"{ITTL}tunefolders/49/495-reels/495-GL/495-GL-ABC.rtf", + f"{ITTL}tunefolders/49/495-reels/495-MR/495-MR-ABC.rtf", + f"{ITTL}tunefolders/49/495-reels/495-SY/495-SY-ABC.rtf", + f"{ITTL}tunefolders/49/496-sjigs/496-ABC.rtf", + f"{ITTL}tunefolders/49/497-arr/497-ABC.rtf", ], ), Collection( @@ -197,12 +184,10 @@ def url_to_file(self, url: str) -> Path: title="Roche Collection", folder="53", subfolders=[ - "53-hps", - "53-jigs", - "53-misc", - "53-polkas", - "53-reels", - "53-sjigs", + "531", + "532", + "533", + "534", ], ), ] @@ -291,8 +276,10 @@ def load_meta(key: str, *, redownload: bool = False, debug: bool = False) -> lis if start == -1: # pragma: no cover raise RuntimeError(f"Could not find start of tune in {p.name}") - # Split on 3 or more % - blocks = re.split(r"\s*%{3,}\s*", text[start:]) + # Split on lines that are solely 3 or more % (with optional trailing horizontal whitespace). + # Using \n+ on both sides consumes surrounding blank lines and avoids splitting on + # commented-out %% directives like `%%%staffwidth 650` (which have non-whitespace after %%%). + blocks = re.split(r"\n+%{3,}[ \t]*\n+", text[start:]) if not blocks: # pragma: no cover raise RuntimeError(f"Splitting blocks failed for {p.name}") @@ -306,8 +293,10 @@ def load_meta(key: str, *, redownload: bool = False, debug: bool = False) -> lis logger.debug(f"Tune in block {i} in {p.name} marked as deleted: {block!r}") continue - if not block.startswith("X:"): - logger.debug(f"Block {i} in {p.name} does not start with `X:`: {block!r}") + if not re.match(r"X: *[0-9]", block): + logger.debug( + f"Block {i} in {p.name} does not start with a valid `X:` field: {block!r}" + ) continue # Remove anything that may be after the final bar symbol diff --git a/tests/test_sources.py b/tests/test_sources.py index 7d21a41..d24c254 100644 --- a/tests/test_sources.py +++ b/tests/test_sources.py @@ -453,9 +453,7 @@ def test_eskin_inflate_pad_3(): assert eskin._inflate(eskin._deflate(s)) == s -@pytest.mark.xfail(reason="Bill Black site now has HTTPS", strict=False) -def test_bill_black_no_https(): - # If the site does get HTTPS, we'd like to know +def test_bill_black_https(): import requests url = "http://www.capeirish.com/ittl/tunefolders/" @@ -463,29 +461,17 @@ def test_bill_black_no_https(): r = requests.head(url, headers={"User-Agent": "pyabc2"}, timeout=5) r.raise_for_status() + assert "Strict-Transport-Security" not in r.headers - with pytest.raises(requests.exceptions.SSLError): - r = requests.head(url_https, headers={"User-Agent": "pyabc2"}, timeout=5) - r.raise_for_status() + r = requests.head(url_https, headers={"User-Agent": "pyabc2"}, timeout=5) + r.raise_for_status() + assert "Strict-Transport-Security" in r.headers @pytest.mark.xfail(reason="Bill Black tunefolders are currently in flux", strict=False) @pytest.mark.parametrize("key", list(bill_black_tunefolders._KEY_TO_COLLECTION)) def test_bill_black_tunefolders(key): - import requests - - col = bill_black_tunefolders.get_collection(key) - if int(col.folder) in {14, 18, 21, 25, 49}: - # 14, 18, 25 -- These only have .txt now, not .rtf - # 21 -- some subfolder names don't match the file names - # 49 -- has subsubfolders - with pytest.raises(requests.exceptions.HTTPError) as e: - lst = bill_black_tunefolders.load_meta(key) - assert e.value.response.status_code == 404 - return - else: - lst = bill_black_tunefolders.load_meta(key) - + lst = bill_black_tunefolders.load_meta(key, redownload=True) assert len(lst) > 0