Moves to using bibtexparser's writer for bibdata. [Fixes #33]

main
Olivier Mangin 7 years ago
parent 14440c5e4c
commit 07be993d02

@ -53,9 +53,10 @@ def customizations(record):
return record return record
bibfield_order = ['author', 'title', 'journal', 'institution', 'publisher', bibfield_order = ['author', 'title', 'journal', 'institution', 'publisher',
'year', 'month', 'number', 'volume', 'pages', 'link', 'doi', 'note', 'year', 'month', 'number', 'volume', 'pages', 'link', 'doi',
'abstract'] 'note', 'abstract']
class EnDecoder(object): class EnDecoder(object):
@ -69,6 +70,9 @@ class EnDecoder(object):
* encode_bibdata will try to recognize exceptions * encode_bibdata will try to recognize exceptions
""" """
bwriter = bp.bwriter.BibTexWriter()
bwriter.display_order = bibfield_order
def encode_metadata(self, metadata): def encode_metadata(self, metadata):
return yaml.safe_dump(metadata, allow_unicode=True, return yaml.safe_dump(metadata, allow_unicode=True,
encoding=None, indent=4) encoding=None, indent=4)
@ -76,41 +80,35 @@ class EnDecoder(object):
def decode_metadata(self, metadata_raw): def decode_metadata(self, metadata_raw):
return yaml.safe_load(metadata_raw) return yaml.safe_load(metadata_raw)
def encode_bibdata(self, bibdata): def encode_bibdata(self, bibdata, ignore_fields=[]):
"""Encode bibdata """ """Encode bibdata """
return '\n'.join(self._encode_bibentry(citekey, entry) bpdata = bp.bibdatabase.BibDatabase()
for citekey, entry in bibdata.items()) bpdata.entries = [self._entry_to_bp_entry(k, copy.copy(bibdata[k]),
ignore_fields=ignore_fields)
@staticmethod for k in bibdata]
def _encode_field(key, value): return self.bwriter.write(bpdata)
if key == 'link':
return ', '.join(link['url'] for link in value) def _entry_to_bp_entry(self, key, entry, ignore_fields=[]):
elif key == 'author': """Convert back entries to the format expected by bibtexparser."""
return ' and '.join(author for author in value) entry[BP_ID_KEY] = key
elif key == 'editor': # Convert internal 'type' to bibtexparser entrytype key
return ' and '.join(editor['name'] for editor in value) entry[BP_ENTRYTYPE_KEY] = entry.pop(TYPE_KEY)
elif key == 'journal': for f in ignore_fields:
return value['name'] entry.pop(f, None)
elif key == 'keyword': if 'link' in entry:
return ', '.join(keyword for keyword in value) entry['link'] = ', '.join(link['url'] for link in entry['link'])
else: if 'author' in entry:
return value entry['author'] = ' and '.join(
author for author in entry['author'])
@staticmethod if 'editor' in entry:
def _encode_bibentry(citekey, bibentry): entry['editor'] = ' and '.join(
bibraw = '@{}{{{},\n'.format(bibentry[TYPE_KEY], citekey) editor['name'] for editor in entry['editor'])
bibentry = copy.copy(bibentry) if 'journal' in entry:
for key in bibfield_order: entry['journal'] = entry['journal']['name']
if key in bibentry: if 'keyword' in entry:
value = bibentry.pop(key) entry['keyword'] = ', '.join(
bibraw += ' {} = {{{}}},\n'.format( keyword for keyword in entry['keyword'])
key, EnDecoder._encode_field(key, value)) return entry
for key, value in bibentry.items():
if key != TYPE_KEY:
bibraw += ' {} = {{{}}},\n'.format(
key, EnDecoder._encode_field(key, value))
bibraw += '}\n'
return bibraw
def decode_bibdata(self, bibdata): def decode_bibdata(self, bibdata):
"""""" """"""

@ -91,13 +91,41 @@ class TestEnDecode(unittest.TestCase):
self.assertIn(u'keyword', entry) self.assertIn(u'keyword', entry)
self.assertEqual(set(keywords), set(entry[u'keyword'])) self.assertEqual(set(keywords), set(entry[u'keyword']))
def test_endecode_metadata(self): def test_endecode_metadata(self):
decoder = endecoder.EnDecoder() decoder = endecoder.EnDecoder()
entry = decoder.decode_metadata(metadata_raw0) entry = decoder.decode_metadata(metadata_raw0)
metadata_output0 = decoder.encode_metadata(entry) metadata_output0 = decoder.encode_metadata(entry)
self.assertEqual(set(metadata_raw0.split('\n')), set(metadata_output0.split('\n'))) self.assertEqual(set(metadata_raw0.split('\n')), set(metadata_output0.split('\n')))
def test_endecode_bibtex_field_order(self):
decoder = endecoder.EnDecoder()
entry = decoder.decode_bibdata(bibtex_raw0)
lines = decoder.encode_bibdata(entry).splitlines()
self.assertEqual(lines[1].split('=')[0].strip(), u'author')
self.assertEqual(lines[2].split('=')[0].strip(), u'title')
self.assertEqual(lines[3].split('=')[0].strip(), u'institution')
self.assertEqual(lines[4].split('=')[0].strip(), u'publisher')
self.assertEqual(lines[5].split('=')[0].strip(), u'year')
self.assertEqual(lines[6].split('=')[0].strip(), u'month')
self.assertEqual(lines[7].split('=')[0].strip(), u'number')
self.assertEqual(lines[8].split('=')[0].strip(), u'link')
self.assertEqual(lines[9].split('=')[0].strip(), u'note')
self.assertEqual(lines[10].split('=')[0].strip(), u'abstract')
def test_endecode_bibtex_ignores_fields(self):
decoder = endecoder.EnDecoder()
entry = decoder.decode_bibdata(bibtex_raw0)
bibraw1 = decoder.encode_bibdata(
entry, ignore_fields=['title', 'note', 'abstract', 'journal'])
entry1 = list(decoder.decode_bibdata(bibraw1).values())[0]
self.assertNotIn('title', entry1)
self.assertNotIn('note', entry1)
self.assertNotIn('abtract', entry1)
self.assertIn('author', entry1)
self.assertIn('institution', entry1)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

Loading…
Cancel
Save