Refactor bibtex to make better use of bibtexparser

This commit is contained in:
Lucas Verney 2016-02-07 15:45:17 +01:00
parent 0ae4894360
commit b2dbe2b8f9
1 changed files with 40 additions and 35 deletions

View File

@ -1,12 +1,11 @@
""" """
This file contains functions to deal with Bibtex files and edit them. This file contains functions to deal with Bibtex files and edit them.
TODO: Unittests + use bibtexparser writer TODO: Unittests
""" """
import bibtexparser import bibtexparser
import re import re
from codecs import open
from libbmc import tools from libbmc import tools
@ -19,7 +18,7 @@ def dict2BibTeX(data):
Convert a single BibTeX entry dict to a BibTeX string. Convert a single BibTeX entry dict to a BibTeX string.
:param data: A dict representing BibTeX entry, as the ones from \ :param data: A dict representing BibTeX entry, as the ones from \
``bibtexparser`` output. ``bibtexparser.BibDatabase.entries`` output.
:return: A formatted BibTeX string. :return: A formatted BibTeX string.
""" """
bibtex = '@' + data['ENTRYTYPE'] + '{' + data['ID'] + ",\n" bibtex = '@' + data['ENTRYTYPE'] + '{' + data['ID'] + ",\n"
@ -30,17 +29,25 @@ def dict2BibTeX(data):
return bibtex return bibtex
def BibDatabase2BibTeX(data):
"""
Convert a BibDatabase object to a BibTeX string.
:param data: A ``bibtexparser.BibDatabase`` object.
:return: A formatted BibTeX string.
"""
return bibtexparser.dumps(data)
def write(filename, data): def write(filename, data):
""" """
Create a new BibTeX file. Create a new BibTeX file.
:param filename: The name of the BibTeX file to write. :param filename: The name of the BibTeX file to write.
:param data: A list of dict representing BibTeX entries, as the ones from \ :param data: A ``bibtexparser.BibDatabase`` object.
``bibtexparser`` output.
""" """
bibtex = "\n".join([dict2BibTeX(i) for i in data]) with open(filename, 'w') as fh:
with open(filename, 'w', encoding='utf-8') as fh: fh.write(BibDatabase2BibTeX(data))
fh.write(bibtex)
def append(filename, data): def append(filename, data):
@ -48,11 +55,10 @@ def append(filename, data):
Append some entries to a bibtex file. Append some entries to a bibtex file.
:param filename: The name of the BibTeX file to edit. :param filename: The name of the BibTeX file to edit.
:param data: A list of dict representing BibTeX entries, as the ones from \ :param data: A ``bibtexparser.BibDatabase`` object.
``bibtexparser`` output.
""" """
with open(filename, 'a', encoding="utf-8") as fh: with open(filename, 'a') as fh:
fh.write("\n".join([dict2BibTeX(i) for i in data])) fh.write(BibDatabase2BibTeX(data))
def edit(filename, identifier, data): def edit(filename, identifier, data):
@ -65,13 +71,12 @@ def edit(filename, identifier, data):
in the BibTeX file but not in this dict will be kept as is. in the BibTeX file but not in this dict will be kept as is.
""" """
# Get current bibtex # Get current bibtex
with open(filename, 'r', encoding="utf-8") as fh: with open(filename, 'r') as fh:
bibtex = bibtexparser.load(fh) bibtex = bibtexparser.load(fh)
bibtex = bibtex.entries_dict
# Update it # Update it
for k in data: for k in data:
bibtex[identifier][k] = data[k] bibtex.entries_dict[identifier][k] = data[k]
# Write the resulting BibTeX # Write the resulting BibTeX
write(filename, bibtex) write(filename, bibtex)
@ -83,16 +88,15 @@ def replace(filename, identifier, data):
:param filename: The name of the BibTeX file to edit. :param filename: The name of the BibTeX file to edit.
:param identifier: The id of the entry to replace, in the BibTeX file. :param identifier: The id of the entry to replace, in the BibTeX file.
:param data: A dict representing a BibTeX entry, as the one from \ :param data: A ``bibtexparser.BibDatabase`` object containing a single \
``bibtexparser`` output. entry.
""" """
# Get current bibtex # Get current bibtex
with open(filename, 'r', encoding="utf-8") as fh: with open(filename, 'r') as fh:
bibtex = bibtexparser.load(fh) bibtex = bibtexparser.load(fh)
bibtex = bibtex.entries_dict
# Update the bibtex # Use entries_dict representation to update easily
bibtex[identifier] = data bibtex.entries_dict[identifier] = data.entries[0]
# Write the resulting BibTeX # Write the resulting BibTeX
write(filename, bibtex) write(filename, bibtex)
@ -106,13 +110,12 @@ def delete(filename, identifier):
:param identifier: The id of the entry to delete, in the BibTeX file. :param identifier: The id of the entry to delete, in the BibTeX file.
""" """
# Get current bibtex # Get current bibtex
with open(filename, 'r', encoding="utf-8") as fh: with open(filename, 'r') as fh:
bibtex = bibtexparser.load(fh) bibtex = bibtexparser.load(fh)
bibtex = bibtex.entries_dict
# Delete the bibtex entry # Delete the bibtex entry
try: try:
del(bibtex[identifier]) del(bibtex.entries_dict[identifier])
except KeyError: except KeyError:
pass pass
@ -128,17 +131,17 @@ def get(filename, ignore_fields=[]):
:param ignore_fields: An optional list of fields to strip from the BibTeX \ :param ignore_fields: An optional list of fields to strip from the BibTeX \
file. file.
:returns: A list of ``bibtexparser`` dicts representing the fetched \ :returns: A ``bibtexparser.BibDatabase`` object representing the fetched \
entries. entries.
""" """
# Open bibtex file # Open bibtex file
with open(filename, 'r', encoding="utf-8") as fh: with open(filename, 'r') as fh:
bibtex = bibtexparser.load(fh) bibtex = bibtexparser.load(fh)
bibtex = bibtex.entries_dict
# Clean the entry dict if necessary # Clean the entry dict if necessary
bibtex = [{k: entry[k] for k in entry if k not in ignore_fields} bibtex.entries_dict = [{k: entry[k]
for entry in bibtex] for k in entry if k not in ignore_fields}
for entry in bibtex.entries_dict]
return bibtex return bibtex
@ -157,14 +160,13 @@ def get_entry_by_filter(filename, filter, ignore_fields=[]):
first matching entry. ``None`` if entry was not found. first matching entry. ``None`` if entry was not found.
""" """
# Open bibtex file # Open bibtex file
with open(filename, 'r', encoding="utf-8") as fh: with open(filename, 'r') as fh:
bibtex = bibtexparser.load(fh) bibtex = bibtexparser.load(fh)
bibtex = bibtex.entries
matching_entry = None matching_entry = None
try: try:
# Try to fetch the matching entry dict # Try to fetch the matching entry dict
for entry in bibtex.items: for entry in bibtex.entries.items:
if filter(entry): if filter(entry):
matching_entry = entry matching_entry = entry
except KeyError: except KeyError:
@ -175,7 +177,9 @@ def get_entry_by_filter(filename, filter, ignore_fields=[]):
matching_entry = {k: matching_entry[k] matching_entry = {k: matching_entry[k]
for k in matching_entry if k not in ignore_fields} for k in matching_entry if k not in ignore_fields}
return matching_entry bib_db = bibtexparser.bibdatabase.BibDatabase()
bib_db.entries = [matching_entry]
return bib_db
def get_entry(filename, identifier, ignore_fields=[]): def get_entry(filename, identifier, ignore_fields=[]):
@ -212,12 +216,13 @@ def to_filename(bibtex, mask=default_papers_filename_mask):
Filename is slugified after applying the masks. Filename is slugified after applying the masks.
:param bibtex: A dict representing a BibTeX entry, as the one from \ :param bibtex: A ``bibtexparser.BibDatabase`` object representing a \
``bibtexparser`` output. BibTeX entry, as the one from ``bibtexparser`` output.
:param mask: A Python format string. :param mask: A Python format string.
:returns: A formatted filename. :returns: A formatted filename.
""" """
bibtex = bibtex.entries[0]
authors = re.split(' and ', bibtex['author']) authors = re.split(' and ', bibtex['author'])
filename = mask filename = mask