Exemple #1
0
    def _iter_testmethods(cls):
        """Iterate over song files to test."""
        # Setting datadir
        # Load the default songbook config
        cls.config = config_model('default')['en']
        cls.config['_datadir'] = ['datadir']

        cls.song_renderer = files.load_renderer_plugins()

        with cls.chdir():
            for source in sorted(glob.glob('*.*.source')):
                [*base, in_format, _] = source.split('.')
                base = '.'.join(base)
                for out_format in OUTPUTS[in_format]:
                    outname = "{}.{}".format(base, out_format)
                    if not os.path.exists(outname):
                        continue
                    yield (
                        "test_{}_{}_2_{}".format(base, in_format, out_format),
                        cls._create_test(base, in_format, out_format),
                        )

            if os.path.isdir("errors"):
                with cls.chdir('errors'):
                    for source in sorted(glob.glob('*.*.source')):
                        [*base, in_format, _] = source.split('.')
                        base = '.'.join(base)
                        yield (
                            "test_{}_{}_failure".format(base, in_format),
                            cls._create_failure(base, in_format),
                            )
Exemple #2
0
def main(args=None):
    """Main function: run from command line."""
    if args is None:
        args = sys.argv
    if len(args) < 4:
        LOGGER.error("Invalid number of arguments.")
        LOGGER.error("Usage: %s", _usage())
        sys.exit(1)

    source = args[1]
    dest = args[2]
    song_files = args[3:]

    renderers = files.load_renderer_plugins()

    if dest not in renderers:
        LOGGER.error(
            "Unknown destination file format '%s'. Available ones are %s.",
            source,
            ", ".join(["'{}'".format(key) for key in renderers.keys()])
            )
        sys.exit(1)
    if source not in renderers[dest]:
        LOGGER.error(
            "Unknown source file format '%s'. Available ones are %s.",
            source,
            ", ".join(["'{}'".format(key) for key in renderers[dest].keys()])
            )
        sys.exit(1)

    for file in song_files:
        try:
            song = renderers[dest][source](file, config_model('default')['en'])
            destname = "{}.{}".format(".".join(file.split(".")[:-1]), dest)
            if os.path.exists(destname):
                if not confirm(destname):
                    continue
            with open(destname, "w") as destfile:
                destfile.write(song.render())

        except ContentError:
            LOGGER.error("Cannot parse file '%s'.", file)
            sys.exit(1)
        except NotImplementedError:
            LOGGER.error("Cannot convert to format '%s'.", dest)
            sys.exit(1)
        except KeyboardInterrupt:
            print()
            LOGGER.info("Aborted by user.")
            sys.exit(0)

    sys.exit(0)
Exemple #3
0
def main(args=None):
    """Main function: run from command line."""
    if args is None:
        args = sys.argv
    if len(args) < 4:
        LOGGER.error("Invalid number of arguments.")
        LOGGER.error("Usage: %s", _usage())
        sys.exit(1)

    source = args[1]
    dest = args[2]
    song_files = args[3:]

    renderers = files.load_renderer_plugins()

    if dest not in renderers:
        LOGGER.error(
            "Unknown destination file format '%s'. Available ones are %s.",
            source,
            ", ".join(["'{}'".format(key) for key in renderers.keys()]))
        sys.exit(1)
    if source not in renderers[dest]:
        LOGGER.error(
            "Unknown source file format '%s'. Available ones are %s.", source,
            ", ".join(["'{}'".format(key) for key in renderers[dest].keys()]))
        sys.exit(1)

    for file in song_files:
        try:
            song = renderers[dest][source](file, config_model('default')['en'])
            destname = "{}.{}".format(".".join(file.split(".")[:-1]), dest)
            if os.path.exists(destname):
                if not confirm(destname):
                    continue
            with open(destname, "w") as destfile:
                destfile.write(song.render())

        except ContentError:
            LOGGER.error("Cannot parse file '%s'.", file)
            sys.exit(1)
        except NotImplementedError:
            LOGGER.error("Cannot convert to format '%s'.", dest)
            sys.exit(1)
        except KeyboardInterrupt:
            print()
            LOGGER.info("Aborted by user.")
            sys.exit(0)

    sys.exit(0)
Exemple #4
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)
Exemple #5
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)