Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load Scores from URL #404

Merged
merged 18 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
44 changes: 36 additions & 8 deletions partitura/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"""
from typing import Union
import os

import urllib.request
from urllib.parse import urlparse
import tempfile
from .importmusicxml import load_musicxml
from .importmidi import load_score_midi, load_performance_midi
from .musescore import load_via_musescore
Expand All @@ -32,6 +34,14 @@ class NotSupportedFormatError(Exception):
pass


def is_url(input):
try:
result = urlparse(input)
return all([result.scheme, result.netloc])
except ValueError:
return False


@deprecated_alias(score_fn="filename")
@deprecated_parameter("ensure_list")
def load_score(filename: PathLike, force_note_ids="keep") -> Score:
Expand All @@ -57,11 +67,29 @@ def load_score(filename: PathLike, force_note_ids="keep") -> Score:
scr: :class:`partitura.score.Score`
A score instance.
"""
if is_url(filename):
url = filename
# Send a GET request to the URL
with urllib.request.urlopen(url) as response:
data = response.read()

# Extract the file extension from the URL
extension = os.path.splitext(url)[-1]

# Create a temporary file
temp_file = tempfile.NamedTemporaryFile(suffix=extension, delete=True)

# Write the content to the temporary file
with open(temp_file.name, 'wb') as f:
f.write(data)

filename = temp_file.name
else:
extension = os.path.splitext(filename)[-1].lower()

extension = os.path.splitext(filename)[-1].lower()
if extension in (".mxl", ".xml", ".musicxml"):
# Load MusicXML
return load_musicxml(
score = load_musicxml(
filename=filename,
force_note_ids=force_note_ids,
)
Expand All @@ -71,15 +99,15 @@ def load_score(filename: PathLike, force_note_ids="keep") -> Score:
assign_note_ids = False
else:
assign_note_ids = True
return load_score_midi(
score = load_score_midi(
filename=filename,
assign_note_ids=assign_note_ids,
)
elif extension in [".mei"]:
# Load MEI
return load_mei(filename=filename)
score = load_mei(filename=filename)
elif extension in [".kern", ".krn"]:
return load_kern(
score = load_kern(
filename=filename,
force_note_ids=force_note_ids,
)
Expand Down Expand Up @@ -107,7 +135,7 @@ def load_score(filename: PathLike, force_note_ids="keep") -> Score:
".gp",
]:
# Load MuseScore
return load_via_musescore(
score = load_via_musescore(
filename=filename,
force_note_ids=force_note_ids,
)
Expand All @@ -117,11 +145,11 @@ def load_score(filename: PathLike, force_note_ids="keep") -> Score:
filename=filename,
create_score=True,
)
return score
else:
raise NotSupportedFormatError(
f"{extension} file extension is not supported. If this should be supported, consider editing partitura/io/__init__.py file"
)
return score


def load_score_as_part(filename: PathLike) -> Part:
Expand Down
4 changes: 2 additions & 2 deletions partitura/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -6037,8 +6037,8 @@ def process_local_key(loc_k_text, glob_k_text, return_step_alter=False):
"iii": Interval(3, "m"),
"iv": Interval(4, "P"),
"v": Interval(5, "P"),
"vi": Interval(6, "m"),
"vii": Interval(7, "m"),
"vi": Interval(6, "M"),
"vii": Interval(7, "M"),
"viio": Interval(7, "M"),
"N": Interval(2, "m"),
"iio": Interval(2, "M"),
Expand Down
26 changes: 26 additions & 0 deletions tests/test_urlload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import unittest
from partitura import load_score
import numpy as np


class TestImport(unittest.TestCase):
def test_load_kern(self):
score = load_score("https://raw.githubusercontent.com/CPJKU/partitura/refs/heads/main/partitura/assets/score_example.krn")
note_array = score.note_array()
self.assertTrue(np.all(note_array["pitch"] == [69, 72, 76]))

def test_load_mei(self):
score = load_score("https://raw.githubusercontent.com/CPJKU/partitura/refs/heads/main/partitura/assets/score_example.mei")
note_array = score.note_array()
self.assertTrue(np.all(note_array["pitch"] == [69, 72, 76]))

def test_load_midi(self):
score = load_score("https://raw.githubusercontent.com/CPJKU/partitura/refs/heads/main/partitura/assets/score_example.mid")
note_array = score.note_array()
self.assertTrue(np.all(note_array["pitch"] == [69, 72, 76]))

def test_load_musicxml(self):
score = load_score("https://raw.githubusercontent.com/CPJKU/partitura/refs/heads/main/partitura/assets/score_example.musicxml")
note_array = score.note_array()
self.assertTrue(np.all(note_array["pitch"] == [69, 72, 76]))

Loading