Skip to content
Merged
5 changes: 5 additions & 0 deletions docs/changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Release notes

## v0.1.2 (unreleased)

* Update Norbeck to the current 2026-01 version ({pull}`96`)
* Various Bill Black fixes ({pull}`96`)

## v0.1.1 (2026-01-20)

* Fix loading The Session sets data ({pull}`77`)
Expand Down
3 changes: 3 additions & 0 deletions docs/examples/sources.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
},
"mystnb": {
"execution_timeout": 60
}
},
"nbformat": 4,
Expand Down
12 changes: 8 additions & 4 deletions pyabc2/sources/bill_black.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Bill Black's Irish Traditional Tune Library

http://www.capeirish.com/ittl/
https://www.capeirish.com/ittl/
"""

import logging
Expand Down Expand Up @@ -33,15 +33,15 @@
"o-tunes-1.txt",
"pq-tunes-1.txt",
"r-tunes-1.txt",
"s-tunes-2.txt",
"s-tunes-2.rtf",
"t-tunes-1.txt",
"uv-tunes-1.txt",
"wz-tunes-1.txt",
]


def download() -> None:
"""Download the alphabetical text files from http://www.capeirish.com/ittl/alltunes/text/
"""Download the alphabetical text files from https://www.capeirish.com/ittl/alltunes/text/
and store them in a compressed archive.
"""
import zipfile
Expand All @@ -57,7 +57,7 @@ def download_one(url):
with ThreadPoolExecutor(max_workers=4) as executor:
futures = []
for fn in TXT_FNS:
url = f"http://www.capeirish.com/ittl/alltunes/text/{fn}"
url = f"https://www.capeirish.com/ittl/alltunes/text/{fn}"
futures.append(executor.submit(download_one, url))

SAVE_TO.mkdir(exist_ok=True)
Expand Down Expand Up @@ -118,6 +118,10 @@ def load_meta(*, redownload: bool = False, debug: bool = False) -> list[str]:
line.strip() for line in text.splitlines() if not line.lstrip().startswith("%")
)

# For RTF, remove trailing backslashes
if fn.endswith(".rtf"):
text = "\n".join(line.rstrip("\\") for line in text.splitlines()).rstrip("}")

# Find the start of the first tune, in order to skip header info
start = text.find("X:")
if start == -1: # pragma: no cover
Expand Down
93 changes: 73 additions & 20 deletions pyabc2/sources/bill_black_tunefolders.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""
Bill Black's Irish Traditional Tune Library

http://www.capeirish.com/ittl/
https://www.capeirish.com/ittl/

