|
@ -167,16 +167,12 @@ class Song: |
|
|
def __repr__(self): |
|
|
def __repr__(self): |
|
|
return repr((self.titles, self.data, self.fullpath)) |
|
|
return repr((self.titles, self.data, self.fullpath)) |
|
|
|
|
|
|
|
|
def render(self, output_format, output=None, *args, **kwargs): |
|
|
def render(self, output=None, *args, **kwargs): |
|
|
"""Return the code rendering this song. |
|
|
"""Return the code rendering this song. |
|
|
|
|
|
|
|
|
Arguments: |
|
|
Arguments: |
|
|
- output_format: Format of the output file (latex, chordpro...) |
|
|
|
|
|
- output: Name of the output file, or `None` if irrelevant. |
|
|
- output: Name of the output file, or `None` if irrelevant. |
|
|
""" |
|
|
""" |
|
|
method = "render_{}".format(output_format) |
|
|
|
|
|
if hasattr(self, method): |
|
|
|
|
|
return getattr(self, method)(output, *args, **kwargs) |
|
|
|
|
|
raise NotImplementedError() |
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
def _parse(self, config): # pylint: disable=no-self-use |
|
|
def _parse(self, config): # pylint: disable=no-self-use |
|
@ -204,15 +200,24 @@ class Song: |
|
|
if os.path.isdir(fullpath): |
|
|
if os.path.isdir(fullpath): |
|
|
yield fullpath |
|
|
yield fullpath |
|
|
|
|
|
|
|
|
def search_file(self, filename, extensions=None, directories=None): |
|
|
def search_datadir_file(self, filename, extensions=None, directories=None): |
|
|
"""Search for a file name. |
|
|
"""Search for a file name. |
|
|
|
|
|
|
|
|
:param str filename: The name, as provided in the chordpro file (with or without extension). |
|
|
:param str filename: The name, as provided in the chordpro file (with or without extension). |
|
|
:param list extensions: Possible extensions (with '.'). Default is no extension. |
|
|
:param list extensions: Possible extensions (with '.'). Default is no extension. |
|
|
:param iterator directories: Other directories where to search for the file |
|
|
:param iterator directories: Other directories where to search for the file |
|
|
The directory where the Song file is stored is added to the list. |
|
|
The directory where the Song file is stored is added to the list. |
|
|
|
|
|
:return: A tuple `(datadir, filename, extension)` if file has been |
|
|
Returns None if nothing found. |
|
|
found. It is guaranteed that `os.path.join(datadir, |
|
|
|
|
|
filename+extension)` is a (relative or absolute) valid path to an |
|
|
|
|
|
existing filename. |
|
|
|
|
|
* `datadir` is the datadir in which the file has been found. Can be |
|
|
|
|
|
the empty string. |
|
|
|
|
|
* `filename` is the filename, relative to the datadir. |
|
|
|
|
|
* `extension` is the extension that is to be appended to the |
|
|
|
|
|
filename to get the real filename. Can be the empty string. |
|
|
|
|
|
|
|
|
|
|
|
Raise `FileNotFoundError` if nothing found. |
|
|
|
|
|
|
|
|
This function can also be used as a preprocessor for a renderer: for |
|
|
This function can also be used as a preprocessor for a renderer: for |
|
|
instance, it can compile a file, place it in a temporary folder, and |
|
|
instance, it can compile a file, place it in a temporary folder, and |
|
@ -223,28 +228,43 @@ class Song: |
|
|
if directories is None: |
|
|
if directories is None: |
|
|
directories = self.config['datadir'] |
|
|
directories = self.config['datadir'] |
|
|
|
|
|
|
|
|
|
|
|
for directory in directories: |
|
|
|
|
|
for extension in extensions: |
|
|
|
|
|
if os.path.isfile(os.path.join(directory, filename + extension)): |
|
|
|
|
|
return directory, filename, extension |
|
|
|
|
|
|
|
|
songdir = os.path.dirname(self.fullpath) |
|
|
songdir = os.path.dirname(self.fullpath) |
|
|
|
|
|
for extension in extensions: |
|
|
|
|
|
if os.path.isfile(os.path.join(songdir, filename + extension)): |
|
|
|
|
|
return "", os.path.join(songdir, filename), extension |
|
|
|
|
|
|
|
|
for directory in [songdir] + list(directories): |
|
|
raise FileNotFoundError(filename) |
|
|
for extension in extensions: |
|
|
|
|
|
fullpath = os.path.join(directory, filename + extension) |
|
|
def search_file(self, filename, extensions=None, *, datadirs=None): |
|
|
if os.path.isfile(fullpath): |
|
|
"""Return the path to a file present in a datadir. |
|
|
return os.path.abspath(fullpath) |
|
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
|
|
def search_image(self, filename, none_if_not_found=False): |
|
|
Implementation is specific to each renderer, as: |
|
|
|
|
|
- some renderers can preprocess files; |
|
|
|
|
|
- some renderers can return the absolute path, other can return something else; |
|
|
|
|
|
- etc. |
|
|
|
|
|
""" |
|
|
|
|
|
raise NotImplementedError() |
|
|
|
|
|
|
|
|
|
|
|
def search_image(self, filename): |
|
|
"""Search for an image file""" |
|
|
"""Search for an image file""" |
|
|
filepath = self.search_file( |
|
|
return self.search_file( |
|
|
filename, |
|
|
filename, |
|
|
['', '.jpg', '.png'], |
|
|
['', '.jpg', '.png'], |
|
|
self.get_datadirs('img'), |
|
|
datadirs=self.get_datadirs('img'), |
|
|
) |
|
|
) |
|
|
return filepath if none_if_not_found or filepath else filename |
|
|
|
|
|
|
|
|
|
|
|
def search_partition(self, filename, none_if_not_found=False): |
|
|
def search_partition(self, filename): |
|
|
"""Search for a lilypond file""" |
|
|
"""Search for a lilypond file""" |
|
|
filepath = self.search_file(filename, ['', '.ly']) |
|
|
return self.search_file( |
|
|
return filepath if none_if_not_found or filepath else filename |
|
|
filename, |
|
|
|
|
|
['', '.ly'], |
|
|
|
|
|
datadirs=self.get_datadirs('img'), |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
def unprefixed_title(title, prefixes): |
|
|
def unprefixed_title(title, prefixes): |
|
|
"""Remove the first prefix of the list in the beginning of title (if any). |
|
|
"""Remove the first prefix of the list in the beginning of title (if any). |
|
|