Example #1
0
def parse(keyword, argument, config):
    """Parse the songsection.

    Arguments:
    - keyword ("songsection" or "songchapter"): the section to use;
    - argument: name of the section;
    - config: configuration dictionary of the current songbook.
    """
    return ContentList([SongSection(keyword, argument)])
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
def parse(keyword, config, argument):
    """Include an external file content.

    Arguments:
        - keyword: the string 'include';
        - config: the current songbook configuration dictionary;
        - argument:
            a list of file paths to be included
            or a string of the file to include

    """
    new_contentlist = ContentList()
    if isinstance(argument, str):
        argument = [argument]

    for filename in argument:
        try:
            filepath = load_from_datadirs(
                filename,
                config['_songdir'],
                config.get('_songbookfile_dir')
            )
        except ContentError as error:
            new_contentlist.append_error(error)
            continue
        content_file = None
        try:
            with encoding.open_read(
                filepath,
                encoding=config['book']['encoding']
                ) as content_file:
                new_content = yaml.load(content_file)
        except Exception as error: # pylint: disable=broad-except
            new_contentlist.append_error(ContentError(
                keyword="include",
                message="Error while loading file '{}': {}".format(filepath, error),
                ))
            continue

        config['_datadir'].append(os.path.abspath(os.path.dirname(filepath)))
        new_contentlist.extend(process_content(new_content, config))
        config['_datadir'].pop()

    return new_contentlist
Example #6
0
def parse(keyword, argument, config):
    """Parse the section.

    Arguments:
    - keyword (one of "part", "chapter", "section", ... , "subparagraph", and
      their starred versions "part*", "chapter*", ... , "subparagraph*"): the
      section to use;
    - argument:
        either a string describing the section name
        or a dict
            name: Name of the section
            short: Shortname of the section (only for non starred sections)
    - config: configuration dictionary of the current songbook.
    """
    if isinstance(argument, str):
        argument = {'name': argument}
    return ContentList([Section(keyword, **argument)])
Example #7
0
def parse(keyword, argument, config):
    """Parse the counter setter.

    Arguments:
    - nothing
        reset the "songnum" counter to 1
    - an int
        reset the "songnum" counter to this value
    - a dict:
        - name ("songnum"): the counter to set;
        - value: value to set the counter to;
    """
    if argument is None:
        argument = {}
    if isinstance(argument, int):
        argument = {'value': argument}
    name = argument.get('name', 'songnum')
    value = argument.get('value', 1)
    return ContentList([CounterSetter(name, value)])
Example #8
0
def parse(keyword, config, argument, contentlist):
    """Include an external file content.

    Arguments:
        - keyword: the string 'include';
        - config: the current songbook configuration dictionary;
        - argument: None;
        - contentlist: a list of file paths to be included.
    """
    new_contentlist = ContentList()

    for path in contentlist:
        try:
            filepath = load_from_datadirs(path, config.get('datadir', []))
        except ContentError as error:
            new_contentlist.append_error(error)
            continue
        content_file = None
        try:
            with encoding.open_read(
                filepath,
                encoding=config['encoding']
                ) as content_file:
                new_content = json.load(content_file)
        except Exception as error: # pylint: disable=broad-except
            new_contentlist.append_error(ContentError(
                keyword="include",
                message="Error while loading file '{}': {}".format(filepath, error),
                ))
            continue

        config["datadir"].append(os.path.abspath(os.path.dirname(filepath)))
        new_contentlist.extend(process_content(new_content, config))
        config["datadir"].pop()

    return new_contentlist
Example #9
0
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)
Example #10
0
def parse(keyword, argument, config):
    return ContentList([FakeContent()])
Example #11
0
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)