Browse Source

Merge pull request #160 from patacrep/crlf_test

Support source file with CRLF line endings
pull/168/head
oliverpool 9 years ago
parent
commit
a4a5501971
  1. 8
      patacrep/songs/chordpro/lexer.py
  2. 6
      test/test_chordpro/metadata.tex
  3. 43
      test/test_chordpro/newline.crlf.html
  4. 41
      test/test_chordpro/newline.crlf.sgc
  5. 2
      test/test_chordpro/newline.crlf.source
  6. 61
      test/test_chordpro/newline.crlf.tex
  7. 95
      test/test_chordpro/test_parser.py

8
patacrep/songs/chordpro/lexer.py

@ -80,8 +80,8 @@ class ChordProLexer:
r'[ \t]+'
return token
t_tablature_TEXT = r'[^\n]+'
t_tablature_ENDOFLINE = r'\n'
t_tablature_TEXT = r'[^\n\r]+'
t_tablature_ENDOFLINE = r'\r?\n'
def __init__(self, *, filename=None):
self.__class__.lexer = lex.lex(module=self)
@ -90,7 +90,7 @@ class ChordProLexer:
# Define a rule so we can track line numbers
@staticmethod
def t_ENDOFLINE(token):
r'[\n\r]'
r'\r?\n'
token.lexer.lineno += 1
return token
@ -101,7 +101,7 @@ class ChordProLexer:
@staticmethod
def t_WORD(token):
r'[^{}\n\][\t ]+'
r'[^{}\r\n\][\t ]+'
return token
def t_LBRACKET(self, __token):

6
test/test_chordpro/metadata.tex

