Пример #1
0
def bib(style_path,
        ds,
        return_cites_and_keys = False,
        formatter = "chocolate",
        apa_tweaks = True,
        # The below options are ignored unless apa_tweaks is on.
        always_include_issue = False,
        include_isbn = False,
        url_after_doi = False,
        publisher_website = True,
        abbreviate_given_names = True):

    if isinstance(formatter, str):
        try:             formatter = formatter_from_name[formatter]
        except KeyError: raise ValueError('Unknown formatter "{}"'.format(formatter))        

    style = get_style(style_path, apa_tweaks,
        include_isbn, url_after_doi, abbreviate_given_names)

    ds = deepcopy(ds)
    if apa_tweaks:
    # Distinguish entries that would have identical authors and years
    # by adding suffixes to the years.
        # Group works by author and year.
        #
        # (Actually, we use only an initial subset of authors,
        # the same number that would be included in an inline citation
        # after the first inline citation. This is 2 for 2 authors
        # and 1 otherwise.)
        ay = defaultdict(list)
        for d in ds:
            names = d.get('author') or d.get('editor')
            if len(names) != 2:
                names = [names[0]]
            k = repr(names)  + '/' + str(d['issued']['date-parts'][0][0])
            if not any(d is v for v in ay[k]):
                ay[k].append(d)
        # If any group has more than one element, add suffixes.
        for v in ay.values():
            if len(v) > 1:
                for i, d in enumerate(sorted(v, key = title_sort_key)):
                   d['year_suffix'] = ascii_lowercase[i]
    for d in ds:
        if 'id' not in d:
            d['id'] = str(random())
        for k in list(d.keys()):
            if d[k] is None: del d[k]
        if apa_tweaks:
            # By default, don't include the issue number for
            # journal articles.
            if not always_include_issue and d['type'] == 'article-journal':
                delf(d, 'issue')
            # Use the weird "Retrieved from Dewey, Cheatem, &
            # Howe website: http://example.com" format prescribed
            # for reports.
            if publisher_website and d['type'] == 'report' and 'publisher' in d and 'URL' in d:
                d['URL'] = '{} website: {}'.format(
                    d.pop('publisher'), d['URL'])
            # Add structure words for presentations and include
            # the event place.
            if d['type'] == 'speech' and d['genre'] == 'paper':
                d['event'] = 'meeting of the {}, {}'.format(
                    d.pop('publisher'), d['event-place'])
            if d['type'] == 'speech' and d['genre'] == 'video':
                d['medium'] = 'Video file'
                del d['genre']
            # Format encyclopedia entries like book chapters.
            if d['type'] == 'entry-encyclopedia':
                d['type'] = 'chapter'
            # When abbreviating given names, remove hyphens
            # preceding lowercase letters. Otherwise, weird
            # stuff happens.
            if abbreviate_given_names and 'author' in d:
               for a in d['author']:
                   if 'given' in a:
                       a['given'] = sub(
                           '-(.)',
                           lambda mo:
                               ("" if mo.group(1).islower() else "-") +
                               mo.group(1),
                           a['given'])

    bibliography = CitationStylesBibliography(
        style,
        CiteProcJSON(ds),
        formatter)
    cites = [ Citation([CitationItem(d['id'])]) for d in ds ]
    for c in cites: bibliography.register(c)
    def sort_key_f(item):
        ref = item.reference
        names = [(name['family'].lower(), name['given'][0].lower() if 'given' in name else '')
            for name in ref.get('author') or ref.get('editor')]
        return (names, ref['issued']['year'],
            title_sort_key(ref),
            ref['page']['first'] if 'page' in ref else '')
    if len(ds) > 1:
        # Sort the bibliography
        # bibliography.sort()   # Doesn't appear to handle leading "the"s correctly.
        bibliography.items = sorted(bibliography.items, key = sort_key_f)
        bibliography.keys = [item.key for item in bibliography.items]
    bibl = bibliography.bibliography()

    for i, s in enumerate(bibl):
        s = ''.join(s)
        # Fix spacing and punctuation issues.
        s = s.replace('  ', ' ')
        s = sub(r'([.!?…])\.', r'\1', s)
        if apa_tweaks:
            if formatter is citeproc.formatter.html or formatter is chocolate:
                # Italicize the stuff between a journal name and a volume
                # number.
                s = sub(r'</i>, <i>(\d)', r', \1', s)
                # Remove redundant periods that are separated
                # from the first end-of-sentence mark by an </i>
                # tag.
                s = sub(r'([.!?…]</i>)\.', r'\1', s)
            # If there are two authors and the first is a mononym,
            # remove the comma after it.
            s = sub('^([^.,]+), &', r'\1 &', s)
        bibl[i] = s

    if return_cites_and_keys:
        fcites = [bibliography.cite(c, lambda x: None) for c in cites]
        return (fcites, bibliography.keys, bibl)
    else:
        return bibl