As of the 2025-06-14 update, the "tunefolders" method is deprecated.
Bill Black is now using the Eskin ABC Tools (http://www.capeirish.com/ittl/alltunes/html/),
while also posting ABC text files (http://www.capeirish.com/ittl/alltunes/text/),
Bill Black is now using the Eskin ABC Tools (https://www.capeirish.com/ittl/alltunes/html/),
while also posting ABC text files (https://www.capeirish.com/ittl/alltunes/text/),
both split up alphabetically by tune name.
"""

Expand All @@ -20,7 +20,7 @@

HERE = Path(__file__).parent

ITTL = "http://www.capeirish.com/ittl/"
ITTL = "https://www.capeirish.com/ittl/"
SAVE_TO = HERE / "_bill-black_tunefolders"


Expand Down Expand Up @@ -65,13 +65,26 @@ 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"],
subfolders=[
"12-AE",
"12-FJ",
"12-KQ",
"12-RST",
"12-UY",
],
),
Collection(
key="bs",
title="Bulmer & Sharpley",
folder="13",
subfolders=["13-hps", "13-jigs", "13-misc", "13-p&s", "13-reels", "13-sjigs"],
subfolders=[
"13-hps",
"13-jigs",
"13-misc",
"13-p&s",
"13-reels",
"13-sjigs",
],
),
Collection(
key="car",
Expand All @@ -82,50 +95,83 @@ def url_to_file(self, url: str) -> Path:
key="cre",
title="Ceol Rince na hÉireann",
folder="18",
subfolders=["18-hornpipes", "18-jigs", "18-polkas_slides", "18-reels", "18-slipjigs"],
subfolders=[
"18-hornpipes",
"18-jigs",
"18-polkas_slides",
"18-reels",
"18-slipjigs",
],
),
Collection(
key="dmi",
title="Dance Music of Ireland",
folder="21",
subfolders=["hps", "jigs", "reels", "slipjigs"],
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"],
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"],
subfolders=[
"hps",
"jigs",
"misc",
"p&s",
"reels",
],
),
Collection(
key="jol",
title="Johnny O'Leary of Sliabh Luachra",
folder="31",
subfolders=["31-hps", "31-jigs", "31-misc", "31-polkas", "31-reels", "31-slides"],
subfolders=[
"31-hps",
"31-jigs",
"31-misc",
"31-polkas",
"31-reels",
"31-slides",
],
),
Collection(
key="levey",
title="Levey Collection",
folder="33",
subfolders=["33-hps", "33-jigs", "33-marches", "33-reels", "33-sjigs"],
subfolders=[
"33-hps",
"33-jigs",
"33-marches",
"33-reels",
"33-sjigs",
],
),
Collection(
key="ofpc",
title="O'Farrell's Pocket Companion",
folder="48",
subfolders=[
"48-hps",
"48-jigs",
"48-marches",
"48-misc",
"48-polkas",
"48-reels",
"48-sjigs",
"481",
"482",
"483",
"484",
],
),
Collection(
Expand All @@ -146,7 +192,14 @@ def url_to_file(self, url: str) -> Path:
key="roche",
title="Roche Collection",
folder="53",
subfolders=["53-hps", "53-jigs", "53-misc", "53-polkas", "53-reels", "53-sjigs"],
subfolders=[
"53-hps",
"53-jigs",
"53-misc",
"53-polkas",
"53-reels",
"53-sjigs",
],
),
]

Expand Down
2 changes: 1 addition & 1 deletion pyabc2/sources/norbeck.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def download() -> None:
import requests

# All Norbeck, including non-Irish
url = "https://www.norbeck.nu/abc/hn202110.zip"
url = "https://www.norbeck.nu/abc/hn202601.zip"

r = requests.get(url, timeout=5)

Expand Down
13 changes: 8 additions & 5 deletions tests/test_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
the_session,
)

NORBECK_IRISH_COUNT = 2733
NORBECK_IRISH_COUNT = 2813


@pytest.mark.parametrize("tune_name", examples)
Expand Down Expand Up @@ -416,6 +416,7 @@ def test_eskin_invalid_tunebook_key():
_ = eskin.get_tunebook_info("asdf")


@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
import requests
Expand All @@ -431,6 +432,7 @@ def test_bill_black_no_https():
r.raise_for_status()


@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
Expand Down Expand Up @@ -462,7 +464,7 @@ def test_bill_black_text_fns():
r = requests.get(url, headers={"User-Agent": "pyabc2"}, timeout=5)
r.raise_for_status()

fns_web = sorted(re.findall(r'href=["\']([a-z0-9\-]+\.txt)["\']', r.text))
fns_web = sorted(re.findall(r'href=["\']([a-z0-9\-]+\.(?:txt|rtf))["\']', r.text))
if "s-tunes-1.txt" in fns_web:
# We're using s-tunes-2, not both
fns_web.remove("s-tunes-1.txt")
Expand Down Expand Up @@ -500,11 +502,12 @@ def test_the_session_get_member_sets():


def test_the_session_get_member_sets_multipage():
sets = the_session.get_member_sets(1, pages=3, size=2, max_threads=2)
sets = the_session.get_member_sets(1, pages=3, size=2, max_threads=2, orderby="oldest")
assert len(sets) == 6
assert len(sets[0]) == 3
d = sets[0][0]
assert d["name"] == "Toss The Feathers"
assert d["tune_id"] == 138
assert d["name"] == "The Tarbolton"
assert d["tune_id"] == 560


def test_the_session_consume_validation():
Expand Down