@ -11,7 +11,7 @@ Subtitle5}[
Texte de Jean Richepin, chanté par Georges Brassens },
album={Album},
copyright={Copyright},
cover={img/test/test_chordpro/metadata_cover},
cover={img/metadata_cover},
foo={Foo},
]
@ -19,8 +19,8 @@ Subtitle5}[
\textnote{Comment}
\musicnote{GuitarComment}
\lilypond{scores/test/test_chordpro/metadata_lilypond}
\image{img/test/test_chordpro/metadata_image}
\lilypond{scores/metadata_lilypond}
\image{img/metadata_image}

43
test/test_chordpro/newline.crlf.html

@ -0,0 +1,43 @@
<span class="song-language">Lang: en</span><br>
<div class="song_content">
<p class="verse">This is a verse<br>
With a new line<br>
<br>
The second part of the verse<br>
Is this line
</p>
<p class="verse">Here is a new line at the end<br>
</p>
<p class="verse">Foo bar
</p>
<p class="verse"><br>
And a new line<br>
At the beginning
</p>
<p class="chorus">New lines can also<br>
<br>
Be in chorus
</p>
<p class="bridge">New lines can also<br>
<br>
Be in bridges
</p>
<p class="verse">New lines can also<br>
<br>
Be surrounded by spaces
</p>
<p class="verse">New lines cannot
</p>
</div>

41
test/test_chordpro/newline.crlf.sgc

@ -0,0 +1,41 @@
{lang: en}
This is a verse
With a new line
{newline}
The second part of the verse
Is this line
Here is a new line at the end
{newline}
Foo bar
{newline}
And a new line
At the beginning
{start_of_chorus}
New lines can also
{newline}
Be in chorus
{end_of_chorus}
{start_of_bridge}
New lines can also
{newline}
Be in bridges
{end_of_bridge}
New lines can also
{newline}
Be surrounded by spaces
New lines cannot

2
test/test_chordpro/newline.crlf.source

@ -0,0 +1,2 @@
# This content will be overwritten with `newline.source` content
# with windows line endings (CRLF) - for testing purposes

61
test/test_chordpro/newline.crlf.tex

@ -0,0 +1,61 @@
\selectlanguage{english}
\beginsong{}[
by={
},
]
\begin{verse}
This is a verse
With a new line
~\\
The second part of the verse
Is this line
\end{verse}
\begin{verse}
Here is a new line at the end
~\\
\end{verse}
\begin{verse}
Foo bar
\end{verse}
\begin{verse}
~\\
And a new line
At the beginning
\end{verse}
\begin{chorus}
New lines can also
~\\
Be in chorus
\end{chorus}
\begin{bridge}
New lines can also
~\\
Be in bridges
\end{bridge}
\begin{verse}
New lines can also
~\\
Be surrounded by spaces
\end{verse}
\begin{verse}
New lines cannot
\end{verse}
\endsong

95
test/test_chordpro/test_parser.py

@ -2,6 +2,7 @@
# pylint: disable=too-few-public-methods
import contextlib
import glob
import os
import unittest
@ -33,6 +34,38 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
maxDiff = None
@classmethod
def setUpClass(cls):
cls._overwrite_clrf()
@classmethod
def tearDownClass(cls):
cls._reset_clrf()
@staticmethod
@contextlib.contextmanager
def chdir():
"""Context to temporarry change current directory to this file directory
"""
olddir = os.getcwd()
os.chdir(resource_filename(__name__, ""))
yield
os.chdir(olddir)
def assertRender(self, base, destformat): # pylint: disable=invalid-name
"""Assert that `{base}.source` is correctly rendered in the `destformat`.
"""
sourcename = "{}.source".format(base)
destname = "{}.{}".format(base, destformat)
with self.chdir():
with open_read(destname) as expectfile:
with disable_logging():
song = self.song_plugins[LANGUAGES[destformat]]['sgc'](sourcename, self.config)
self.assertMultiLineEqual(
song.render(output=sourcename).strip(),
expectfile.read().strip(),
)
@classmethod
def _iter_testmethods(cls):
"""Iterate over song files to test."""
@ -40,7 +73,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
cls.config = DEFAULT_CONFIG
if 'datadir' not in cls.config:
cls.config['datadir'] = []
cls.config['datadir'].append(resource_filename(__name__, 'datadir'))
cls.config['datadir'].append('datadir')
cls.config['datadir'].append(__DATADIR__)
cls.song_plugins = files.load_plugins(
@ -48,19 +81,17 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
root_modules=['songs'],
keyword='SONG_RENDERERS',
)
for source in sorted(glob.glob(os.path.join(
os.path.dirname(__file__),
'*.source',
))):
base = os.path.relpath(source, os.getcwd())[:-len(".source")]
for dest in LANGUAGES:
destname = "{}.{}".format(base, dest)
if not os.path.exists(destname):
continue
yield (
"test_{}_{}".format(os.path.basename(base), dest),
cls._create_test(base, dest),
)
with cls.chdir():
for source in sorted(glob.glob('*.source')):
base = source[:-len(".source")]
for dest in LANGUAGES:
destname = "{}.{}".format(base, dest)
if not os.path.exists(destname):
continue
yield (
"test_{}_{}".format(base, dest),
cls._create_test(base, dest),
)
@classmethod
def _create_test(cls, base, dest):
@ -71,19 +102,35 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
"""Test that `base` is correctly parsed and rendered."""
if base is None or dest is None:
return
destname = "{}.{}".format(base, dest)
with open_read(destname) as expectfile:
chordproname = "{}.source".format(base)
with disable_logging():
self.assertMultiLineEqual(
self.song_plugins[LANGUAGES[dest]]['sgc'](chordproname, self.config).render(
output=chordproname,
).strip(),
expectfile.read().strip(),
)
self.assertRender(base, dest)
test_parse_render.__doc__ = (
"Test that '{base}' is correctly parsed and rendererd into '{format}' format."
).format(base=os.path.basename(base), format=dest)
return test_parse_render
@classmethod
def _overwrite_clrf(cls):
"""Overwrite `*.crlf.source` files to force the CRLF line endings.
"""
with cls.chdir():
for crlfname in sorted(glob.glob('*.crlf.source')):
base = crlfname[:-len(".crlf.source")]
sourcename = base + ".source"
with open_read(sourcename) as sourcefile:
with open(crlfname, 'w') as crlffile:
for line in sourcefile:
crlffile.write(line.replace('\n', '\r\n'))
@classmethod
def _reset_clrf(cls):
"""Reset `*.crlf.source` files.
"""
crlf_msg = """# This content will be overwritten with `{}.source` content
# with windows line endings (CRLF) - for testing purposes
"""
with cls.chdir():
for crlfname in sorted(glob.glob('*.crlf.source')):
base = crlfname[:-len(".crlf.source")]
with open(crlfname, 'w') as crlffile:
crlffile.write(crlf_msg.format(base))

Loading…
Cancel
Save