Пример #2
0
def bib(style_path,
        ds,
        return_cites_and_keys = False,
        formatter = "chocolate",
        dumb_quotes = True,
          # Turning this off won't educate any straight quotes in
          # the data, but leaving it on will stupefy all the
          # smart quotes in the output.
        apa_tweaks = True,
        # The below options are ignored unless apa_tweaks is on.
        always_include_issue = False,
        include_isbn = False,
        url_after_doi = False,
        publisher_website = True,
        abbreviate_given_names = True):

    if isinstance(formatter, str):
        try:             formatter = formatter_from_name[formatter]
        except KeyError: raise ValueError('Unknown formatter "{}"'.format(formatter))        

    style = get_style(style_path, apa_tweaks,
        include_isbn, url_after_doi, abbreviate_given_names)

    ds = deepcopy(ds)
    if apa_tweaks:
    # Distinguish entries that would have identical authors and years
    # by adding suffixes to the years.
        # Group works by author and year.
        ay = defaultdict(list)
        for d in ds:
            k = repr(d.get('author') or d.get('editor'))  + '/' + str(d['issued']['date-parts'][0][0])
            if not any(d is v for v in ay[k]):
                ay[k].append(d)
        # If any group has more than one element, add suffixes.
        for v in ay.values():
            if len(v) > 1:
                for i, d in enumerate(sorted(v, key = title_sort_key)):
                   d['year_suffix'] = ascii_lowercase[i]
    for d in ds:
        if 'id' not in d:
            d['id'] = str(random())
        for k in list(d.keys()):
            if d[k] is None: del d[k]
        if apa_tweaks:
            # By default, don't include the issue number for
            # journal articles.
            if not always_include_issue and d['type'] == 'article-journal':
                delf(d, 'issue')
            # Use the weird "Retrieved from Dewey, Cheatem, &
            # Howe website: http://example.com" format prescribed
            # for reports.
            if publisher_website and d['type'] == 'report' and 'publisher' in d and 'URL' in d:
                d['URL'] = '{} website: {}'.format(
                    d.pop('publisher'), d['URL'])
            # Add structure words for presentations and include
            # the event place.
            if d['type'] == 'speech' and d['genre'] == 'paper':
                d['event'] = 'meeting of the {}, {}'.format(
                    d.pop('publisher'), d['event-place'])
            if d['type'] == 'speech' and d['genre'] == 'video':
                d['medium'] = 'Video file'
                del d['genre']
            # When abbreviating given names, remove hyphens
            # preceding lowercase letters. Otherwise, weird
            # stuff happens.
            if abbreviate_given_names and 'author' in d:
               for a in d['author']:
                   if 'given' in a:
                       a['given'] = sub(
                           '-(.)',
                           lambda mo:
                               ("" if mo.group(1).islower() else "-") +
                               mo.group(1),
                           a['given'])
            # Abbreviate a long list of authors with an ellipsis
            # and the final author.
            if 'author' in d and len(d['author']) > 7:
                d['author'] = (
                    d['author'][0:6] +
                    [{'given': '', 'family': '⣥<ellipsis>⣥'}] +
                    d['author'][-1:])

    bibliography = CitationStylesBibliography(
        style,
        {ref.key: ref for ref in parse_references(ds)},
        formatter)
    cites = [ Citation([CitationItem(d['id'])]) for d in ds ]
    for c in cites: bibliography.register(c)
    def sort_key_f(item):
        ref = item.reference
        names = [(name['family'].lower(), name['given'][0].lower() if 'given' in name else '')
            for name in ref.get('author') or ref.get('editor')
            if name.family != '⣥<ellipsis>⣥']
        return (names, ref['issued']['year'],
            title_sort_key(ref),
            ref['page']['first'] if 'page' in ref else '')
    if len(ds) > 1:
        # Sort the bibliography
        # bibliography.sort()   # Doesn't appear to handle leading "the"s correctly.
        bibliography.items = sorted(bibliography.items, key = sort_key_f)
        bibliography.keys = [item.key for item in bibliography.items]
    bibl = bibliography.bibliography()

    for i, s in enumerate(bibl):
        s = ''.join(s)
        # Fix spacing and punctuation issues.
        s = s.replace('  ', ' ')
        s = sub(r'([.!?…])\.', r'\1', s)
        if dumb_quotes:
            s = s.replace('‘', "'").replace('’', "'").replace('“', '"').replace('”', '"')
        if apa_tweaks:
            if formatter is citeproc.formatter.html or formatter is chocolate:
                # Italicize the stuff between a journal name and a volume
                # number.
                s = sub(r'</i>, <i>(\d)', r', \1', s)
            # Make "p." into "pp." when more than one page is cited.
            s = sub(r'(\W)p\. (\S+[,–])', r'\1pp. \2', s)
            # Replace the ellipsis placeholder.
            s = s.replace('⣥<ellipsis>⣥, ., &', '…')
        bibl[i] = s

    if return_cites_and_keys:
        fcites = [bibliography.cite(c, lambda x: None) for c in cites]
        return (fcites, bibliography.keys, bibl)
    else:
        return bibl