Improves behaviors related to bibtex decoding error.

- from editor input in add and edit commands,
- from files in import command.
main
Olivier Mangin 7 years ago
parent d8dc386a18
commit 8a7d143261
No known key found for this signature in database
GPG Key ID: D72FEC1C3120A884

@ -11,6 +11,7 @@ from .. import templates
from .. import apis
from .. import pretty
from .. import utils
from .. import endecoder
from ..completion import CommaSeparatedTagsCompletion
@ -57,12 +58,13 @@ def bibentry_from_editor(conf, ui, rp):
bibstruct.verify_bibdata(bibentry)
# REFACTOR Generate citykey
again = False
except ValueError:
except endecoder.EnDecoder.BibDecodingError:
again = ui.input_yn(
question='Invalid bibfile. Edit again ?',
question='Invalid bibfile. Edit again?',
default='y')
if not again:
ui.exit(0)
ui.exit()
return bibentry

@ -64,9 +64,14 @@ def command(conf, args):
'as `{}`.'.format(citekey, new_paper.citekey)))
else:
ui.info(('Paper `{}` was successfully edited.'.format(
citekey)))
citekey)))
break
except coder.BibDecodingError:
if not ui.input_yn(question="Error parsing bibdata. Edit again?"):
ui.error("Aborting, paper not updated.")
ui.exit()
except repo.CiteKeyCollision:
options = ['overwrite', 'edit again', 'abort']
choice = options[ui.input_choice(

@ -27,7 +27,7 @@ def parser(subparsers, conf):
return parser
def many_from_path(bibpath):
def many_from_path(ui, bibpath):
"""Extract list of papers found in bibliographic files in path.
The behavior is to:
@ -49,11 +49,17 @@ def many_from_path(bibpath):
biblist = []
for filepath in all_files:
biblist.append(coder.decode_bibdata(read_text_file(filepath)))
try:
biblist.append(coder.decode_bibdata(read_text_file(filepath)))
except coder.BibDecodingError:
ui.error("Could not parse bibtex at {}. Aborting import.".format(filepath))
ui.exit()
papers = {}
for b in biblist:
for k, b in b.items():
if k in papers:
ui.warning('Duplicated citekey {}. Keeping last.'.format(k))
try:
papers[k] = Paper(k, b)
papers[k].added = datetime.datetime.now()
@ -75,7 +81,7 @@ def command(conf, args):
rp = repo.Repository(conf)
# Extract papers from bib
papers = many_from_path(bibpath)
papers = many_from_path(ui, bibpath)
keys = args.keys or papers.keys()
for k in keys:
p = papers[k]

@ -66,6 +66,16 @@ class EnDecoder(object):
* encode_bibdata will try to recognize exceptions
"""
class BibDecodingError(Exception):
message = "Could not parse provided bibdata:\n---\n{}\n---"
def __init__(self, bibdata):
self.data = bibdata
def __str__(self):
return self.message.format(self.data)
bwriter = bp.bwriter.BibTexWriter()
bwriter.display_order = BIBFIELD_ORDER
@ -103,7 +113,10 @@ class EnDecoder(object):
return entry
def decode_bibdata(self, bibdata):
""""""
"""Decodes bibdata from string.
If the decoding fails, returns a BibParseError.
"""
try:
entries = bp.bparser.BibTexParser(
bibdata, common_strings=True,
@ -121,4 +134,5 @@ class EnDecoder(object):
except Exception:
import traceback
traceback.print_exc()
raise ValueError('could not parse provided bibdata:\n{}'.format(bibdata))
raise self.BibDecodingError(bibdata)
# TODO: filter exceptions from pyparsing and pass reason upstream

@ -104,6 +104,7 @@ class PrintUI(object):
self.exit()
return True # never happens
class InputUI(PrintUI):
"""UI class. Stores configuration parameters and system information.
"""
@ -118,7 +119,7 @@ class InputUI(PrintUI):
except EOFError:
self.error('Standard input ended while waiting for answer.')
self.exit(1)
return ustr(data) #.decode('utf-8')
return ustr(data) #.decode('utf-8')
def input_choice_ng(self, options, option_chars=None, default=None, question=''):
"""Ask the user to chose between a set of options. The user is asked

@ -32,7 +32,7 @@ class TestDOI2Bibtex(unittest.TestCase):
def test_parse_fails_on_incorrect_DOI(self):
bib = doi2bibtex('999999')
with self.assertRaises(ValueError):
with self.assertRaises(EnDecoder.BibDecodingError):
self.endecoder.decode_bibdata(bib)
@ -56,7 +56,7 @@ class TestISBN2Bibtex(unittest.TestCase):
def test_parse_fails_on_incorrect_ISBN(self):
bib = doi2bibtex('9' * 13)
with self.assertRaises(ValueError):
with self.assertRaises(EnDecoder.BibDecodingError):
self.endecoder.decode_bibdata(bib)

@ -147,6 +147,11 @@ class TestEnDecode(unittest.TestCase):
self.assertIn('author', entry1)
self.assertIn('institution', entry1)
def test_endecodes_raises_exception(self):
decoder = endecoder.EnDecoder()
with self.assertRaises(decoder.BibDecodingError):
decoder.decode_bibdata("@misc{I am not a correct bibtex{{}")
if __name__ == '__main__':
unittest.main()

@ -337,11 +337,20 @@ class TestAdd(URLContentTestCase):
def test_add_no_citekey_fails(self):
# See #113
cmds = ['pubs init',
('pubs add', [str_fixtures.bibtex_no_citekey]),
('pubs add', [str_fixtures.bibtex_no_citekey, 'n']),
]
with self.assertRaises(FakeSystemExit):
self.execute_cmds(cmds)
def test_add_edit_fails(self):
cmds = ['pubs init',
('pubs add',
['@misc{I am not a correct bibtex{{}', 'n']),
]
with self.assertRaises(FakeSystemExit) as cm:
self.execute_cmds(cmds)
self.assertEqual(cm.exception.code, 1)
class TestList(DataCommandTestCase):
@ -690,6 +699,32 @@ class TestUsecase(DataCommandTestCase):
]
self.execute_cmds(cmds)
def test_editor_succeeds_on_second_edit(self):
cmds = ['pubs init',
'pubs add data/pagerank.bib',
('pubs edit Page99', [
'', 'y',
'@misc{Page99, title="TTT", author="X. YY"}', '']),
('pubs list', [], '[Page99] YY, X. "TTT" \n')
]
self.execute_cmds(cmds)
def test_add_aborts(self):
with self.assertRaises(FakeSystemExit):
cmds = ['pubs init',
('pubs add New', ['']),
]
self.execute_cmds(cmds)
def test_add_succeeds_on_second_edit(self):
cmds = ['pubs init',
('pubs add', [
'', 'y',
'@misc{New, title="TTT", author="X. YY"}', '']),
('pubs list', [], '[New] YY, X. "TTT" \n')
]
self.execute_cmds(cmds)
def test_editor_success(self):
cmds = ['pubs init',
('pubs add', [str_fixtures.bibtex_external0]),

Loading…
Cancel
Save