frescobaldi / python-ly

A Python package and commandline tool to manipulate LilyPond files
https://pypi.org/project/python-ly
132 stars 32 forks source link

Broken tests for py3.{9..11} #153

Open arkamar opened 1 year ago

arkamar commented 1 year ago

Test suit generealy does not work in latest version with following output (Only for the first test, the rest is pretty the same):

python3.11 -m pytest -vv -ra -l -Wdefault --color=yes -o console_output_style=count -p no:cov -p no:flake8 -p no:flakes -p no:pylint -p no:markdown -p no:sugar -p no:xvfb -p no:tavern
================================================= test session starts =================================================
platform linux -- Python 3.11.1, pytest-7.2.1, pluggy-1.0.0 -- /var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7-python3_11/install/usr/bin/python3.11
cachedir: .pytest_cache
rootdir: /var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7
collecting ... collected 16 items

tests/test_xml.py::test_glissando FAILED                                                                       [ 1/16]
tests/test_xml.py::test_tie FAILED                                                                             [ 2/16]
tests/test_xml.py::test_merge_voice FAILED                                                                     [ 3/16]
tests/test_xml.py::test_variable FAILED                                                                        [ 4/16]
tests/test_xml.py::test_dynamics FAILED                                                                        [ 5/16]
tests/test_xml.py::test_tuplet FAILED                                                                          [ 6/16]
tests/test_xml.py::test_merge_voice_slurs FAILED                                                               [ 7/16]
tests/test_xml.py::test_break FAILED                                                                           [ 8/16]
tests/test_xml.py::test_mark FAILED                                                                            [ 9/16]
tests/test_xml.py::test_partial FAILED                                                                         [10/16]
tests/test_xml.py::test_full_bar FAILED                                                                        [11/16]
tests/test_xml.py::test_stem_direction FAILED                                                                  [12/16]
tests/test_xml.py::test_church FAILED                                                                          [13/16]
tests/test_xml.py::test_markup FAILED                                                                          [14/16]
tests/test_xml.py::test_breathe FAILED                                                                         [15/16]
tests/test_xml.py::test_no_barcheck FAILED                                                                     [16/16]

====================================================== FAILURES =======================================================
___________________________________________________ test_glissando ____________________________________________________

    def test_glissando():
>       compare_output('glissando')

tests/test_xml.py:11: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_xml.py:97: in compare_output
    output = ly_to_xml(filebase + '.ly')
        filebase   = '/var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7/tests/test_xml_files/glissando'
        filename   = 'glissando'
tests/test_xml.py:79: in ly_to_xml
    xml.write(sio, "utf-8")
        filename   = '/var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7/tests/test_xml_files/glissando.ly'
        lyfile     = <_io.TextIOWrapper name='/var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7/tests/test_xml_files/glissando.ly' mode='r' encoding='UTF-8'>
        sio        = <_io.StringIO object at 0x7fa31554f760>
        writer     = <ly.musicxml.lymus2musxml.ParseSource object at 0x7fa315551410>
        xml        = <ly.musicxml.create_musicxml.MusicXML object at 0x7fa314dd5f10>
ly/musicxml/create_musicxml.py:703: in write
    write(file)
        doctype    = True
        encoding   = 'utf-8'
        file       = <_io.StringIO object at 0x7fa31554f760>
        self       = <ly.musicxml.create_musicxml.MusicXML object at 0x7fa314dd5f10>
        write      = <function MusicXML.write.<locals>.write at 0x7fa314f30680>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

f = <_io.StringIO object at 0x7fa31554f760>

    def write(f):
        if doctype:
>           f.write((xml_decl_txt + "\n").format(encoding=encoding).encode(encoding))
E           TypeError: string argument expected, got 'bytes'

doctype    = True
encoding   = 'utf-8'
f          = <_io.StringIO object at 0x7fa31554f760>
self       = <ly.musicxml.create_musicxml.MusicXML object at 0x7fa314dd5f10>

