Showing the changes to python (2 of 2 files). Show all
Unified · Split
| @@ -15,11 +15,13 @@ else: · 14 unmodified lines | |||
| 15 | def note2midi(note): | 15 | def note2midi(note): |
| 16 | " convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] " | 16 | " convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] " |
| 17 | _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} | 17 | _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} |
| 18 | _valid_modifiers = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2, | 18 | _valid_modifiers = { |
| 19 | u'\U0001D12A': +2, | 19 | u'𝄫': -2, # double flat |
| 20 | 'b': -1, u'♭': -1, u'\ufffd': -2, | 20 | u'♭': -1, 'b': -1, '\u266d': -1, # simple flat |
| 21 | u'\U0001D12B': -2, | 21 | u'♮': 0, '\u266e': 0, None: 0, # natural |
| 22 | } | 22 | '#': +1, u'♯': +1, '\u266f': +1, # sharp |
| 23 | u'𝄪': +2, # double sharp | ||
| 24 | } | ||
| 23 | _valid_octaves = range(-1, 10) | 25 | _valid_octaves = range(-1, 10) |
| 24 | if not isinstance(note, str_instances): | 26 | if not isinstance(note, str_instances): |
| 25 | raise TypeError("a string is required, got %s (%s)" % (note, str(type(note)))) | 27 | raise TypeError("a string is required, got %s (%s)" % (note, str(type(note)))) |
| @@ -14,21 +14,36 @@ list_of_known_notes = ( · 13 unmodified lines | |||
| 14 | ( 'C3', 48 ), | 14 | ( 'C3', 48 ), |
| 15 | ( 'B3', 59 ), | 15 | ( 'B3', 59 ), |
| 16 | ( 'B#3', 60 ), | 16 | ( 'B#3', 60 ), |
| 17 | ( 'C\u266f4', 61 ), | 17 | ( 'C♯4', 61 ), |
| 18 | ( 'C\U0001D12A4', 62 ), | ||
| 19 | ( 'E\U0001D12B4', 62 ), | ||
| 20 | ( 'A4', 69 ), | 18 | ( 'A4', 69 ), |
| 21 | ( 'A#4', 70 ), | 19 | ( 'A#4', 70 ), |
| 20 | ( 'A♯4', 70 ), | ||
| 21 | ( 'A\u266f4', 70 ), | ||
| 22 | ( 'Bb4', 70 ), | 22 | ( 'Bb4', 70 ), |
| 23 | ( 'B♭4', 70 ), | 23 | ( 'B♭4', 70 ), |
| 24 | ( 'B\u266d4', 70 ), | ||
| 24 | ( 'G8', 115 ), | 25 | ( 'G8', 115 ), |
| 25 | ( 'G♯8', 116 ), | 26 | ( 'G♯8', 116 ), |
| 26 | ( 'G9', 127 ), | 27 | ( 'G9', 127 ), |
| 27 | ( 'G\udd2a2', 45 ), | ||
| 28 | ( 'B\ufffd2', 45 ), | ||
| 29 | ( 'A♮2', 45 ), | 28 | ( 'A♮2', 45 ), |
| 30 | ) | 29 | ) |
| 31 | 30 | ||
| 31 | list_of_known_notes_with_unicode_issues = ( | ||
| 32 | ('C𝄪4', 62 ), | ||
| 33 | ('E𝄫4', 62 ), | ||
| 34 | ) | ||
| 35 | |||
| 36 | list_of_unknown_notes = ( | ||
| 37 | ( 'G\udd2a2' ), | ||
| 38 | ( 'B\ufffd2' ), | ||
| 39 | ( 'B\u266e\u266e2' ), | ||
| 40 | ( 'B\u266f\u266d3' ), | ||
| 41 | ( 'B33' ), | ||
| 42 | ( 'C.3' ), | ||
| 43 | ( 'A' ), | ||
| 44 | ( '2' ), | ||
| 45 | ) | ||
| 46 | |||
| 32 | class note2midi_good_values(unittest.TestCase): | 47 | class note2midi_good_values(unittest.TestCase): |
| 33 | 48 | ||
| 34 | @params(*list_of_known_notes) | 49 | @params(*list_of_known_notes) |
| @@ -36,6 +51,21 @@ class note2midi_good_values(unittest.TestCase): · 1 unmodified line | |||
| 36 | " known values are correctly converted " | 51 | " known values are correctly converted " |
| 37 | self.assertEqual ( note2midi(note), midi ) | 52 | self.assertEqual ( note2midi(note), midi ) |
| 38 | 53 | ||
| 54 | @params(*list_of_known_notes_with_unicode_issues) | ||
| 55 | def test_note2midi_known_values_with_unicode_issues(self, note, midi): | ||
| 56 | " known values are correctly converted, unless decoding is expected to fail" | ||
| 57 | try: | ||
| 58 | self.assertEqual ( note2midi(note), midi ) | ||
| 59 | except UnicodeEncodeError as e: | ||
| 60 | import sys | ||
| 61 | strfmt = "len(u'\\U0001D12A') != 1, excpected decoding failure | {:s} | {:s} {:s}" | ||
| 62 | strres = strfmt.format(e, sys.platform, sys.version) | ||
| 63 | # happens with: darwin 2.7.10, windows 2.7.12 | ||
| 64 | if len('\U0001D12A') != 1 and sys.version[0] == '2': | ||
| 65 | self.skipTest(strres + " | upgrade to Python 3 to fix") | ||
| 66 | else: | ||
| 67 | raise | ||
| 68 | |||
| 39 | class note2midi_wrong_values(unittest.TestCase): | 69 | class note2midi_wrong_values(unittest.TestCase): |
| 40 | 70 | ||
| 41 | def test_note2midi_missing_octave(self): | 71 | def test_note2midi_missing_octave(self): |
| @@ -70,6 +100,14 @@ class note2midi_wrong_values(unittest.TestCase): · 28 unmodified lines | |||
| 70 | " fails when passed a non-string value " | 100 | " fails when passed a non-string value " |
| 71 | self.assertRaises(TypeError, note2midi, 123) | 101 | self.assertRaises(TypeError, note2midi, 123) |
| 72 | 102 | ||
| 103 | def test_note2midi_wrong_data_too_long(self): | ||
| 104 | " fails when passed a note with a note name longer than expected" | ||
| 105 | self.assertRaises(ValueError, note2midi, 'CB+-3') | ||
| 106 | |||
| 107 | @params(*list_of_unknown_notes) | ||
| 108 | def test_note2midi_unknown_values(self, note): | ||
| 109 | " unknown values throw out an error " | ||
| 110 | self.assertRaises(ValueError, note2midi, note) | ||
| 73 | 111 | ||
| 74 | class freq2note_simple_test(unittest.TestCase): | 112 | class freq2note_simple_test(unittest.TestCase): |
| 75 | 113 | ||