Exemple #1
0
 def to_snippet(self, style):
     if style == '':
         self.errors = 'No style specified'
         return None
     try:
         style_file = os.path.join(style_folder, style)
         bib_style = citeproc.CitationStylesStyle(style=style_file,
                                                  validate=False)
     except AttributeError:
         self.errors = 'The style "{style}" is not available'.format(
             style=style)
         return None
     except lxml.etree.XMLSyntaxError:
         self.errors = 'The style "{style}" could not be processed'.format(
             style=style)
         return None
     bib_source = citeproc.source.BibliographySource()
     bib_source.add(self)
     bibliography = citeproc.CitationStylesBibliography(
         bib_style, bib_source, citeproc.formatter.plain)
     citation = citeproc.Citation([citeproc.CitationItem('refkey')])
     bibliography.register(citation)
     if len(bibliography.bibliography()) > 0:
         snippet = str(bibliography.bibliography()[0])
     else:
         snippet = None
     return snippet
Exemple #2
0
    def apply(self):
        # Get the document biblio database
        biblio = self.document.settings.biblio

        # Get the citation keys
        raw_cit = self.startnode.details['raw_citation']
        keys = raw_cit.split(';')

        def link_format(key):
            return 'bib-' + key.lower()

        # Create a citation and register it
        def mkitem(key):
            return citeproc.CitationItem(key,
                                         prefix='`',
                                         suffix=' <#%s>`_' % link_format(key))

        cit = citeproc.Citation([mkitem(key) for key in keys])
        biblio.register(cit)

        # Create a new pending for the second transform
        pending = docutils.nodes.pending(CitationSecondTransform)
        pending.details['raw_citation'] = raw_cit
        pending.details['citation'] = cit
        pending.details['biblio'] = biblio
        self.document.note_pending(pending)

        self.startnode.replace_self(pending)
Exemple #3
0
def process_dom(dom, biblio, citation_separator=';', sort_order='alpha',
                link_format=lambda x: x.lower()):
    '''
    :param xml.dom.Document dom:   Source DOM document.
    :param str citation_separator: Separator delimiting multiple citations
                                   in a single <citation/> element.
    '''
    # Search all citations and their keys
    cit_nodes = [(n.childNodes[0].data.lower().split(citation_separator),n)
                 for n in dom.getElementsByTagNameNS(docbook_ns, 'citation') 
                 if len(n.childNodes) == 1
                    and n.childNodes[0].nodeType == n.TEXT_NODE]

    # Create the citations
    cits = []
    for (keys,n) in cit_nodes:
        def mkitem(key):
            return citeproc.CitationItem(key,
                     prefix='<link linkend="%s">'%(link_format(key)),
                     suffix='</link>')
        cit = citeproc.Citation([mkitem(key) for key in keys])
        biblio.register(cit)
        cits.append(cit)

    # Print the citations
    def warn(cit_item):
        print('warning: citation reference not found for', cit_item.key)
    for ((keys,n),cit) in zip(cit_nodes,cits):
        txt = str(biblio.cite(cit,warn))
        cit_dom = xml.dom.minidom.parseString('<para>%s</para>'%txt)
        # Remove all previous <citation/> children
        for node in n.childNodes:
            n.removeChild(node)
        # Add the new children
        cit_root = cit_dom.documentElement
        while cit_root.hasChildNodes():
            n.appendChild(cit_root.firstChild)

    # Fill the existing bibliography node
    # TODO: add support for per-section bibliographies
    for bib_node in dom.getElementsByTagNameNS(docbook_ns, 'bibliography'):
        # Only keep the bibliography title
        # TODO: specify which nodes to keep
        for node in bib_node.childNodes:
            if node.nodeType == node.ELEMENT_NODE:
                if node.tagName != 'title':
                    bib_node.removeChild(node)
        # Add the bibliography entries
        bib_entries = list(zip(biblio.items,biblio.bibliography()))
        if sort_order == 'alpha':
            bib_entries.sort(key=lambda x: x[0].key)
        # TODO add support for raw entries
        for (itm,bibitem) in bib_entries:
            itemdom = xml.dom.minidom.parseString('<bibliomixed xml:id="%s">%s</bibliomixed>'%(link_format(itm.key),str(bibitem)))
            bib_node.appendChild(itemdom.documentElement)
        # Only process one bibliography element
        break