ly/musicxml/create_musicxml.py:697: TypeError

...

FAILED tests/test_xml.py::test_glissando - TypeError: string argument expected, got 'bytes'

This is because StringIO.getvalue() returs string. I changed it to BytesIO with following patch:

index 33ddfbb..38a8a45 100644
--- a/tests/test_xml.py
+++ b/tests/test_xml.py
@@ -75,9 +75,9 @@ def ly_to_xml(filename):
     with open(filename, 'r') as lyfile:
         writer.parse_text(lyfile.read())
     xml = writer.musicxml()
-    sio = io.StringIO()
-    xml.write(sio, "utf-8")
-    return sio.getvalue()
+    bio = io.BytesIO()
+    xml.write(bio, "UTF-8")
+    return bio.getvalue().decode("utf-8")

 def read_expected_xml(filename):
-- 
2.39.2

but tests fail with following errors:

python3.11 -m pytest -vv -ra -l -Wdefault --color=yes -o console_output_style=count -p no:cov -p no:flake8 -p no:flakes -p no:pylint -p no:markdown -p no:sugar -p no:xvfb -p no:tavern
================================================= test session starts =================================================
platform linux -- Python 3.11.1, pytest-7.2.1, pluggy-1.0.0 -- /var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7-python3_11/install/usr/bin/python3.11
cachedir: .pytest_cache
rootdir: /var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7
collecting ... collected 16 items

tests/test_xml.py::test_glissando FAILED                                                                       [ 1/16]
tests/test_xml.py::test_tie FAILED                                                                             [ 2/16]
tests/test_xml.py::test_merge_voice FAILED                                                                     [ 3/16]
tests/test_xml.py::test_variable FAILED                                                                        [ 4/16]
tests/test_xml.py::test_dynamics FAILED                                                                        [ 5/16]
tests/test_xml.py::test_tuplet FAILED                                                                          [ 6/16]
tests/test_xml.py::test_merge_voice_slurs FAILED                                                               [ 7/16]
tests/test_xml.py::test_break FAILED                                                                           [ 8/16]
tests/test_xml.py::test_mark FAILED                                                                            [ 9/16]
tests/test_xml.py::test_partial FAILED                                                                         [10/16]
tests/test_xml.py::test_full_bar FAILED                                                                        [11/16]
tests/test_xml.py::test_stem_direction FAILED                                                                  [12/16]
tests/test_xml.py::test_church FAILED                                                                          [13/16]
tests/test_xml.py::test_markup FAILED                                                                          [14/16]
tests/test_xml.py::test_breathe FAILED                                                                         [15/16]
tests/test_xml.py::test_no_barcheck FAILED                                                                     [16/16]

====================================================== FAILURES =======================================================
___________________________________________________ test_glissando ____________________________________________________

    def test_glissando():
>       compare_output('glissando')

