From 2e9d92fa20d371f3df169fbab1aefeed20fdc73b Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 08:52:53 -0600 Subject: [PATCH 01/11] Move the abcjs-related modules together --- pyabc2/{ => abcjs}/html.py | 0 pyabc2/{ => abcjs}/sheet/__init__.py | 0 pyabc2/{ => abcjs}/sheet/cli.cjs | 0 pyabc2/{ => abcjs}/sheet/package.json | 0 pyabc2/{ => abcjs}/sheet/render.js | 0 pyabc2/{ => abcjs}/widget/__init__.py | 0 pyabc2/{ => abcjs}/widget/index.css | 0 pyabc2/{ => abcjs}/widget/index.js | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename pyabc2/{ => abcjs}/html.py (100%) rename pyabc2/{ => abcjs}/sheet/__init__.py (100%) rename pyabc2/{ => abcjs}/sheet/cli.cjs (100%) rename pyabc2/{ => abcjs}/sheet/package.json (100%) rename pyabc2/{ => abcjs}/sheet/render.js (100%) rename pyabc2/{ => abcjs}/widget/__init__.py (100%) rename pyabc2/{ => abcjs}/widget/index.css (100%) rename pyabc2/{ => abcjs}/widget/index.js (100%) diff --git a/pyabc2/html.py b/pyabc2/abcjs/html.py similarity index 100% rename from pyabc2/html.py rename to pyabc2/abcjs/html.py diff --git a/pyabc2/sheet/__init__.py b/pyabc2/abcjs/sheet/__init__.py similarity index 100% rename from pyabc2/sheet/__init__.py rename to pyabc2/abcjs/sheet/__init__.py diff --git a/pyabc2/sheet/cli.cjs b/pyabc2/abcjs/sheet/cli.cjs similarity index 100% rename from pyabc2/sheet/cli.cjs rename to pyabc2/abcjs/sheet/cli.cjs diff --git a/pyabc2/sheet/package.json b/pyabc2/abcjs/sheet/package.json similarity index 100% rename from pyabc2/sheet/package.json rename to pyabc2/abcjs/sheet/package.json diff --git a/pyabc2/sheet/render.js b/pyabc2/abcjs/sheet/render.js similarity index 100% rename from pyabc2/sheet/render.js rename to pyabc2/abcjs/sheet/render.js diff --git a/pyabc2/widget/__init__.py b/pyabc2/abcjs/widget/__init__.py similarity index 100% rename from pyabc2/widget/__init__.py rename to pyabc2/abcjs/widget/__init__.py diff --git a/pyabc2/widget/index.css b/pyabc2/abcjs/widget/index.css similarity index 100% rename from pyabc2/widget/index.css rename to pyabc2/abcjs/widget/index.css diff --git a/pyabc2/widget/index.js b/pyabc2/abcjs/widget/index.js similarity index 100% rename from pyabc2/widget/index.js rename to pyabc2/abcjs/widget/index.js From 0a005ad0acfe8fe086da1dfc7968bdeb2b4c3870 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 08:53:42 -0600 Subject: [PATCH 02/11] Give html a dir too in case add some template files or something later --- pyabc2/abcjs/{html.py => html/__init__.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pyabc2/abcjs/{html.py => html/__init__.py} (100%) diff --git a/pyabc2/abcjs/html.py b/pyabc2/abcjs/html/__init__.py similarity index 100% rename from pyabc2/abcjs/html.py rename to pyabc2/abcjs/html/__init__.py From 93b3c3a47b9e5b6a3c1f9295df391c30d6676a04 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 08:55:56 -0600 Subject: [PATCH 03/11] `sheet` -> `headless` --- pyabc2/abcjs/{sheet => headless}/__init__.py | 0 pyabc2/abcjs/{sheet => headless}/cli.cjs | 0 pyabc2/abcjs/{sheet => headless}/package.json | 0 pyabc2/abcjs/{sheet => headless}/render.js | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename pyabc2/abcjs/{sheet => headless}/__init__.py (100%) rename pyabc2/abcjs/{sheet => headless}/cli.cjs (100%) rename pyabc2/abcjs/{sheet => headless}/package.json (100%) rename pyabc2/abcjs/{sheet => headless}/render.js (100%) diff --git a/pyabc2/abcjs/sheet/__init__.py b/pyabc2/abcjs/headless/__init__.py similarity index 100% rename from pyabc2/abcjs/sheet/__init__.py rename to pyabc2/abcjs/headless/__init__.py diff --git a/pyabc2/abcjs/sheet/cli.cjs b/pyabc2/abcjs/headless/cli.cjs similarity index 100% rename from pyabc2/abcjs/sheet/cli.cjs rename to pyabc2/abcjs/headless/cli.cjs diff --git a/pyabc2/abcjs/sheet/package.json b/pyabc2/abcjs/headless/package.json similarity index 100% rename from pyabc2/abcjs/sheet/package.json rename to pyabc2/abcjs/headless/package.json diff --git a/pyabc2/abcjs/sheet/render.js b/pyabc2/abcjs/headless/render.js similarity index 100% rename from pyabc2/abcjs/sheet/render.js rename to pyabc2/abcjs/headless/render.js From 6374154c0dabbb93d57d8aa602fa7808ee52a5a0 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 09:16:41 -0600 Subject: [PATCH 04/11] Update docs/tests for abcjs module renames --- .gitignore | 2 +- docs/api.rst | 22 +++++++++++++++---- docs/examples/widget.ipynb | 13 ++++++----- pyabc2/abcjs/headless/__init__.py | 2 +- pyabc2/abcjs/html/__init__.py | 2 +- pyabc2/abcjs/widget/__init__.py | 7 ++++-- ...abcjs_nodejs.py => test_abcjs_headless.py} | 2 +- tests/test_html.py | 2 +- 8 files changed, 35 insertions(+), 17 deletions(-) rename tests/{test_abcjs_nodejs.py => test_abcjs_headless.py} (96%) diff --git a/.gitignore b/.gitignore index e677cc6..d6d2e73 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ poetry.lock venv*/ docs/api/ docs/examples/music*.svg -pyabc2/sheet/test.* +pyabc2/abcjs/headless/test.* # node node_modules diff --git a/docs/api.rst b/docs/api.rst index e88c43e..3b301a7 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -151,10 +151,13 @@ Functions: eskin.abctools_url_to_abc eskin.abc_to_abctools_url +abcjs tools +=========== + Widget -====== +------ -.. automodule:: pyabc2.widget +.. automodule:: pyabc2.abcjs.widget .. autosummary:: :toctree: api/ @@ -164,9 +167,9 @@ Widget Headless rendering -================== +------------------ -.. automodule:: pyabc2.sheet +.. automodule:: pyabc2.abcjs.headless .. autosummary:: :toctree: api/ @@ -174,3 +177,14 @@ Headless rendering svg svg_to build + +HTML page generation +-------------------- + +.. automodule:: pyabc2.abcjs.html + +.. autosummary:: + :toctree: api/ + + html + open_html diff --git a/docs/examples/widget.ipynb b/docs/examples/widget.ipynb index ecb771a..46dc2a0 100644 --- a/docs/examples/widget.ipynb +++ b/docs/examples/widget.ipynb @@ -18,7 +18,7 @@ "import ipywidgets as ipw\n", "from IPython.display import SVG\n", "\n", - "from pyabc2.widget import ABCJSWidget, interactive" + "from pyabc2.abcjs.widget import ABCJSWidget, interactive" ] }, { @@ -28,7 +28,8 @@ "source": [ "## The display widget\n", "\n", - "Used to {ref}`display ` {class}`~pyabc2.Tune`s in the notebook environment." + "Used to {ref}`display ` {class}`~pyabc2.Tune`s in the notebook environment.\n", + "{class}`~pyabc2.abcjs.widget.ABCJSWidget` supports many of the [abcjs render options](https://docs.abcjs.net/visual/render-abc-options.html)." ] }, { @@ -274,7 +275,7 @@ "source": [ "## Headless\n", "\n", - "We can also use abcjs in the background via Node.js using {mod}`pyabc2.sheet`." + "We can also use abcjs in the background via Node.js using {mod}`pyabc2.abcjs.headless`." ] }, { @@ -286,7 +287,7 @@ "source": [ "from IPython.display import SVG, Image\n", "\n", - "from pyabc2.sheet import svg, svg_to" + "from pyabc2.abcjs.headless import svg, svg_to" ] }, { @@ -306,8 +307,8 @@ "id": "26", "metadata": {}, "source": [ - "{func}`~pyabc2.sheet.build` is automatically called if needed.\n", - "But the next time we call {func}`~pyabc2.sheet.svg`, it will be ready to go:" + "{func}`~pyabc2.abcjs.headless.build` is automatically called if needed.\n", + "The next time we call {func}`~pyabc2.abcjs.headless.svg`, it should be faster." ] }, { diff --git a/pyabc2/abcjs/headless/__init__.py b/pyabc2/abcjs/headless/__init__.py index e01e475..40734db 100644 --- a/pyabc2/abcjs/headless/__init__.py +++ b/pyabc2/abcjs/headless/__init__.py @@ -64,7 +64,7 @@ def svg( **kwargs Additional abcjs options that haven't been explicitly defined here in the signature. - https://paulrosen.github.io/abcjs/visual/render-abc-options.html + https://docs.abcjs.net/visual/render-abc-options.html """ from nodejs_wheel import node diff --git a/pyabc2/abcjs/html/__init__.py b/pyabc2/abcjs/html/__init__.py index 0576d9f..6f2aa94 100644 --- a/pyabc2/abcjs/html/__init__.py +++ b/pyabc2/abcjs/html/__init__.py @@ -52,7 +52,7 @@ def html( **kwargs Additional abcjs options that haven't been explicitly defined here in the signature. - https://paulrosen.github.io/abcjs/visual/render-abc-options.html + https://docs.abcjs.net/visual/render-abc-options.html """ params = { **kwargs, diff --git a/pyabc2/abcjs/widget/__init__.py b/pyabc2/abcjs/widget/__init__.py index a953e11..9ddb999 100644 --- a/pyabc2/abcjs/widget/__init__.py +++ b/pyabc2/abcjs/widget/__init__.py @@ -19,10 +19,13 @@ class ABCJSWidget(anywidget.AnyWidget): """Display SVG sheet music rendered from ABC notation by abcjs. + Many of the `render options `__ + are supported, though some names have been modified to fit the Python style. + Examples -------- - >>> from pyabc2.widget import ABCJSWidget - >>> w = ABCJSWidget(abc="ABCD", staff_width=250) + >>> from pyabc2.abcjs.widget import ABCJSWidget + >>> w = ABCJSWidget(abc='ABCD', staff_width=250) """ _esm = HERE / "index.js" diff --git a/tests/test_abcjs_nodejs.py b/tests/test_abcjs_headless.py similarity index 96% rename from tests/test_abcjs_nodejs.py rename to tests/test_abcjs_headless.py index a789994..4ec45ce 100644 --- a/tests/test_abcjs_nodejs.py +++ b/tests/test_abcjs_headless.py @@ -1,6 +1,6 @@ import pytest -from pyabc2.sheet import svg, svg_to +from pyabc2.abcjs.headless import svg, svg_to HAVE_CAIROSVG = True try: diff --git a/tests/test_html.py b/tests/test_html.py index 1395f8a..70c8931 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -1,7 +1,7 @@ from pathlib import Path from tempfile import gettempdir -from pyabc2.html import html, open_html +from pyabc2.abcjs.html import html, open_html TMP = gettempdir() From c420896af7e7a18ac781174bb126246a3d675695 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 09:19:56 -0600 Subject: [PATCH 05/11] Add docs module targets --- docs/api.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index 3b301a7..4e2be3e 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -87,7 +87,7 @@ These methods/properties result from tune body parsing and repeat/ending expansi Tune sources ============ -.. currentmodule:: pyabc2.sources +.. module:: pyabc2.sources The :mod:`pyabc2.sources` namespace contains a few general tools. @@ -154,6 +154,8 @@ Functions: abcjs tools =========== +.. module:: pyabc2.abcjs + Widget ------ From 2d1ddd7da269946aac3703a25949fb5d48bb3c03 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 09:22:11 -0600 Subject: [PATCH 06/11] Fix Tune repr --- pyabc2/parse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyabc2/parse.py b/pyabc2/parse.py index 9105410..905e06f 100644 --- a/pyabc2/parse.py +++ b/pyabc2/parse.py @@ -354,7 +354,7 @@ def _repr_html_(self): # pragma: no cover try: from IPython.display import display - from .widget import ABCJSWidget + from .abcjs.widget import ABCJSWidget except ImportError: warnings.warn( "The 'widget' extra is required for HTML representation of tunes via abcjs." From 86c8f232d4da15bb69f9fbf90feea7a77388694b Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 09:25:16 -0600 Subject: [PATCH 07/11] Update the extra names accordingly --- .readthedocs.yaml | 4 ++-- pyabc2/abcjs/headless/__init__.py | 2 +- pyabc2/parse.py | 2 +- pyproject.toml | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 8b387a5..fb7a639 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,8 +12,8 @@ python: extra_requirements: - doc - sources - - widget - - sheet + - abcjs-widget + - abcjs-headless sphinx: configuration: docs/conf.py diff --git a/pyabc2/abcjs/headless/__init__.py b/pyabc2/abcjs/headless/__init__.py index 40734db..121c169 100644 --- a/pyabc2/abcjs/headless/__init__.py +++ b/pyabc2/abcjs/headless/__init__.py @@ -24,7 +24,7 @@ def build(): raise RuntimeError( "The 'nodejs-wheel-binaries' package is required " "to render sheet music in the background with abcjs via Node.js. " - "It is included with the pyabc2 'sheet' extra." + "It is included with the pyabc2 'abcjs-headless' extra." ) from e rc = npm(["install", "--prefix", HERE.as_posix()]) diff --git a/pyabc2/parse.py b/pyabc2/parse.py index 905e06f..2d69823 100644 --- a/pyabc2/parse.py +++ b/pyabc2/parse.py @@ -357,7 +357,7 @@ def _repr_html_(self): # pragma: no cover from .abcjs.widget import ABCJSWidget except ImportError: warnings.warn( - "The 'widget' extra is required for HTML representation of tunes via abcjs." + "The 'abcjs-widget' extra is required for HTML representation of tunes via abcjs." ) else: display(ABCJSWidget(abc=self.abc)) diff --git a/pyproject.toml b/pyproject.toml index 2e0e648..3fc9cf3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,12 +23,12 @@ sources = [ "pandas ==2.*", "requests ==2.*", ] -widget = [ +abcjs-widget = [ "anywidget", "ipywidgets", "traitlets", ] -sheet = [ +abcjs-headless = [ "cairosvg", "nodejs-wheel-binaries", ] From 62497ae49b4505d3210fc4201ccafadd17bead48 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sat, 17 Jan 2026 09:36:59 -0600 Subject: [PATCH 08/11] Specify tests' location in CI got: ImportError: cannot import name 'escape' from 'html' (/home/runner/work/PyABC2/PyABC2/pyabc2/abcjs/html/__init__.py) which is used in Norbeck, but also by anywidget deps, it looks like in the tb --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7dfe8c0..5d09d5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,7 @@ jobs: --doctest-modules --cov=pyabc2 --cov-report xml --cov-report term-missing -n auto + tests/ - name: Check type annotations run: | From a866ee1092cd235e17b0ad7b7f211cb72ff7cc99 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sun, 18 Jan 2026 22:23:37 -0600 Subject: [PATCH 09/11] Revert "Specify tests' location" This reverts commit 62497ae49b4505d3210fc4201ccafadd17bead48. --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d09d5a..7dfe8c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,6 @@ jobs: --doctest-modules --cov=pyabc2 --cov-report xml --cov-report term-missing -n auto - tests/ - name: Check type annotations run: | From 66e72060a36d982b66dcc70dc9ce1bac6638dda5 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sun, 18 Jan 2026 22:24:33 -0600 Subject: [PATCH 10/11] `html` -> `htmlgen` so as to not shadow a builtin --- docs/api.rst | 2 +- pyabc2/abcjs/{html => htmlgen}/__init__.py | 0 tests/test_html.py | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename pyabc2/abcjs/{html => htmlgen}/__init__.py (100%) diff --git a/docs/api.rst b/docs/api.rst index 4e2be3e..c40945c 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -183,7 +183,7 @@ Headless rendering HTML page generation -------------------- -.. automodule:: pyabc2.abcjs.html +.. automodule:: pyabc2.abcjs.htmlgen .. autosummary:: :toctree: api/ diff --git a/pyabc2/abcjs/html/__init__.py b/pyabc2/abcjs/htmlgen/__init__.py similarity index 100% rename from pyabc2/abcjs/html/__init__.py rename to pyabc2/abcjs/htmlgen/__init__.py diff --git a/tests/test_html.py b/tests/test_html.py index 70c8931..a087759 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -1,7 +1,7 @@ from pathlib import Path from tempfile import gettempdir -from pyabc2.abcjs.html import html, open_html +from pyabc2.abcjs.htmlgen import html, open_html TMP = gettempdir() From 0e68638adfe8900e4e816944754093f60bcaa117 Mon Sep 17 00:00:00 2001 From: zmoon Date: Sun, 18 Jan 2026 22:25:32 -0600 Subject: [PATCH 11/11] Get Tune class name for repr consistent with Pitch etc. --- pyabc2/parse.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyabc2/parse.py b/pyabc2/parse.py index 2d69823..2f06f32 100644 --- a/pyabc2/parse.py +++ b/pyabc2/parse.py @@ -336,9 +336,7 @@ def _extract_measures(self, tune_lines: list[str]) -> None: self.measures = measures def __repr__(self): - return ( - f"{self.__class__.__name__}(title={self.title!r}, key={self.key}, type={self.type!r})" - ) + return f"{type(self).__name__}(title={self.title!r}, key={self.key}, type={self.type!r})" def __eq__(self, other): if not isinstance(other, type(self)):