def parse(keyword, argument, config): """Parse the tex files. Arguments: - keyword: unused; - argument: a list of tex files to include or a string of the tex file to include; - config: configuration dictionary of the current songbook. """ if isinstance(argument, str): argument = [argument] filelist = ContentList() basefolders = [path.fullpath for path in config['_songdir']] + list( files.iter_datadirs(config['_datadir'], 'latex')) for filename in argument: checked_file = None for path in basefolders: if os.path.exists(os.path.join(path, filename)): checked_file = os.path.relpath(os.path.join( path, filename, )) break if not checked_file: filelist.append_error( ContentError( keyword="tex", message=errors.notfound(filename, basefolders), )) continue filelist.append(LaTeX(checked_file)) return filelist
def load_from_datadirs(filename, songdirs): """Load 'filename' from one of the songdirs. Raise an exception if it was not found in any songdir. """ for path in songdirs: fullpath = os.path.join(path.fullpath, filename) if os.path.exists(fullpath): return fullpath # File not found raise ContentError("include", errors.notfound(filename, list(songdirs)))
def load_from_datadirs(path, datadirs): """Load 'path' from one of the datadirs. Raise an exception if it was found if none of the datadirs of 'config'. """ for filepath in files.iter_datadirs(datadirs, "songs", path): if os.path.exists(filepath): return filepath # File not found raise ContentError( "include", errors.notfound(path, list(files.iter_datadirs(datadirs))) )
def load_from_datadirs(filename, songdirs): """Load 'filename' from one of the songdirs. Raise an exception if it was not found in any songdir. """ for path in songdirs: fullpath = os.path.join(path.fullpath, filename) if os.path.exists(fullpath): return fullpath # File not found raise ContentError( "include", errors.notfound(filename, list(songdirs)) )
def load_from_datadirs(filename, songdirs, songbookfile_dir=None): """Load 'filename', relative to: - or one of the songdirs - the dir of the songbook file dir Raise an exception if it was not found in any directory. """ for path in songdirs: fullpath = os.path.join(path.fullpath, filename) if os.path.exists(fullpath): return fullpath if songbookfile_dir: fullpath = os.path.join(songbookfile_dir, filename) if os.path.exists(fullpath): return fullpath # File not found raise ContentError("include", errors.notfound(filename, list(songdirs)))
def load_from_datadirs(filename, songdirs, songbookfile_dir=None): """Load 'filename', relative to: - or one of the songdirs - the dir of the songbook file dir Raise an exception if it was not found in any directory. """ for path in songdirs: fullpath = os.path.join(path.fullpath, filename) if os.path.exists(fullpath): return fullpath if songbookfile_dir: fullpath = os.path.join(songbookfile_dir, filename) if os.path.exists(fullpath): return fullpath # File not found raise ContentError( "include", errors.notfound(filename, list(songdirs)) )
def parse(keyword, argument, contentlist, config): """Parse the contentlist. Arguments: - keyword: unused; - argument: unused; - contentlist: a list of name of tex files; - config: configuration dictionary of the current songbook. """ if not contentlist: LOGGER.warning( "Useless 'tex' content: list of files to include is empty." ) filelist = ContentList() basefolders = itertools.chain( (path.fullpath for path in config['_songdir']), files.iter_datadirs(config['datadir']), files.iter_datadirs(config['datadir'], 'latex'), ) for filename in contentlist: checked_file = None for path in basefolders: if os.path.exists(os.path.join(path, filename)): checked_file = os.path.relpath(os.path.join( path, filename, )) break if not checked_file: filelist.append_error( ContentError( keyword="tex", message=errors.notfound(filename, basefolders), ) ) continue filelist.append(LaTeX(checked_file)) return filelist
def parse(keyword, argument, config): """Parse the tex files. Arguments: - keyword: unused; - argument: a list of tex files to include or a string of the tex file to include; - config: configuration dictionary of the current songbook. """ if isinstance(argument, str): argument = [argument] filelist = ContentList() basefolders = itertools.chain( (path.fullpath for path in config['_songdir']), files.iter_datadirs(config['_datadir'], 'latex'), ) for filename in argument: checked_file = None for path in basefolders: if os.path.exists(os.path.join(path, filename)): checked_file = os.path.relpath(os.path.join( path, filename, )) break if not checked_file: filelist.append_error( ContentError( keyword="tex", message=errors.notfound(filename, basefolders), ) ) continue filelist.append(LaTeX(checked_file)) return filelist
def __init__(self, template, datadirs, lang, encoding=None): '''Start a new jinja2 environment for .tex creation. Arguments: - template: name of the template to use. - datadirs: list of locations of the data directory (which may contain file <datadir>/templates/<template>). - lang: main language of songbook. - encoding: if set, encoding of the template. ''' self.lang = lang # Load templates in filesystem ... loaders = [ FileSystemLoader(datadir) for datadir in files.iter_datadirs(datadirs, 'templates', 'songbook') ] jinjaenv = Environment( loader=ChoiceLoader(loaders), extensions=[VariablesExtension], ) try: super().__init__(template, jinjaenv, encoding) except TemplateNotFound as exception: # Only works if all loaders are FileSystemLoader(). paths = [ item for loader in self.jinjaenv.loader.loaders for item in loader.searchpath ] raise errors.TemplateError( exception, errors.notfound( exception.name, paths, message='Template "{name}" not found in {paths}.' ), )
def parse(keyword, argument, config): """Parse data associated with keyword 'song'. Arguments: - keyword: unused; - argument: a list of strings, which are interpreted as regular expressions (interpreted using the glob module), referring to songs. - config: the current songbook configuration dictionary. Return a list of Song() instances. """ contentlist = argument if isinstance(contentlist, str): contentlist = [contentlist] plugins = files.load_renderer_plugins(config['_datadir'])['tsg'] if '_langs' not in config: config['_langs'] = set() songlist = ContentList() for songdir in config['_songdir']: if contentlist: break contentlist = files.recursive_find(songdir.fullpath, plugins.keys()) if contentlist is None: contentlist = [] # No content was set or found for elem in contentlist: before = len(songlist) for songdir in config['_songdir']: if not os.path.isdir(songdir.datadir): continue with files.chdir(songdir.datadir): # Starting with Python 3.5 glob can be recursive: **/*.csg for instance # for filename in glob.iglob(os.path.join(songdir.subpath, elem), recursive=True): for filename in glob.iglob(os.path.join(songdir.subpath, elem)): LOGGER.debug('Parsing file "{}"…'.format(filename)) extension = filename.split(".")[-1] if extension not in plugins: LOGGER.info( ('Cannot parse "%s": name does not end with one ' 'of %s. Ignored.'), os.path.join(songdir.datadir, filename), ", ".join([ "'.{}'".format(key) for key in plugins.keys() ])) continue try: renderer = SongRenderer(plugins[extension]( filename, config, datadir=songdir.datadir, )) except ContentError as error: songlist.append_error(error) if config['_error'] == "failonsong": raise errors.SongbookError( "Error in song '{}'. Stopping as requested.". format(os.path.join(songdir.fullpath, filename))) continue if renderer.has_errors( ) and config['_error'] == "failonsong": raise errors.SongbookError( "Error in song '{}'. Stopping as requested.". format(os.path.join(songdir.fullpath, filename))) songlist.append(renderer) config["_langs"].add(renderer.song.lang) if len(songlist) > before: break if len(songlist) == before: # No songs were added LOGGER.warning( errors.notfound( elem, [item.fullpath for item in config['_songdir']], message= 'Ignoring "{name}": did not match any file in {paths}.', )) return sorted(songlist)
def parse(keyword, argument, contentlist, config): """Parse data associated with keyword 'song'. Arguments: - keyword: unused; - argument: unused; - contentlist: a list of strings, which are interpreted as regular expressions (interpreted using the glob module), referring to songs. - config: the current songbook configuration dictionary. Return a list of Song() instances. """ plugins = config['_song_plugins'] if '_langs' not in config: config['_langs'] = set() songlist = ContentList() for songdir in config['_songdir']: if contentlist: break contentlist = files.recursive_find(songdir.fullpath, plugins.keys()) for elem in contentlist: before = len(songlist) for songdir in config['_songdir']: if not os.path.isdir(songdir.datadir): continue with files.chdir(songdir.datadir): # Starting with Python 3.5 glob can be recursive: **/*.csg for instance # for filename in glob.iglob(os.path.join(songdir.subpath, elem), recursive=True): for filename in glob.iglob(os.path.join(songdir.subpath, elem)): LOGGER.debug('Parsing file "{}"…'.format(filename)) extension = filename.split(".")[-1] if extension not in plugins: LOGGER.info( ( 'Cannot parse "%s": name does not end with one ' 'of %s. Ignored.' ), os.path.join(songdir.datadir, filename), ", ".join(["'.{}'".format(key) for key in plugins.keys()]) ) continue try: renderer = SongRenderer(plugins[extension]( filename, config, datadir=songdir.datadir, )) except ContentError as error: songlist.append_error(error) if config['_error'] == "failonsong": raise errors.SongbookError( "Error in song '{}'. Stopping as requested." .format(os.path.join(songdir.fullpath, filename)) ) continue if renderer.has_errors() and config['_error'] == "failonsong": raise errors.SongbookError( "Error in song '{}'. Stopping as requested." .format(os.path.join(songdir.fullpath, filename)) ) songlist.append(renderer) config["_langs"].add(renderer.song.lang) if len(songlist) > before: break if len(songlist) == before: # No songs were added LOGGER.warning(errors.notfound( elem, [item.fullpath for item in config['_songdir']], message='Ignoring "{name}": did not match any file in {paths}.', )) return sorted(songlist)