Example #1
0
def parse(keyword, config, argument, contentlist):
    """Return a list songs included in contentlist, whith a different base path.

    Arguments:
    - keyword: unused;
    - config: the current songbook configuration dictionary;
    - argument: a directory;
    - contentlist: songbook content, that is parsed by
      patacrep.content.process_content().

    This function adds 'argument' to the directories where songs are searched
    for, and then processes the content.

    The 'argument' is added:
    - first as a relative path to the current directory;
    - then as a relative path to every path already present in
      config['songdir'].
    """
    old_songdir = config['_songdir']
    config['_songdir'] = (
            [argument] +
            [os.path.join(path, argument) for path in config['_songdir']] +
            config['_songdir']
            )
    processed_content = process_content(contentlist, config)
    config['_songdir'] = old_songdir
    return processed_content
Example #2
0
def parse(keyword, config, argument):
    """Return a list of songs, whith an another base path.

    Arguments:
    - keyword: unused;
    - config: the current songbook configuration dictionary;
    - argument: a dict containing:
        path: string specifying the path to add to the songdirs list;
        content: songbook content, that is parsed by
            patacrep.content.process_content().

    This function adds 'path' to the directories where songs are searched
    for, and then processes the content.

    The 'path' is added as a relative path to the dir of the songbook file.
    """
    subpath = argument['path']
    old_songdir = config['_songdir']

    config['_songdir'] = [DataSubpath(config['_songbookfile_dir'], subpath)]
    config['_songdir'].extend(old_songdir)

    processed_content = process_content(argument.get('content'), config)
    config['_songdir'] = old_songdir
    return processed_content
Example #3
0
def parse(keyword, config, argument):
    """Return a list of songs, whith an another base path.

    Arguments:
    - keyword: unused;
    - config: the current songbook configuration dictionary;
    - argument: a dict containing:
        path: string specifying the path to add to the songdirs list;
        content: songbook content, that is parsed by
            patacrep.content.process_content().

    This function adds 'path' to the directories where songs are searched
    for, and then processes the content.

    The 'path' is added as a relative path to the dir of the songbook file.
    """
    subpath = argument["path"]
    old_songdir = config["_songdir"]

    config["_songdir"] = [DataSubpath(config["_songbookfile_dir"], subpath)]
    config["_songdir"].extend(old_songdir)

    processed_content = process_content(argument.get("content"), config)
    config["_songdir"] = old_songdir
    return processed_content
Example #4
0
def parse(keyword, config, argument):
    """Return a sorted list of songs.

    Arguments:
        - keyword: the string 'sort';
        - config: the current songbook configuration dictionary;
        - argument: a dict of:
            key: the list of the fields used to sort songs (e.g. "by", "album", "title")
            content: content to be sorted. If this content
                contain something else than a song, an exception is raised.
    """
    if argument is None:
        argument = {}
    sort = argument.get('key', DEFAULT_SORT)
    if isinstance(sort, str):
        sort = [sort]
    try:
        songlist = process_content(argument.get('content'), config)
    except OnlySongsError as error:
        raise ContentError(
            keyword,
            ("Content list of this keyword can be only songs (or content "
             "that result into songs), and the following are not:" +
             str(error.not_songs)))
    return sorted(songlist, key=key_generator(sort))
Example #5
0
def parse(keyword, config, argument):
    """Return a sorted list of songs.

    Arguments:
        - keyword: the string 'sort';
        - config: the current songbook configuration dictionary;
        - argument: a dict of:
            key: the list of the fields used to sort songs (e.g. "by", "album", "title")
            content: content to be sorted. If this content
                contain something else than a song, an exception is raised.
    """
    if argument is None:
        argument = {}
    sort = argument.get('key', DEFAULT_SORT)
    if isinstance(sort, str):
        sort = [sort]
    try:
        songlist = process_content(argument.get('content'), config)
    except OnlySongsError as error:
        raise ContentError(keyword, (
            "Content list of this keyword can be only songs (or content "
            "that result into songs), and the following are not:" +
            str(error.not_songs)
            ))
    return sorted(songlist, key=key_generator(sort))
