Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release notes

## v0.1.4 (unreleased)

* Updates for Eskin and Bill Black ({pull}`112`)

## v0.1.3 (2026-04-17)

* Improve styling of abcjs containers, pandas dataframes, and ipywidgets
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/sources.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@
"metadata": {},
"outputs": [],
"source": [
"Tune(df.query(\"group == 'jigs'\").iloc[0].abc)"
"Tune(df.query(\"group == 'Jig A-G'\").iloc[0].abc)"
]
},
{
Expand Down
73 changes: 48 additions & 25 deletions pyabc2/sources/bill_black.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* `requests <https://requests.readthedocs.io/>`__
"""

import functools
import logging
import re
from pathlib import Path
Expand All @@ -20,48 +21,70 @@

SAVE_TO = HERE / "_bill-black"
TXT_FNS = [
"a-tunes-1.txt",
"b-tunes-1.txt",
"c-tunes-1.txt",
"d-tunes-1.txt",
"e-tunes-1.txt",
"f-tunes-1.txt",
"g-tunes-1.txt",
"h-tunes-1.txt",
"i-tunes-1.txt",
"j-tunes-1.txt",
"k-tunes-1.txt",
"l-tunes-1.txt",
"m-tunes-1.txt",
"n-tunes-1.txt",
"o-tunes-1.txt",
"pq-tunes-1.txt",
"r-tunes-1.txt",
"s-tunes-2.rtf",
"t-tunes-1.txt",
"uv-tunes-1.txt",
"wz-tunes-1.txt",
"a-tunes.txt",
"b-tunes.txt",
"c-tunes.txt",
"d-tunes.txt",
"e-tunes.txt",
"f-tunes.txt",
"g-tunes.txt",
"h-tunes.txt",
"i-tunes.txt",
"j-tunes.txt",
"k-tunes.txt",
"L-tunes.txt",
Comment thread
zmoon marked this conversation as resolved.
"m-tunes.txt",
"n-tunes.txt",
"o-tunes.txt",
"pq-tunes.txt",
"r-tunes.txt",
"s-tunes.txt",
"t-tunes.txt",
"uv-tunes.txt",
"wxyz-tunes.txt",
]


@functools.lru_cache(1)
def _get_session():
import requests
from requests.adapters import HTTPAdapter
from urllib3.util import Retry

session = requests.Session()
session.headers.update({"User-Agent": "pyabc2"})
retries = Retry(
total=10,
backoff_factor=1.0,
backoff_jitter=0.5,
allowed_methods={"GET", "HEAD"},
status_forcelist=[403, 429, 500, 502, 503, 504],
# Bill Black seems to sporadically return 403 (forbidden)
# possibly to indicate a temporary server issue or throttling/anti-bot
)
session.mount("https://", HTTPAdapter(max_retries=retries))
Comment thread
zmoon marked this conversation as resolved.

return session


def download() -> None:
"""Download the alphabetical text files from https://www.capeirish.com/ittl/alltunes/text/
"""Download the alphabetical text files from https://www.capeirish.com/ittl/alltunes/alltunes-text/
and store them in a compressed archive.
"""
import zipfile
from concurrent.futures import ThreadPoolExecutor

import requests
session = _get_session()

def download_one(url):
r = requests.get(url, headers={"User-Agent": "pyabc2"}, timeout=5)
r = session.get(url, timeout=5)
r.raise_for_status()
Comment thread
zmoon marked this conversation as resolved.
Outdated
return r.text

with ThreadPoolExecutor(max_workers=4) as executor:
futures = []
for fn in TXT_FNS:
url = f"https://www.capeirish.com/ittl/alltunes/text/{fn}"
url = f"https://www.capeirish.com/ittl/alltunes/alltunes-text/{fn}"
futures.append(executor.submit(download_one, url))

SAVE_TO.mkdir(exist_ok=True)
Expand Down
9 changes: 5 additions & 4 deletions pyabc2/sources/bill_black_tunefolders.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
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 (https://www.capeirish.com/ittl/alltunes/html/),
while also posting ABC text files (https://www.capeirish.com/ittl/alltunes/text/),
Bill Black is now using the Eskin ABC Tools (https://www.capeirish.com/ittl/alltunes/alltunes-html/),
while also posting ABC text files (https://www.capeirish.com/ittl/alltunes/alltunes-text/),
both split up alphabetically by tune name.

Requires:
Expand All @@ -19,6 +19,7 @@
from pathlib import Path

from pyabc2._util import get_logger as _get_logger
from pyabc2.sources.bill_black import _get_session

logger = _get_logger(__name__)

Expand Down Expand Up @@ -209,7 +210,7 @@ def get_collection(key: str) -> Collection:
def download(key: str | Iterable[str] | None = None) -> None:
import gzip

import requests
session = _get_session()

SAVE_TO.mkdir(exist_ok=True)

Expand All @@ -224,7 +225,7 @@ def download(key: str | Iterable[str] | None = None) -> None:
for url in collection.abc_urls:
p = collection.url_to_file(url)
logger.info(f"Downloading {url} to {p.relative_to(HERE).as_posix()}")
r = requests.get(url, headers={"User-Agent": "pyabc2"}, timeout=5)
r = session.get(url, timeout=5)
r.raise_for_status()

# Extract filename from URL and append .gz
Expand Down
Loading