From 3aad0b1b1ba6dd4b88b4905e78bc80da83ee23b8 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Sat, 3 Dec 2016 04:03:47 +0100 Subject: [PATCH] python/lib/aubio/midiconv.py: improve unicode handling, skip UnicodeEncodeError on python 2.x --- python/lib/aubio/midiconv.py | 12 ++++++----- python/tests/test_note2midi.py | 48 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/python/lib/aubio/midiconv.py b/python/lib/aubio/midiconv.py index efe7ec09..c79523f5 100644 --- a/python/lib/aubio/midiconv.py +++ b/python/lib/aubio/midiconv.py @@ -15,11 +15,13 @@ else: def note2midi(note): " convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] " _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} - _valid_modifiers = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2, - u'\U0001D12A': +2, - 'b': -1, u'♭': -1, u'\ufffd': -2, - u'\U0001D12B': -2, - } + _valid_modifiers = { + u'𝄫': -2, # double flat + u'♭': -1, 'b': -1, '\u266d': -1, # simple flat + u'♮': 0, '\u266e': 0, None: 0, # natural + '#': +1, u'♯': +1, '\u266f': +1, # sharp + u'𝄪': +2, # double sharp + } _valid_octaves = range(-1, 10) if not isinstance(note, str_instances): raise TypeError("a string is required, got %s (%s)" % (note, str(type(note)))) diff --git a/python/tests/test_note2midi.py b/python/tests/test_note2midi.py index 7524a519..261b025b 100755 --- a/python/tests/test_note2midi.py +++ b/python/tests/test_note2midi.py @@ -14,21 +14,36 @@ list_of_known_notes = ( ( 'C3', 48 ), ( 'B3', 59 ), ( 'B#3', 60 ), - ( 'C\u266f4', 61 ), - ( 'C\U0001D12A4', 62 ), - ( 'E\U0001D12B4', 62 ), + ( 'C♯4', 61 ), ( 'A4', 69 ), ( 'A#4', 70 ), + ( 'A♯4', 70 ), + ( 'A\u266f4', 70 ), ( 'Bb4', 70 ), ( 'B♭4', 70 ), + ( 'B\u266d4', 70 ), ( 'G8', 115 ), ( 'G♯8', 116 ), ( 'G9', 127 ), - ( 'G\udd2a2', 45 ), - ( 'B\ufffd2', 45 ), ( 'A♮2', 45 ), ) +list_of_known_notes_with_unicode_issues = ( + ('C𝄪4', 62 ), + ('E𝄫4', 62 ), + ) + +list_of_unknown_notes = ( + ( 'G\udd2a2' ), + ( 'B\ufffd2' ), + ( 'B\u266e\u266e2' ), + ( 'B\u266f\u266d3' ), + ( 'B33' ), + ( 'C.3' ), + ( 'A' ), + ( '2' ), + ) + class note2midi_good_values(unittest.TestCase): @params(*list_of_known_notes) @@ -36,6 +51,21 @@ class note2midi_good_values(unittest.TestCase): " known values are correctly converted " self.assertEqual ( note2midi(note), midi ) + @params(*list_of_known_notes_with_unicode_issues) + def test_note2midi_known_values_with_unicode_issues(self, note, midi): + " known values are correctly converted, unless decoding is expected to fail" + try: + self.assertEqual ( note2midi(note), midi ) + except UnicodeEncodeError as e: + import sys + strfmt = "len(u'\\U0001D12A') != 1, excpected decoding failure | {:s} | {:s} {:s}" + strres = strfmt.format(e, sys.platform, sys.version) + # happens with: darwin 2.7.10, windows 2.7.12 + if len('\U0001D12A') != 1 and sys.version[0] == '2': + self.skipTest(strres + " | upgrade to Python 3 to fix") + else: + raise + class note2midi_wrong_values(unittest.TestCase): def test_note2midi_missing_octave(self): @@ -70,6 +100,14 @@ class note2midi_wrong_values(unittest.TestCase): " fails when passed a non-string value " self.assertRaises(TypeError, note2midi, 123) + def test_note2midi_wrong_data_too_long(self): + " fails when passed a note with a note name longer than expected" + self.assertRaises(ValueError, note2midi, 'CB+-3') + + @params(*list_of_unknown_notes) + def test_note2midi_unknown_values(self, note): + " unknown values throw out an error " + self.assertRaises(ValueError, note2midi, note) class freq2note_simple_test(unittest.TestCase): -- 2.11.0