Example #6
0
    def write_tex(self, output):
        """Build the '.tex' file corresponding to self.

        Arguments:
        - output: a file object, in which the file will be written.
        """
        # Updating configuration
        config = DEFAULT_CONFIG
        config.update(self.config)
        renderer = TexRenderer(
                config['template'],
                config['datadir'],
                config['lang'],
                )
        config.update(self.config)
        config.update(renderer.get_variables())

        config['authwords'] = authors.compile_authwords(config['authwords'])

        self.config = config
        # Configuration set

        self.contentlist = content.process_content(
                self.config.get('content', []),
                self.config,
                )
        self.config['render_content'] = content.render_content
        self.config['titleprefixkeys'] = ["after", "sep", "ignore"]
        self.config['content'] = self.contentlist
        self.config['filename'] = output.name[:-4]

        renderer.render_tex(output, self.config)
Example #7
0
def parse(keyword, config, argument, contentlist):
    """Return a sorted list of songs contained in 'contentlist'.

    Arguments:
        - keyword: the string 'sorted';
        - config: the current songbook configuration dictionary;
        - argument: the list of the fields used to sort songs, as strings
          separated by commas (e.g. "by, album, @title");
        - contentlist: the list of content to be sorted. If this content
          contain something else than a song, an exception is raised.
    """
    if argument:
        sort = [key.strip() for key in argument.split(",")]
    else:
        sort = DEFAULT_SORT
    try:
        songlist = process_content(contentlist, config)
    except OnlySongsError as error:
        return EmptyContentList(
            errors=[
                ContentError(
                    keyword,
                    (
                        "Content list of this keyword can be only songs (or content "
                        "that result into songs), and the following are not:" + str(error.not_songs)
                    ),
                )
            ]
        )
    return sorted(songlist, key=key_generator(sort))
Example #8
0
    def write_tex(self, output):
        """Build the '.tex' file corresponding to self.

        Arguments:
        - output: a file object, in which the file will be written.
        """
        # Updating configuration
        self._config = self._raw_config.copy()
        renderer = TexBookRenderer(
            self._config['book']['template'],
            self._config['_datadir'],
            self._config['book']['lang'],
            self._config['book']['encoding'],
            )

        try:
            self._config['_template'] = renderer.get_all_variables(self._config.get('template', {}))
        except errors.SchemaError as exception:
            exception.message = "The songbook file '{}' is not valid\n{}".format(
                self.basename, exception.message)
            raise exception

        self._config['_compiled_authwords'] = authors.compile_authwords(
            copy.deepcopy(self._config['authors'])
            )

        # Loading custom plugins
        self._config['_content_plugins'] = files.load_plugins(
            datadirs=self._config['_datadir'],
            root_modules=['content'],
            keyword='CONTENT_PLUGINS',
            )
        self._config['_song_plugins'] = files.load_plugins(
            datadirs=self._config['_datadir'],
            root_modules=['songs'],
            keyword='SONG_RENDERERS',
            )['tsg']

        # Configuration set
        self._config['render'] = content.render
        self._config['content'] = content.process_content(
            self._config.get('content', []),
            self._config,
            )
        self._config['filename'] = output.name[:-4]

        self._config['_bookoptions'] = iter_bookoptions(self._config)

        renderer.render_tex(output, self._config)

        # Get all errors, and maybe exit program
        self._errors.extend(renderer.errors)
        if self._config['_error'] == "failonbook":
            if self.has_errors():
                raise errors.SongbookError("Some songs contain errors. Stopping as requested.")