Exemple #4
0
def format_bibtex(bibtex_entry, style='harvard1'):
    try:
        from citeproc.source.bibtex import BibTeX as cpBibTeX
        import citeproc as cp
    except ImportError as e:
        raise RuntimeError(
            "For formatted output we need citeproc and all of its dependencies "
            "(such as lxml) but there is a problem while importing citeproc: %s"
            % str(e))
    key = bibtex_entry.get_key()
    # need to save it temporarily to use citeproc-py
    fname = tempfile.mktemp(suffix='.bib')
    try:
        with open(fname, 'wt') as f:
            bibtex = bibtex_entry.rawentry
            bibtex = bibtex.replace(u'\u2013', '--') + "\n"
            # TODO: manage to save/use UTF-8
            if PY2:
                bibtex = bibtex.encode('ascii', 'ignore')
            f.write(bibtex)
        # We need to avoid cpBibTex spitting out warnings
        old_filters = warnings.filters[:]  # store a copy of filters
        warnings.simplefilter('ignore', UserWarning)
        try:
            bib_source = cpBibTeX(fname)
        except Exception as e:
            lgr.error("Failed to process BibTeX file %s: %s" % (fname, e))
            return "ERRORED: %s" % str(e)
        finally:
            # return warnings back
            warnings.filters = old_filters
        bib_style = cp.CitationStylesStyle(style, validate=False)
        # TODO: specify which tags of formatter we want
        bibliography = cp.CitationStylesBibliography(bib_style, bib_source,
                                                     cp.formatter.plain)
        citation = cp.Citation([cp.CitationItem(key)])
        bibliography.register(citation)
    finally:
        if not os.environ.get("DUECREDIT_KEEPTEMP"):
            os.unlink(fname)

    biblio_out = bibliography.bibliography()
    assert(len(biblio_out) == 1)
    biblio_out = ''.join(biblio_out[0])
    return biblio_out # if biblio_out else str(bibtex_entry)
    def preprocess_cell(self, cell, resources, index):
        """
        Preprocess cell

        Parameters
        ----------
        cell : NotebookNode cell
            Notebook cell being processed
        resources : dictionary
            Additional resources used in the conversion process.  Allows
            preprocessors to pass variables into the Jinja engine.
        cell_index : int
            Index of the cell being processed (see base.py)
        """

        if cell.cell_type == "markdown":
            replaced = None
            if "html" in resources["output_extension"]:
                replaced = cell.source
                for citation in re.finditer('<cite data-cite=\\"(.*?)\\"></cite>', cell.source):
                    tempcite = citeproc.Citation([citeproc.CitationItem(citation.groups()[0])])
                    self.bibliography.register(tempcite)
                    replaced = re.sub('<cite data-cite=\\"'+citation.groups()[0]+'\\"></cite>', '<a href="#'+tempcite['cites'][0]["key"]+'">'+str(self.bibliography.cite(tempcite, cite_warn))+'</a>', replaced)
            if "<div class=\"cite2c-biblio\"></div>" in cell.source:
                if "html" in resources["output_extension"]:
                    html_bibliography = '<h2 id="bibliography">Bibliography</h2>'
                    for item, key in zip(self.bibliography.bibliography(), self.bibliography.keys):
                        html_bibliography += '<p id="'+key+'">'
                        html_bibliography += str(item)
                        html_bibliography += '</p>\n'
                    replaced = re.sub("<div class=\"cite2c-biblio\"></div>", html_bibliography, cell.source)
                elif "tex" in resources["output_extension"]:
                    replaced = re.sub("<div class=\"cite2c-biblio\"></div>", r"\\bibliography{"+resources["output_files_dir"]+"/"+resources["unique_key"]+r"} \n ", cell.source)
            if replaced:
                cell.source = replaced
        return cell, resources
