Merge pull request #114 from pubs/fix/empty_key

Better checks and error message for empty key (Closes #113).
main
Olivier Mangin 7 years ago committed by GitHub
commit d685ec10aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -12,8 +12,9 @@ TYPE_KEY = 'type'
CONTROL_CHARS = ''.join(map(uchr, list(range(0, 32)) + list(range(127, 160)))) CONTROL_CHARS = ''.join(map(uchr, list(range(0, 32)) + list(range(127, 160))))
CITEKEY_FORBIDDEN_CHARS = '@\'\\,#}{~%/ ' # '/' is OK for bibtex but forbidden CITEKEY_FORBIDDEN_CHARS = '@\'\\,#}{~%/ ' # '/' is OK for bibtex but forbidden
# here since we transform citekeys into filenames # here since we transform citekeys into filenames
CITEKEY_EXCLUDE_RE = re.compile('[%s]' CITEKEY_EXCLUDE_RE = re.compile(
% re.escape(CONTROL_CHARS + CITEKEY_FORBIDDEN_CHARS)) '[%s]' % re.escape(CONTROL_CHARS + CITEKEY_FORBIDDEN_CHARS))
def str2citekey(s): def str2citekey(s):
key = unicodedata.normalize('NFKD', ustr(s)).encode('ascii', 'ignore').decode() key = unicodedata.normalize('NFKD', ustr(s)).encode('ascii', 'ignore').decode()
@ -21,32 +22,40 @@ def str2citekey(s):
# Normalize chars and remove non-ascii # Normalize chars and remove non-ascii
return key return key
def check_citekey(citekey): def check_citekey(citekey):
if citekey is None or not citekey.strip():
raise ValueError(u"Empty citekeys are not valid")
# TODO This is not the right way to test that (17/12/2012) # TODO This is not the right way to test that (17/12/2012)
if ustr(citekey) != str2citekey(citekey): if ustr(citekey) != str2citekey(citekey):
raise ValueError(u"Invalid `{}` citekey; ".format(citekey) + raise ValueError(u"Invalid `{}` citekey; ".format(citekey) +
u"utf-8 citekeys are not supported yet.\n" u"utf-8 citekeys are not supported yet.\n"
u"See https://github.com/pubs/pubs/issues/28 for details.") u"See https://github.com/pubs/pubs/issues/28 for details.")
def verify_bibdata(bibdata): def verify_bibdata(bibdata):
if bibdata is None or len(bibdata) == 0: if bibdata is None or len(bibdata) == 0:
raise ValueError(u"no valid bibdata") raise ValueError(u"no valid bibdata")
if len(bibdata) > 1: if len(bibdata) > 1:
raise ValueError(u"ambiguous: multiple entries in the bibdata.") raise ValueError(u"ambiguous: multiple entries in the bibdata.")
def get_entry(bibdata): def get_entry(bibdata):
verify_bibdata(bibdata) verify_bibdata(bibdata)
for e in bibdata.items(): for e in bibdata.items():
return e return e
def extract_citekey(bibdata): def extract_citekey(bibdata):
citekey, entry = get_entry(bibdata) citekey, entry = get_entry(bibdata)
return citekey return citekey
def author_last(author_str): def author_last(author_str):
""" Return the last name of the author """ """ Return the last name of the author """
return author_str.split(',')[0] return author_str.split(',')[0]
def generate_citekey(bibdata): def generate_citekey(bibdata):
""" Generate a citekey from bib_data. """ Generate a citekey from bib_data.
@ -69,6 +78,7 @@ def generate_citekey(bibdata):
return str2citekey(citekey) return str2citekey(citekey)
def extract_docfile(bibdata, remove=False): def extract_docfile(bibdata, remove=False):
""" Try extracting document file from bib data. """ Try extracting document file from bib data.
Returns None if not found. Returns None if not found.

@ -58,6 +58,17 @@ tags: [AI, computer]
added: '2013-11-14 13:14:20' added: '2013-11-14 13:14:20'
""" """
# Should not parse (see #113)
bibtex_no_citekey = """@Manual{,
title = {R: A Language and Environment for Statistical Computing},
author = {{R Core Team}},
organization = {R Foundation for Statistical Computing},
address = {Vienna, Austria},
year = {2017},
url = {https://www.R-project.org/},
}
"""
sample_conf = """ sample_conf = """
[main] [main]

@ -42,6 +42,10 @@ class TestAttributes(unittest.TestCase):
self.assertEqual(self.p.tags, set()) self.assertEqual(self.p.tags, set())
self.p.remove_tag('ranking') self.p.remove_tag('ranking')
def test_fails_with_empty_citekey(self):
with self.assertRaises(ValueError):
Paper(" ", fixtures.doe_bibdata)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

@ -331,6 +331,14 @@ class TestAdd(URLContentTestCase):
] ]
self.execute_cmds(cmds) self.execute_cmds(cmds)
def test_add_no_citekey_fails(self):
# See #113
cmds = ['pubs init',
('pubs add', [str_fixtures.bibtex_no_citekey]),
]
with self.assertRaises(FakeSystemExit):
self.execute_cmds(cmds)
class TestList(DataCommandTestCase): class TestList(DataCommandTestCase):

Loading…
Cancel
Save