|
|
@ -4,13 +4,14 @@ |
|
|
|
|
|
|
|
import errno |
|
|
|
import hashlib |
|
|
|
import jinja2 |
|
|
|
import logging |
|
|
|
import os |
|
|
|
import pickle |
|
|
|
import re |
|
|
|
|
|
|
|
from patacrep.authors import processauthors |
|
|
|
from patacrep.latex import parsesong |
|
|
|
from patacrep.content import Content |
|
|
|
|
|
|
|
LOGGER = logging.getLogger(__name__) |
|
|
|
|
|
|
@ -62,18 +63,32 @@ class DataSubpath(object): |
|
|
|
self.subpath = os.path.join(self.subpath, path) |
|
|
|
return self |
|
|
|
|
|
|
|
# pylint: disable=too-few-public-methods, too-many-instance-attributes |
|
|
|
class Song(object): |
|
|
|
"""Song management""" |
|
|
|
# pylint: disable=too-many-instance-attributes |
|
|
|
class Song(Content): |
|
|
|
"""Song (or song metadata) |
|
|
|
|
|
|
|
This class represents a song, bound to a file. |
|
|
|
|
|
|
|
- It can parse the file given in arguments. |
|
|
|
- It can render the song as some LaTeX code. |
|
|
|
- Its content is cached, so that if the file has not been changed, the |
|
|
|
file is not parsed again. |
|
|
|
|
|
|
|
This class is inherited by classes implementing song management for |
|
|
|
several file formats. Those subclasses must implement: |
|
|
|
- `parse()` to parse the file; |
|
|
|
- `render()` to render the song as LaTeX code. |
|
|
|
""" |
|
|
|
|
|
|
|
# Version format of cached song. Increment this number if we update |
|
|
|
# information stored in cache. |
|
|
|
CACHE_VERSION = 0 |
|
|
|
CACHE_VERSION = 1 |
|
|
|
|
|
|
|
# List of attributes to cache |
|
|
|
cached_attributes = [ |
|
|
|
"titles", |
|
|
|
"unprefixed_titles", |
|
|
|
"cached", |
|
|
|
"data", |
|
|
|
"datadir", |
|
|
|
"fullpath", |
|
|
@ -109,10 +124,14 @@ class Song(object): |
|
|
|
self.fullpath |
|
|
|
)) |
|
|
|
|
|
|
|
# Data extraction from the latex song |
|
|
|
self.data = parsesong(self.fullpath) |
|
|
|
self.titles = self.data['@titles'] |
|
|
|
self.languages = self.data['@languages'] |
|
|
|
# Default values |
|
|
|
self.data = {} |
|
|
|
self.titles = [] |
|
|
|
self.languages = [] |
|
|
|
self.authors = [] |
|
|
|
|
|
|
|
# Parsing and data processing |
|
|
|
self.parse() |
|
|
|
self.datadir = datadir |
|
|
|
self.unprefixed_titles = [ |
|
|
|
unprefixed_title( |
|
|
@ -123,13 +142,15 @@ class Song(object): |
|
|
|
in self.titles |
|
|
|
] |
|
|
|
self.subpath = subpath |
|
|
|
if "by" in self.data: |
|
|
|
self.authors = processauthors( |
|
|
|
self.data["by"], |
|
|
|
**config["_compiled_authwords"] |
|
|
|
) |
|
|
|
else: |
|
|
|
self.authors = [] |
|
|
|
self.authors = processauthors( |
|
|
|
self.authors, |
|
|
|
**config["_compiled_authwords"] |
|
|
|
) |
|
|
|
|
|
|
|
# Cache management |
|
|
|
|
|
|
|
#: Special attribute to allow plugins to store cached data |
|
|
|
self.cached = None |
|
|
|
|
|
|
|
self._version = self.CACHE_VERSION |
|
|
|
self._write_cache() |
|
|
@ -149,6 +170,50 @@ class Song(object): |
|
|
|
def __repr__(self): |
|
|
|
return repr((self.titles, self.data, self.fullpath)) |
|
|
|
|
|
|
|
def begin_new_block(self, previous, __context): |
|
|
|
"""Return a boolean stating if a new block is to be created.""" |
|
|
|
return not isinstance(previous, Song) |
|
|
|
|
|
|
|
def begin_block(self, context): |
|
|
|
"""Return the string to begin a block.""" |
|
|
|
indexes = context.resolve("indexes") |
|
|
|
if isinstance(indexes, jinja2.runtime.Undefined): |
|
|
|
indexes = "" |
|
|
|
return r'\begin{songs}{%s}' % indexes |
|
|
|
|
|
|
|
def end_block(self, __context): |
|
|
|
"""Return the string to end a block.""" |
|
|
|
return r'\end{songs}' |
|
|
|
|
|
|
|
def render(self, __context): |
|
|
|
"""Returns the TeX code rendering the song. |
|
|
|
|
|
|
|
This function is to be defined by subclasses. |
|
|
|
""" |
|
|
|
return '' |
|
|
|
|
|
|
|
def parse(self): |
|
|
|
"""Parse file `self.fullpath`. |
|
|
|
|
|
|
|
This function is to be defined by subclasses. |
|
|
|
|
|
|
|
It set the following attributes: |
|
|
|
|
|
|
|
- titles: the list of (raw) titles. This list will be processed to |
|
|
|
remove prefixes. |
|
|
|
- languages: the list of languages used in the song, as languages |
|
|
|
recognized by the LaTeX babel package. |
|
|
|
- authors: the list of (raw) authors. This list will be processed to |
|
|
|
'clean' it (see function :func:`patacrep.authors.processauthors`). |
|
|
|
- data: song metadata. Used (among others) to sort the songs. |
|
|
|
- cached: additional data that will be cached. Thus, data stored in |
|
|
|
this attribute must be picklable. |
|
|
|
""" |
|
|
|
self.data = {} |
|
|
|
self.titles = [] |
|
|
|
self.languages = [] |
|
|
|
self.authors = [] |
|
|
|
|
|
|
|
def unprefixed_title(title, prefixes): |
|
|
|
"""Remove the first prefix of the list in the beginning of title (if any). |
|
|
|
""" |
|
|
@ -158,4 +223,3 @@ def unprefixed_title(title, prefixes): |
|
|
|
return match.group(2) |
|
|
|
return title |
|
|
|
|
|
|
|
|