Example #9
0
 def get_content_items(self):
     """Return: a list of ContentItem objects, corresponding to the content to be
     included in the .tex file.
     """
     content_config = self._raw_config.copy()
     # Updates the '_langs' key
     content_items = content.process_content(
         content_config.get('content', []),
         content_config,
         )
     content_langs = content_config['_langs']
     return content_langs, content_items
Example #10
0
 def get_content_items(self):
     """Return: a list of ContentItem objects, corresponding to the content to be
     included in the .tex file.
     """
     content_config = self._raw_config.copy()
     # Updates the '_langs' key
     content_items = content.process_content(
         content_config.get('content', []),
         content_config,
         )
     content_langs = content_config['_langs']
     return content_langs, content_items
Example #11
0
def process_songs(content, config=None):
    """Process content that containt only songs.

    Call patacrep.content.process_content(), checks if the returned list
    contains only songs, and raise an exception if not.
    """
    contentlist = process_content(content, config)
    not_songs = [
        item for item in contentlist if not isinstance(item, SongRenderer)
    ]
    if not_songs:
        raise OnlySongsError(not_songs)
    return contentlist
Example #12
0
def process_songs(content, config=None):
    """Process content that containt only songs.

    Call patacrep.content.process_content(), checks if the returned list
    contains only songs, and raise an exception if not.
    """
    contentlist = process_content(content, config)
    not_songs = [
        item
        for item
        in contentlist
        if not isinstance(item, SongRenderer)
        ]
    if not_songs:
        raise OnlySongsError(not_songs)
    return contentlist
Example #13
0
    def write_tex(self, output):
        """Build the '.tex' file corresponding to self.

        Arguments:
        - output: a file object, in which the file will be written.
        """
        # Updating configuration
        self._config = self._raw_config.copy()
        renderer = TexBookRenderer(
            self._config['book']['template'],
            self._config['_datadir'],
            self._config['book']['lang'],
            self._config['book']['encoding'],
        )

        try:
            self._config['_template'] = renderer.get_all_variables(
                self._config.get('template', {}))
        except errors.SchemaError as exception:
            exception.message = "The songbook file '{}' is not valid\n{}".format(
                self.basename, exception.message)
            raise exception

        self._config['_compiled_authwords'] = authors.compile_authwords(
            copy.deepcopy(self._config['authors']))

        # Configuration set
        self._config['render'] = content.render
        self._config['content'] = content.process_content(
            self._config.get('content', []),
            self._config,
        )
        self._config['filename'] = output.name[:-4]

        # Processing special options
        self._config['_bookoptions'] = iter_bookoptions(self._config)
        self._config['chords']['_notenames'] = self._get_chord_names(
            self._config['chords']['notation'])

        renderer.render_tex(output, self._config)

        # Get all errors, and maybe exit program
        self._errors.extend(renderer.errors)
        if self._config['_error'] == "failonbook":
            if self.has_errors():
                raise errors.SongbookError(
                    "Some songs contain errors. Stopping as requested.")
Example #14
0
        def test_content(self):
            """Test that `base.source` produces the correct file list"""
            sourcename = "{}.source".format(base)
            with open(sourcename, mode="r", encoding="utf8") as sourcefile:
                sbcontent = json.load(sourcefile)

            with logging_reduced('patacrep.content.song'):
                expandedlist = content.process_content(sbcontent, cls.config.copy())
            sourcelist = [cls._clean_path(elem) for elem in expandedlist]

            controlname = "{}.control".format(base)
            if not os.path.exists(controlname):
                raise Exception("Missing control:" + str(sourcelist).replace("'", '"'))
            with open(controlname, mode="r", encoding="utf8") as controlfile:
                controllist = json.load(controlfile)

            self.assertEqual(controllist, sourcelist)