tests/test_xml.py:11: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_xml.py:100: in compare_output
    assert_multi_line_equal(expected_output, output)
        expected_output = ('<?xml version="1.0" encoding="utf-8"?>\n'
 '<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 '
 'Partwise//EN"\n'
 '                                '
 '"http://www.musicxml.org/dtds/partwise.dtd">\n'
 '<score-partwise version="3.0">\n'
 '  <identification>\n'
 '    <encoding>\n'
 '      <software>python-ly 0.9.4</software>\n'
 '      <encoding-date>2023-02-21</encoding-date>\n'
 '    </encoding>\n'
 '  </identification>\n'
 '  <part-list>\n'
 '    <score-part id="P1">\n'
 '      <part-name />\n'
 '    </score-part>\n'
 '  </part-list>\n'
 '  <part id="P1">\n'
 '    <measure number="1">\n'
 '      <attributes>\n'
 '        <divisions>1</divisions>\n'
 '        <time symbol="common">\n'
 '          <beats>4</beats>\n'
 '          <beat-type>4</beat-type>\n'
 '        </time>\n'
 '        <clef>\n'
 '          <sign>G</sign>\n'
 '          <line>2</line>\n'
 '        </clef>\n'
 '      </attributes>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>C</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="start" />\n'
 '        </notations>\n'
 '      </note>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>E</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="stop" />\n'
 '        </notations>\n'
 '      </note>\n'
 '    </measure>\n'
 '  </part>\n'
 '</score-partwise>\n')
        filebase   = '/var/tmp/portage/dev-python/python-ly-0.9.7/work/python-ly-0.9.7/tests/test_xml_files/glissando'
        filename   = 'glissando'
        output     = ('<?xml version="1.0" encoding="UTF-8"?>\n'
 '<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 '
 'Partwise//EN"\n'
 '                                '
 '"http://www.musicxml.org/dtds/partwise.dtd">\n'
 '<score-partwise version="3.0">\n'
 '  <identification>\n'
 '    <encoding>\n'
 '      <software>python-ly 0.9.7</software>\n'
 '      <encoding-date>2023-02-21</encoding-date>\n'
 '    </encoding>\n'
 '  </identification>\n'
 '  <part-list>\n'
 '    <score-part id="P1">\n'
 '      <part-name />\n'
 '    </score-part>\n'
 '  </part-list>\n'
 '  <part id="P1">\n'
 '    <measure number="1">\n'
 '      <attributes>\n'
 '        <divisions>1</divisions>\n'
 '        <time symbol="common">\n'
 '          <beats>4</beats>\n'
 '          <beat-type>4</beat-type>\n'
 '        </time>\n'
 '        <clef>\n'
 '          <sign>G</sign>\n'
 '          <line>2</line>\n'
 '        </clef>\n'
 '      </attributes>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>C</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="start" />\n'
 '        </notations>\n'
 '      </note>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>E</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="stop" />\n'
 '        </notations>\n'
 '      </note>\n'
 '    </measure>\n'
 '  </part>\n'
 '</score-partwise>\n')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

first = '<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN"..."solid" number="1" type="stop" />\n        </notations>\n      </note>\n    </measure>\n  </part>\n</score-partwise>\n'
second = '<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN"..."solid" number="1" type="stop" />\n        </notations>\n      </note>\n    </measure>\n  </part>\n</score-partwise>\n'
msg = None

    def assert_multi_line_equal(first, second, msg=None):
        """Assert that two multi-line strings are equal.

        If they aren't, show a nice diff.
        """
        assert isinstance(first, str), 'First argument is not a string'
        assert isinstance(second, str), 'Second argument is not a string'

        if first != second:
            message = ''.join(difflib.ndiff(first.splitlines(True),
                                            second.splitlines(True)))
            if msg:
                message += " : " + msg
>           assert False, "Multi-line strings are unequal:\n" + message
E           AssertionError: Multi-line strings are unequal:
E             - <?xml version="1.0" encoding="utf-8"?>
E             ?                               ^^^
E             + <?xml version="1.0" encoding="UTF-8"?>
E             ?                               ^^^
E               <!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN"
E                                               "http://www.musicxml.org/dtds/partwise.dtd">
E               <score-partwise version="3.0">
E                 <identification>
E                   <encoding>
E             -       <software>python-ly 0.9.4</software>
E             ?                               ^
E             +       <software>python-ly 0.9.7</software>
E             ?                               ^
E                     <encoding-date>2023-02-21</encoding-date>
E                   </encoding>
E                 </identification>
E                 <part-list>
E                   <score-part id="P1">
E                     <part-name />
E                   </score-part>
E                 </part-list>
E                 <part id="P1">
E                   <measure number="1">
E                     <attributes>
E                       <divisions>1</divisions>
E                       <time symbol="common">
E                         <beats>4</beats>
E                         <beat-type>4</beat-type>
E                       </time>
E                       <clef>
E                         <sign>G</sign>
E                         <line>2</line>
E                       </clef>
E                     </attributes>
E                     <note>
E                       <pitch>
E                         <step>C</step>
E                         <octave>3</octave>
E                       </pitch>
E                       <duration>1</duration>
E                       <voice>1</voice>
E                       <type>quarter</type>
E                       <notations>
E                         <glissando line-type="solid" number="1" type="start" />
E                       </notations>
E                     </note>
E                     <note>
E                       <pitch>
E                         <step>E</step>
E                         <octave>3</octave>
E                       </pitch>
E                       <duration>1</duration>
E                       <voice>1</voice>
E                       <type>quarter</type>
E                       <notations>
E                         <glissando line-type="solid" number="1" type="stop" />
E                       </notations>
E                     </note>
E                   </measure>
E                 </part>
E               </score-partwise>
E             
E           assert False

