from .. import mime_utils
+ A converter for a simple markup for song lyrics.
+ The first paragraph is interpreted as information about the song.
+ The first line is the song title, and the second line has the authors.
+ Remainder lines are in a "Key: Value" format, where the keys can be
+ anything, and are case-insensitive.
+ This is followed by paragraphs, where each paragraph is a verse.
+ ... Author One, Author Two
+ ... Copyleft: Foobar Lawyers
+ ... And a continuation of the same verse!
+ ... This verse is labelled.
+ ... The label won't show.
+ ... And the verse can be repeated::
+ ... If it has a colon on the first line,
+ ... it must be doubled to escape it
+ The lyrics can be loaded using the from_file class method.
+ Then, the lyrics can be queried for their information.
+ >>> from StringIO import StringIO
+ >>> lyrics = LyricsConverter.from_file(StringIO(source), 'text/plain')
+ >>> lyrics.info['title']
+ >>> lyrics.info['authors']
+ 'Author One, Author Two'
+ >>> lyrics.info['copyleft']
+ >>> lyrics.verses == lyrics.verses
+ >>> 'verse is labelled' in lyrics.verses
+ >>> 'Verse 2' in lyrics.verses
+ The lyrics can be changed and written out to a variety of output types.
+ For instance, if we change the song name, the source output should be almost
+ the same as the original data.
+ The differences are that the info keys will be shown in title case, and
+ verse labels will be removed.
+ TODO: fix this so that verse labels are retained.
+ >>> lyrics.title = 'Your Song Title'
+ >>> output = StringIO()
+ >>> lyrics.save(output, 'text/plain')
+ >>> new_source = output.getvalue()
+ Copyleft: Foobar Lawyers
+ And a continuation of the same verse!
+ This verse is labelled.
+ This verse is labelled.
+ And the verse can be repeated::
+ If it has a colon on the first line,
+ it must be doubled to escape it
+ def __init__(self, info, verses):
+ self.verses = list(verses)
+ return self.info['title']
+ def set_title(self, new_title):
+ self.info['title'] = new_title
+ title = property(get_title, set_title)
+ return self.info['authors']
+ def set_authors(self, new_authors):
+ self.info['authors'] = new_authors
+ authors = property(get_authors, set_authors)
+ def save_source(self, output):
+ print >> output, self.title
+ print >> output, self.authors
+ for key, value in self.info.items():
+ if key not in ('title', 'authors'):
+ print >> output, '%s: %s' % (key.title(), value)
+ print >> output, '\n\n'.join(self.verses)
def save(self, file, mime):
assert mime_utils.any_matches(mime, self.output_mimetypes)
+ if mime == 'text/plain':
+ elif mime == 'text/html':
+ elif mime == 'text/x-tex':
+ raise NotImplementedError
+ # only reached if you've changed output_mimetypes
+ # without changing this if statement
+ raise ValueError, 'should not be reached'
def from_file(cls, file, mime):
assert mime_utils.any_matches(mime, cls.input_mimetypes)
+ info, verses = parse_lyrics(file)
+ return cls(info, verses)
- info, verses = parse_lyrics(file)