Example #15
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 #16
0
        def test_content(self):
            """Test that `base.source` produces the correct file list"""
            sourcename = "{}.source".format(base)
            with open(sourcename, mode="r", encoding="utf8") as sourcefile:
                sbcontent = yaml.safe_load(sourcefile)

            outputdir = os.path.dirname(base)
            config = cls._generate_config(sbcontent, outputdir, base)

            with logging_reduced('patacrep.content.song'):
                expandedlist = content.process_content(sbcontent, config)
            sourcelist = [cls._clean_path(elem.to_dict()) for elem in expandedlist]

            controlname = "{}.control".format(base)
            if not os.path.exists(controlname):
                raise Exception("Missing control:" + str(controlname).replace("'", '"'))
            with open(controlname, mode="r", encoding="utf8") as controlfile:
                controllist = yaml.safe_load(controlfile)

            self.assertEqual(controllist, sourcelist)
Example #17
0
def parse(keyword, config, argument):
    """Return a list of songs, whith a different base path.

    Arguments:
    - keyword: unused;
    - config: the current songbook configuration dictionary;
    - argument: a dict containing:
        path: string specifying the path to append to current songdirs;
        content: songbook content, that is parsed by
            patacrep.content.process_content().

    The 'path' is added as a relative path to every path already present
    in config['songdir'] (which are 'songs' dir inside the datadirs).
    """
    subpath = argument['path']
    old_songdir = config['_songdir']

    config['_songdir'] = [path.clone().join(subpath) for path in config['_songdir']]

    processed_content = process_content(argument.get('content'), config)
    config['_songdir'] = old_songdir
    return processed_content
Example #18
0
        def test_content(self):
            """Test that `base.source` produces the correct file list"""
            sourcename = "{}.source".format(base)
            with open(sourcename, mode="r", encoding="utf8") as sourcefile:
                sbcontent = yaml.load(sourcefile)

            outputdir = os.path.dirname(base)
            config = cls._generate_config(sbcontent, outputdir, base)

            with logging_reduced('patacrep.content.song'):
                expandedlist = content.process_content(sbcontent, config)
            sourcelist = [cls._clean_path(elem) for elem in expandedlist]

            controlname = "{}.control".format(base)
            if not os.path.exists(controlname):
                raise Exception("Missing control:" + str(sourcelist).replace("'", '"'))
            with open(controlname, mode="r", encoding="utf8") as controlfile:
                controllist = [
                    elem.replace("@TEST_FOLDER@", files.path2posix(resource_filename(__name__, "")))
                    for elem in yaml.load(controlfile)
                    ]

            self.assertEqual(controllist, sourcelist)
Example #19
0
    def write_tex(self, output):
        """Build the '.tex' file corresponding to self.

        Arguments:
        - output: a file object, in which the file will be written.
        """
        # Updating configuration
        self._config = DEFAULT_CONFIG.copy()
        self._config.update(self._raw_config)
        renderer = TexBookRenderer(
            self._config["template"], self._config["datadir"], self._config["lang"], self._config["encoding"]
        )
        self._config.update(renderer.get_variables())
        self._config.update(self._raw_config)

        self._config["_compiled_authwords"] = authors.compile_authwords(copy.deepcopy(self._config["authwords"]))

        # Loading custom plugins
        self._config["_content_plugins"] = files.load_plugins(
            datadirs=self._config.get("datadir", []), root_modules=["content"], keyword="CONTENT_PLUGINS"
        )
        self._config["_song_plugins"] = files.load_plugins(
            datadirs=self._config.get("datadir", []), root_modules=["songs"], keyword="SONG_RENDERERS"
        )["tsg"]

        # Configuration set
        self._config["render"] = content.render
        self._config["content"] = content.process_content(self._config.get("content", []), self._config)
        self._config["filename"] = output.name[:-4]

        renderer.render_tex(output, self._config)

        # Get all errors, and maybe exit program
        self._errors.extend(renderer.errors)
        if self.config["_error"] == "failonbook":
            if self.has_errors():
                raise errors.SongbookError("Some songs contain errors. Stopping as requested.")
Example #20
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