first      = ('<?xml version="1.0" encoding="utf-8"?>\n'
 '<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 '
 'Partwise//EN"\n'
 '                                '
 '"http://www.musicxml.org/dtds/partwise.dtd">\n'
 '<score-partwise version="3.0">\n'
 '  <identification>\n'
 '    <encoding>\n'
 '      <software>python-ly 0.9.4</software>\n'
 '      <encoding-date>2023-02-21</encoding-date>\n'
 '    </encoding>\n'
 '  </identification>\n'
 '  <part-list>\n'
 '    <score-part id="P1">\n'
 '      <part-name />\n'
 '    </score-part>\n'
 '  </part-list>\n'
 '  <part id="P1">\n'
 '    <measure number="1">\n'
 '      <attributes>\n'
 '        <divisions>1</divisions>\n'
 '        <time symbol="common">\n'
 '          <beats>4</beats>\n'
 '          <beat-type>4</beat-type>\n'
 '        </time>\n'
 '        <clef>\n'
 '          <sign>G</sign>\n'
 '          <line>2</line>\n'
 '        </clef>\n'
 '      </attributes>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>C</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="start" />\n'
 '        </notations>\n'
 '      </note>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>E</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="stop" />\n'
 '        </notations>\n'
 '      </note>\n'
 '    </measure>\n'
 '  </part>\n'
 '</score-partwise>\n')
message    = ('- <?xml version="1.0" encoding="utf-8"?>\n'
 '?                               ^^^\n'
 '+ <?xml version="1.0" encoding="UTF-8"?>\n'
 '?                               ^^^\n'
 '  <!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 '
 'Partwise//EN"\n'
 '                                  '
 '"http://www.musicxml.org/dtds/partwise.dtd">\n'
 '  <score-partwise version="3.0">\n'
 '    <identification>\n'
 '      <encoding>\n'
 '-       <software>python-ly 0.9.4</software>\n'
 '?                               ^\n'
 '+       <software>python-ly 0.9.7</software>\n'
 '?                               ^\n'
 '        <encoding-date>2023-02-21</encoding-date>\n'
 '      </encoding>\n'
 '    </identification>\n'
 '    <part-list>\n'
 '      <score-part id="P1">\n'
 '        <part-name />\n'
 '      </score-part>\n'
 '    </part-list>\n'
 '    <part id="P1">\n'
 '      <measure number="1">\n'
 '        <attributes>\n'
 '          <divisions>1</divisions>\n'
 '          <time symbol="common">\n'
 '            <beats>4</beats>\n'
 '            <beat-type>4</beat-type>\n'
 '          </time>\n'
 '          <clef>\n'
 '            <sign>G</sign>\n'
 '            <line>2</line>\n'
 '          </clef>\n'
 '        </attributes>\n'
 '        <note>\n'
 '          <pitch>\n'
 '            <step>C</step>\n'
 '            <octave>3</octave>\n'
 '          </pitch>\n'
 '          <duration>1</duration>\n'
 '          <voice>1</voice>\n'
 '          <type>quarter</type>\n'
 '          <notations>\n'
 '            <glissando line-type="solid" number="1" type="start" />\n'
 '          </notations>\n'
 '        </note>\n'
 '        <note>\n'
 '          <pitch>\n'
 '            <step>E</step>\n'
 '            <octave>3</octave>\n'
 '          </pitch>\n'
 '          <duration>1</duration>\n'
 '          <voice>1</voice>\n'
 '          <type>quarter</type>\n'
 '          <notations>\n'
 '            <glissando line-type="solid" number="1" type="stop" />\n'
 '          </notations>\n'
 '        </note>\n'
 '      </measure>\n'
 '    </part>\n'
 '  </score-partwise>\n')
