Repository: cuthbertLab/music21
Pull request #1330 (2022-06-29 15:16:14)

Fix midmeasure clef export regression involving voices
Fix a regression in #1261 with midmeasure clef changes outside voices.

From Amy Beach corpus example:

**Before**
<img width="587" alt="Screen Shot 2022-06-29 at 11 15 24 AM" src="https://user-images.githubusercontent.com/38668450/176472831-798370e6-dc14-4bf6-a981-faa6ecc4c358.png">

**After**
<img width="573" alt="Screen Shot 2022-06-29 at 11 14 58 AM" src="https://user-images.githubusercontent.com/38668450/176472889-79362d4a-cb0e-4d0b-841a-60035e957cfa.png">


coveralls: 
[![Coverage Status](https://coveralls.io/builds/50468865/badge)](https://coveralls.io/builds/50468865)

Coverage increased (+0.001%) to 93.055% when pulling **f5ec2f9815cd5219de2b4914e01c2ec0e2c03ec1 on jacobtylerwalls:clef-regression** into **c46bde460b2f868c2b55261b84d8094df053f980 on cuthbertLab:master**.


Patch:
diff --git a/music21/musicxml/m21ToXml.py b/music21/musicxml/m21ToXml.py
index 30f47c60d..108963873 100644
--- a/music21/musicxml/m21ToXml.py
+++ b/music21/musicxml/m21ToXml.py
@@ -3113,8 +3113,8 @@ class MeasureExporter(XMLExporterBase):
             amountToMoveForward = int(round(divisions * (groupOffset
                                                              - self.offsetInMeasure)))
             if amountToMoveForward > 0 and any(
-                    isinstance(obj, note.GeneralNote) for obj in objGroup):
-                # gap in stream between GeneralNote objects: create <forward>
+                    isinstance(obj, (note.GeneralNote, clef.Clef)) for obj in objGroup):
+                # gap in stream between GeneralNote/Clef objects: create <forward>
                 mxForward = Element('forward')
                 mxDuration = SubElement(mxForward, 'duration')
                 mxDuration.text = str(amountToMoveForward)
diff --git a/music21/tinyNotation.py b/music21/tinyNotation.py
index 49fedc124..954643032 100644
--- a/music21/tinyNotation.py
+++ b/music21/tinyNotation.py
@@ -229,7 +229,6 @@ for details on how to do that.
 import collections
 import copy
 import re
-import sre_parse
 import typing
 import unittest
 
@@ -1124,7 +1123,7 @@ class Converter:
         for rePre, classCall in self.tokenMap:
             try:
                 self._tokenMapRe.append((re.compile(rePre), classCall))
-            except sre_parse.error as e:
+            except re.error as e:
                 raise TinyNotationException(
                     f'Error in compiling token, {rePre}: {e}'
                 ) from e


Test patch:
diff --git a/music21/musicxml/testPrimitive.py b/music21/musicxml/testPrimitive.py
index 6f7c6eac0..5d7f2a3fa 100644
--- a/music21/musicxml/testPrimitive.py
+++ b/music21/musicxml/testPrimitive.py
@@ -18236,6 +18236,30 @@ class Test(unittest.TestCase):
         self.assertEqual([c.classes for c in new_clefs],
                          [c.classes for c in orig_clefs])
 
+    def testMidMeasureClefs3(self):
+        '''
+        Test midmeasure clef changes outside voices
+        '''
+        from music21 import clef
+        from music21 import note
+        from music21 import musicxml
+        from music21 import stream
+
+        v1 = stream.Voice()
+        v2 = stream.Voice()
+        quarter = note.Note()
+        v1.repeatAppend(quarter, 4)
+        v2.repeatAppend(quarter, 4)
+        m = stream.Measure([v1, v2])
+        m.insert(1.0, clef.BassClef())
+        p = stream.Part(m)
+        p.makeNotation(inPlace=True)
+
+        tree = musicxml.test_m21ToXml.Test().getET(p)
+        self.assertEqual(len(tree.findall('.//clef')), 1)
+        # One backup from the clef back to voice 1, then another back to voice 2
+        self.assertEqual(len(tree.findall('.//backup')), 2)
+
 # ------------------------------------------------------------------------------