def add_publications(generator):
    """
    Populates context with a list of BibTeX publications.

    Configuration
    -------------
    generator.settings['PUBLICATIONS_SRC']:
        local path to the BibTeX file to read.

    Output
    ------
    generator.context['publications']:
        List of tuples (key, entry, record, external).
        See Readme.md for more details.
    """

    if "PUBLICATIONS_SRC" not in generator.settings:
        return
    if "PUBLICATIONS_STYLE" not in generator.settings:
        return

    refs_file = generator.settings["PUBLICATIONS_SRC"]
    refs_style = generator.settings["PUBLICATIONS_STYLE"]
    refs_sort = generator.settings.get("PUBLICATIONS_SORT", "date")

    supress_warning = generator.settings.get(
        "PUBLICATIONS_SUPRESS_BIBTEX_WARNING", True)

    with open(refs_file, "r") as fp:
        bibtex_data = bibtexparser.load(fp)

    try:
        entries = sort_entries(bibtex_data.entries, refs_sort)
    except ValueError as e:
        logger.error("%s", e)
        return

    unknown_bib_field = "Unsupported BibTeX field"

    with warnings.catch_warnings(record=True) as w_list:
        citeproc_data = citeproc.source.bibtex.BibTeX(refs_file)
        for w in w_list:
            if supress_warning and unknown_bib_field in str(w.message):
                logger.info("Warning in citeproc-py '%s'", w.message)
            else:
                logger.warning("Warning in citeproc-py '%s'", w.message)

    citeproc_style = citeproc.CitationStylesStyle(refs_style, validate=False)

    if not citeproc_style.has_bibliography():
        logger.warning("Style '%s'  does not include a bibliography",
                       refs_style)
        return

    bibliography = citeproc.CitationStylesBibliography(citeproc_style,
                                                       citeproc_data,
                                                       citeproc.formatter.html)

    cite = {}

    for record in entries:
        key = record["ID"].lower()
        cite["key"] = citeproc.Citation([citeproc.CitationItem(key)])
        bibliography.register(cite["key"])

    for key in bibliography.keys:
        bibliography.cite(cite["key"], cite_warn)

    bibitems = {}
    for key, item in zip(bibliography.keys, bibliography.bibliography()):
        bibitems[key] = str(item)

    publications = []

    for record in entries:
        key = record["ID"].lower()
        entry = bibitems[key]
        external = {}
        if "eprinttype" in record and "eprint" in record:
            if record["eprinttype"] == "arxiv":
                if "eprintclass" in record:
                    external[
                        "ARXIV"] = "http://arxiv.org/abs/{eprintclass}/{eprint}".format(
                            **record)
                else:
                    external["ARXIV"] = "http://arxiv.org/abs/{eprint}".format(
                        **record)
        if "doi" in record and record["doi"] not in entry:
            external["DOI"] = record["doi"]

        publications.append((key, entry, record, external))
    generator.context["publications"] = publications