msg        = None
second     = ('<?xml version="1.0" encoding="UTF-8"?>\n'
 '<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 '
 'Partwise//EN"\n'
 '                                '
 '"http://www.musicxml.org/dtds/partwise.dtd">\n'
 '<score-partwise version="3.0">\n'
 '  <identification>\n'
 '    <encoding>\n'
 '      <software>python-ly 0.9.7</software>\n'
 '      <encoding-date>2023-02-21</encoding-date>\n'
 '    </encoding>\n'
 '  </identification>\n'
 '  <part-list>\n'
 '    <score-part id="P1">\n'
 '      <part-name />\n'
 '    </score-part>\n'
 '  </part-list>\n'
 '  <part id="P1">\n'
 '    <measure number="1">\n'
 '      <attributes>\n'
 '        <divisions>1</divisions>\n'
 '        <time symbol="common">\n'
 '          <beats>4</beats>\n'
 '          <beat-type>4</beat-type>\n'
 '        </time>\n'
 '        <clef>\n'
 '          <sign>G</sign>\n'
 '          <line>2</line>\n'
 '        </clef>\n'
 '      </attributes>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>C</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="start" />\n'
 '        </notations>\n'
 '      </note>\n'
 '      <note>\n'
 '        <pitch>\n'
 '          <step>E</step>\n'
 '          <octave>3</octave>\n'
 '        </pitch>\n'
 '        <duration>1</duration>\n'
 '        <voice>1</voice>\n'
 '        <type>quarter</type>\n'
 '        <notations>\n'
 '          <glissando line-type="solid" number="1" type="stop" />\n'
 '        </notations>\n'
 '      </note>\n'
 '    </measure>\n'
 '  </part>\n'
 '</score-partwise>\n')

tests/test_xml.py:129: AssertionError

...

=============================================== short test summary info ===============================================
FAILED tests/test_xml.py::test_glissando - AssertionError: Multi-line strings are unequal:

I have tried to fix this with some substitutions simalar to how date is handled but I failed to make it work. Here are my latest substitutions I have made in case anyone will try to fix it:

diff --git a/tests/test_xml.py b/tests/test_xml.py
index 38a8a45..1b9b740 100644
--- a/tests/test_xml.py
+++ b/tests/test_xml.py
@@ -2,9 +2,11 @@
 import datetime
 import difflib
 import ly.musicxml
+import ly.pkginfo
 from lxml import etree
 import os
 import io
+import re

 def test_glissando():
@@ -85,7 +87,9 @@ def read_expected_xml(filename):
     with open(filename, 'r') as xmlfile:
         output = xmlfile.read()
     # Replace date in XML file with today's date
-    output = output.replace("2016-03-28", str(datetime.date.today()))
+    output = output.replace("utf-8", "UTF-8")
+    output = re.sub("python-ly \d.\d.\d", ly.pkginfo.name + " " + ly.pkginfo.version, output)
+    output = re.sub(r'201\d-\d{2}-\d{2}', str(datetime.date.today()), output)
     return output

-- 
jeanas commented 1 year ago

I wasn't there, but I'm guessing these tests were a failed experiment? No way they are going to work if the expected output includes the encoding-date...