Exemple #7
0
def format_bibtex(bibtex_entry, style='harvard1'):
    try:
        from citeproc.source.bibtex import BibTeX as cpBibTeX
        import citeproc as cp
    except ImportError as e:
        raise RuntimeError(
            "For formatted output we need citeproc and all of its dependencies "
            "(such as lxml) but there is a problem while importing citeproc: %s"
            % str(e))
    decode_exceptions = UnicodeDecodeError
    try:
        from citeproc.source.bibtex.bibparse import BibTeXDecodeError
        decode_exceptions = (decode_exceptions, BibTeXDecodeError)
    except ImportError:
        # this version doesn't yet have this exception defined
        pass
    key = bibtex_entry.get_key()
    # need to save it temporarily to use citeproc-py
    fname = tempfile.mktemp(suffix='.bib')
    try:
        with open(fname, 'wb') as f:
            f.write(condition_bibtex(bibtex_entry.rawentry))
        # We need to avoid cpBibTex spitting out warnings
        old_filters = warnings.filters[:]  # store a copy of filters
        warnings.simplefilter('ignore', UserWarning)
        try:
            try:
                bib_source = cpBibTeX(fname)
            except decode_exceptions as e:
                # So .bib must be having UTF-8 characters.  With
                # a recent (not yet released past v0.3.0-68-g9800dad
                # we should be able to provide encoding argument
                bib_source = cpBibTeX(fname, encoding='utf-8')
        except Exception as e:
            lgr.error("Failed to process BibTeX file %s: %s" % (fname, e))
            return "ERRORED: %s" % str(e)
        finally:
            # return warnings back
            warnings.filters = old_filters
        bib_style = cp.CitationStylesStyle(style, validate=False)
        # TODO: specify which tags of formatter we want
        bibliography = cp.CitationStylesBibliography(bib_style, bib_source,
                                                     cp.formatter.plain)
        citation = cp.Citation([cp.CitationItem(key)])
        bibliography.register(citation)
    finally:
        if not os.environ.get("DUECREDIT_KEEPTEMP"):
            exceptions = (OSError, WindowsError) if on_windows else OSError
            for i in range(50):
                try:
                    os.unlink(fname)
                except exceptions:
                    if i < 49:
                        sleep(0.1)
                        continue
                    else:
                        raise
                break

    biblio_out = bibliography.bibliography()
    assert (len(biblio_out) == 1)
    biblio_out = ''.join(biblio_out[0])
    return biblio_out  # if biblio_out else str(bibtex_entry)
Exemple #8
0
    def run(self):
        #print('running the biblio directive', file=sys.stderr)
        #print('bibliography directive, content=', self.content, file=sys.stderr)

        # Get biblio database type
        db_type = 'bibtex'
        if 'mendeley' in self.options:
            db_type = 'mendeley'

        # Get biblio database
        if len(self.arguments) == 0:
            db_path = bibgen.default_database(db_type)
        else:
            db_path = self.arguments[0]

        # Make the biblio path relative to the source directory
        src_path = self.state.document.current_source
        if os.path.exists(src_path):
            src_dir = os.path.dirname(src_path)
            rel_path = os.path.join(src_dir, db_path)
            if os.path.exists(rel_path):
                db_path = rel_path

        # Other options
        hidden = 'hidden' in self.options
        style = self.options.get('style', 'harvard1')
        encoding = self.options.get('encoding', 'utf-8')
        sort = self.options.get('sort', 'alpha')

        # Open a biblio database for the document,
        # possibly replacing a command-line one.
        biblio = bibgen.open_bibliography(db_type, db_path, encoding, style,
                                          'rst')

        # Create citations for the content
        if len(self.content) > 0:
            for key in self.content:
                itm = citeproc.CitationItem(key)
                cit = citeproc.Citation([itm])
                biblio.register(cit)
        # Cite every bibliographic entry if asked
        elif 'all' in self.options:
            for key in biblio.source:
                itm = citeproc.CitationItem(key)
                cit = citeproc.Citation([itm])
                biblio.register(cit)
        # Only ibliography directives without content are citable
        else:
            self.state.document.settings.biblio = biblio

        pending = docutils.nodes.pending(BibliographyTransform)
        pending.details['biblio'] = biblio
        pending.details['hidden'] = hidden
        pending.details['sort'] = sort
        self.state.document.note_pending(pending)

        # The bibliography will be filled after the cite transforms
        node = docutils.nodes.section(classes=['bibliography'],
                                      names=['bibliography'],
                                      ids=['bibliography'])

        title = docutils.nodes.title('', 'Bibliography')
        node.setup_child(title)
        node += title

        node.setup_child(pending)
        node += pending

        return [node]