diff --git a/pubs/bibstruct.py b/pubs/bibstruct.py index 76c0854..5a40abf 100644 --- a/pubs/bibstruct.py +++ b/pubs/bibstruct.py @@ -5,12 +5,12 @@ import re from .p3 import ustr, uchr - # citekey stuff +# Citekey stuff TYPE_KEY = 'type' 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 CITEKEY_EXCLUDE_RE = re.compile('[%s]' % re.escape(CONTROL_CHARS + CITEKEY_FORBIDDEN_CHARS)) @@ -75,24 +75,22 @@ def extract_docfile(bibdata, remove=False): :param remove: remove field after extracting information (default: False) """ - citekey, entry = get_entry(bibdata) - try: - if 'file' in entry: - field = entry['file'] + if 'file' in bibdata: + field = bibdata['file'] # Check if this is mendeley specific for f in field.split(':'): if len(f) > 0: break if remove: - entry.pop('file') + bibdata.pop('file') # This is a hck for Mendeley. Make clean if f[0] != '/': f = '/' + f return f - if 'attachments' in entry: - return entry['attachments'] - if 'pdf' in entry: - return entry['pdf'] + if 'attachments' in bibdata: + return bibdata['attachments'] + if 'pdf' in bibdata: + return bibdata['pdf'] except (KeyError, IndexError): return None diff --git a/pubs/commands/add_cmd.py b/pubs/commands/add_cmd.py index 39d0b0c..f9ddee6 100644 --- a/pubs/commands/add_cmd.py +++ b/pubs/commands/add_cmd.py @@ -12,7 +12,7 @@ from .. import pretty def parser(subparsers): parser = subparsers.add_parser('add', help='add a paper to the repository') - parser.add_argument('bibfile', nargs='?', default = None, + parser.add_argument('bibfile', nargs='?', default=None, help='bibtex file') parser.add_argument('-D', '--doi', help='doi number to retrieve the bibtex entry, if it is not provided', default=None) parser.add_argument('-I', '--isbn', help='isbn number to retrieve the bibtex entry, if it is not provided', default=None) @@ -26,7 +26,7 @@ def parser(subparsers): return parser -def bibdata_from_editor(ui, rp): +def bibentry_from_editor(ui, rp): again = True bibstr = templates.add_bib while again: @@ -41,8 +41,8 @@ def bibdata_from_editor(ui, rp): if not again: ui.exit(0) else: - bibdata = rp.databroker.verify(bibstr) - bibstruct.verify_bibdata(bibdata) + bibentry = rp.databroker.verify(bibstr) + bibstruct.verify_bibdata(bibentry) # REFACTOR Generate citykey again = False except ValueError: @@ -52,7 +52,8 @@ def bibdata_from_editor(ui, rp): if not again: ui.exit(0) - return bibdata + return bibentry + def command(args): """ @@ -64,47 +65,47 @@ def command(args): bibfile = args.bibfile docfile = args.docfile tags = args.tags - citekey = args.copy + citekey = args.citekey rp = repo.Repository(config()) # get bibtex entry if bibfile is None: if args.doi is None and args.isbn is None: - bibdata = bibdata_from_editor(ui, rp) + bibentry = bibentry_from_editor(ui, rp) else: if args.doi is not None: - bibdata_raw = apis.doi2bibtex(args.doi) - bibdata = rp.databroker.verify(bibdata_raw) - if bibdata is None: + bibentry_raw = apis.doi2bibtex(args.doi) + bibentry = rp.databroker.verify(bibentry_raw) + if bibentry is None: ui.error('invalid doi {} or unable to retrieve bibfile from it.'.format(args.doi)) if args.isbn is None: ui.exit(1) if args.isbn is not None: - bibdata_raw = apis.isbn2bibtex(args.isbn) - bibdata = rp.databroker.verify(bibdata_raw) - if bibdata is None: + bibentry_raw = apis.isbn2bibtex(args.isbn) + bibentry = rp.databroker.verify(bibentry_raw) + if bibentry is None: ui.error('invalid isbn {} or unable to retrieve bibfile from it.'.format(args.isbn)) ui.exit(1) # TODO distinguish between cases, offer to open the error page in a webbrowser. # TODO offer to confirm/change citekey else: - bibdata_raw = content.get_content(bibfile, ui=ui) - bibdata = rp.databroker.verify(bibdata_raw) - if bibdata is None: + bibentry_raw = content.get_content(bibfile, ui=ui) + bibentry = rp.databroker.verify(bibentry_raw) + if bibentry is None: ui.error('invalid bibfile {}.'.format(bibfile)) # citekey citekey = args.citekey if citekey is None: - base_key = bibstruct.extract_citekey(bibdata) + base_key = bibstruct.extract_citekey(bibentry) citekey = rp.unique_citekey(base_key) elif citekey in rp: ui.error('citekey already exist {}.'.format(citekey)) ui.exit(1) - p = paper.Paper(bibdata, citekey=citekey) + p = paper.Paper.from_bibentry(bibentry, citekey=citekey) # tags @@ -113,7 +114,7 @@ def command(args): # document file - bib_docfile = bibstruct.extract_docfile(bibdata) + bib_docfile = bibstruct.extract_docfile(bibentry) if docfile is None: docfile = bib_docfile elif bib_docfile is not None: @@ -126,9 +127,6 @@ def command(args): rp.push_paper(p) if docfile is not None: rp.push_doc(p.citekey, docfile, copy=args.copy) - if args.copy: - if ui.input_yn('{} has been copied into pubs; should the original be removed?'.format(color.dye(docfile, color.bold))): - content.remove_file(docfile) ui.print_('{}\nwas added to pubs.'.format(pretty.paper_oneliner(p))) except ValueError as v: ui.error(v.message) diff --git a/pubs/commands/attach_cmd.py b/pubs/commands/attach_cmd.py index 8bd5ebd..e7b4392 100644 --- a/pubs/commands/attach_cmd.py +++ b/pubs/commands/attach_cmd.py @@ -32,9 +32,6 @@ def command(args): try: document = args.document rp.push_doc(paper.citekey, document, copy=args.copy) - if args.copy: - if ui.input_yn('{} has been copied into pubs; should the original be removed?'.format(color.dye(document, color.bold))): - content.remove_file(document) ui.print_('{} attached to {}'.format(color.dye(document, color.bold), color.dye(paper.citekey, color.citekey))) except ValueError as v: diff --git a/pubs/commands/edit_cmd.py b/pubs/commands/edit_cmd.py index d563dc6..497665f 100644 --- a/pubs/commands/edit_cmd.py +++ b/pubs/commands/edit_cmd.py @@ -5,6 +5,7 @@ from ..uis import get_ui from ..endecoder import EnDecoder from ..utils import resolve_citekey + def parser(subparsers): parser = subparsers.add_parser('edit', help='open the paper bibliographic file in an editor') @@ -34,7 +35,7 @@ def command(args): encode = coder.encode_bibdata decode = coder.decode_bibdata suffix = '.bib' - raw_content = encode(paper.bibdata) + raw_content = encode(paper.bibentry) while True: # Get new content from user @@ -44,10 +45,11 @@ def command(args): content = decode(raw_content) if meta: - new_paper = Paper(paper.bibdata, citekey=paper.citekey, + new_paper = Paper(paper.citekey, paper.bibdata, metadata=content) else: - new_paper = Paper(content, metadata=paper.metadata) + new_paper = Paper.from_bibentry(content, + metadata=paper.metadata) rp.rename_paper(new_paper, old_citekey=paper.citekey) break diff --git a/pubs/commands/export_cmd.py b/pubs/commands/export_cmd.py index 65bc1cc..5266343 100644 --- a/pubs/commands/export_cmd.py +++ b/pubs/commands/export_cmd.py @@ -33,7 +33,7 @@ def command(args): papers = rp.all_papers() bib = {} for p in papers: - bib[p.citekey] = p.bibentry + bib[p.citekey] = p.bibdata exporter = endecoder.EnDecoder() bibdata_raw = exporter.encode_bibdata(bib) ui.print_(bibdata_raw) diff --git a/pubs/commands/import_cmd.py b/pubs/commands/import_cmd.py index bf331d0..a0fb98d 100644 --- a/pubs/commands/import_cmd.py +++ b/pubs/commands/import_cmd.py @@ -49,12 +49,9 @@ def many_from_path(bibpath): papers = {} for b in biblist: - for k in b.keys(): + for k, b in b.items(): try: - bibdata = {} - bibdata[k] = b[k] - - papers[k] = Paper(bibdata, citekey=k) + papers[k] = Paper(k, b) papers[k].added = datetime.datetime.now() except ValueError as e: papers[k] = e diff --git a/pubs/commands/list_cmd.py b/pubs/commands/list_cmd.py index 1874a3e..950e86e 100644 --- a/pubs/commands/list_cmd.py +++ b/pubs/commands/list_cmd.py @@ -73,10 +73,10 @@ def _lower(s, lower=True): def _check_author_match(paper, query, case_sensitive=False): """Only checks within last names.""" - if not 'author' in paper.bibentry: + if not 'author' in paper.bibdata: return False return any([query in _lower(bibstruct.author_last(p), lower=(not case_sensitive)) - for p in paper.bibentry['author']]) + for p in paper.bibdata['author']]) @@ -86,8 +86,8 @@ def _check_tag_match(paper, query, case_sensitive=False): def _check_field_match(paper, field, query, case_sensitive=False): - return query in _lower(paper.bibentry[field], - lower=(not case_sensitive)) + return query in _lower(paper.bibdata[field], + lower=(not case_sensitive)) def _check_query_block(paper, query_block, case_sensitive=None): @@ -100,7 +100,7 @@ def _check_query_block(paper, query_block, case_sensitive=None): return _check_tag_match(paper, value, case_sensitive=case_sensitive) elif field == 'author': return _check_author_match(paper, value, case_sensitive=case_sensitive) - elif field in paper.bibentry: + elif field in paper.bibdata: return _check_field_match(paper, field, value, case_sensitive=case_sensitive) else: diff --git a/pubs/configs.py b/pubs/configs.py index 6a6cdb3..457a9e6 100644 --- a/pubs/configs.py +++ b/pubs/configs.py @@ -66,12 +66,12 @@ class Config(object): if not check_file(path, fail=False): raise IOError(("The configuration file {} does not exist." " Did you run 'pubs init' ?").format(path)) - with _open(path, 'rb+') as f: + with _open(path, 'r+') as f: _read_config(self._cfg, f) return self def save(self, path=DFT_CONFIG_PATH): - with _open(path, 'wb+') as f: + with _open(path, 'w+') as f: self._cfg.write(f) def __setattr__(self, name, value): diff --git a/pubs/databroker.py b/pubs/databroker.py index 801bbe5..b206c26 100644 --- a/pubs/databroker.py +++ b/pubs/databroker.py @@ -21,7 +21,7 @@ class DataBroker(object): metadata_raw = self.filebroker.pull_metafile(citekey) return self.endecoder.decode_metadata(metadata_raw) - def pull_bibdata(self, citekey): + def pull_bibentry(self, citekey): bibdata_raw = self.filebroker.pull_bibfile(citekey) return self.endecoder.decode_bibdata(bibdata_raw) @@ -29,7 +29,7 @@ class DataBroker(object): metadata_raw = self.endecoder.encode_metadata(metadata) self.filebroker.push_metafile(citekey, metadata_raw) - def push_bibdata(self, citekey, bibdata): + def push_bibentry(self, citekey, bibdata): bibdata_raw = self.endecoder.encode_bibdata(bibdata) self.filebroker.push_bibfile(citekey, bibdata_raw) diff --git a/pubs/datacache.py b/pubs/datacache.py index 98b3914..2c3c5a4 100644 --- a/pubs/datacache.py +++ b/pubs/datacache.py @@ -31,14 +31,14 @@ class DataCache(object): def pull_metadata(self, citekey): return self.databroker.pull_metadata(citekey) - def pull_bibdata(self, citekey): - return self.databroker.pull_bibdata(citekey) + def pull_bibentry(self, citekey): + return self.databroker.pull_bibentry(citekey) def push_metadata(self, citekey, metadata): self.databroker.push_metadata(citekey, metadata) - def push_bibdata(self, citekey, bibdata): - self.databroker.push_bibdata(citekey, bibdata) + def push_bibentry(self, citekey, bibdata): + self.databroker.push_bibentry(citekey, bibdata) def push(self, citekey, metadata, bibdata): self.databroker.push(citekey, metadata, bibdata) diff --git a/pubs/paper.py b/pubs/paper.py index c137ce2..e0c10d0 100644 --- a/pubs/paper.py +++ b/pubs/paper.py @@ -28,19 +28,11 @@ class Paper(object): in a pythonic manner. """ - def __init__(self, bibdata, citekey=None, metadata=None): + def __init__(self, citekey, bibdata, metadata=None): self.citekey = citekey self.metadata = _clean_metadata(metadata) self.bibdata = bibdata - - _, self.bibentry = bibstruct.get_entry(self.bibdata) - - if self.citekey is None: - self.citekey = bibstruct.extract_citekey(self.bibdata) - bibstruct.check_citekey(self.citekey) - else: - def_citekey = bibstruct.extract_citekey(self.bibdata) - self.bibdata = {citekey: self.bibdata[def_citekey]} + bibstruct.check_citekey(self.citekey) def __eq__(self, other): return (isinstance(self, Paper) and type(other) is type(self) @@ -50,15 +42,15 @@ class Paper(object): def __repr__(self): return 'Paper(%s, %s, %s)' % ( - self.citekey, self.bibentry, self.metadata) + self.citekey, self.bibdata, self.metadata) def __deepcopy__(self, memo): - return Paper(citekey =self.citekey, + return Paper(citekey=self.citekey, metadata=copy.deepcopy(self.metadata, memo), bibdata=copy.deepcopy(self.bibdata, memo)) def __copy__(self): - return Paper(citekey =self.citekey, + return Paper(citekey=self.citekey, metadata=self.metadata, bibdata=self.bibdata) @@ -67,6 +59,10 @@ class Paper(object): # docpath + @property + def bibentry(self): + return {self.citekey: self.bibdata} + @property def docpath(self): return self.metadata.get('docfile', '') @@ -105,3 +101,10 @@ class Paper(object): @added.setter def added(self, value): self.metadata['added'] = value + + @staticmethod + def from_bibentry(bibentry, citekey=None, metadata=None): + bibentry_key, bibdata = bibstruct.get_entry(bibentry) + if citekey is None: + citekey = bibentry_key + return Paper(citekey, bibdata, metadata=metadata) diff --git a/pubs/pretty.py b/pubs/pretty.py index 7869221..55e7e18 100644 --- a/pubs/pretty.py +++ b/pubs/pretty.py @@ -1,6 +1,7 @@ # display formatting from . import color +from .bibstruct import TYPE_KEY # should be adaptated to bibtexparser dicts @@ -12,9 +13,9 @@ def person_repr(p): ' '.join(p.lineage(abbr=True))] if s) -def short_authors(bibentry): +def short_authors(bibdata): try: - authors = [p for p in bibentry['author']] + authors = [p for p in bibdata['author']] if len(authors) < 3: return ' and '.join(authors) else: @@ -23,19 +24,19 @@ def short_authors(bibentry): return '' -def bib_oneliner(bibentry): - authors = short_authors(bibentry) +def bib_oneliner(bibdata): + authors = short_authors(bibdata) journal = '' - if 'journal' in bibentry: - journal = ' ' + bibentry['journal']['name'] - elif bibentry['type'] == 'inproceedings': - journal = ' ' + bibentry.get('booktitle', '') + if 'journal' in bibdata: + journal = ' ' + bibdata['journal']['name'] + elif bibdata[TYPE_KEY] == 'inproceedings': + journal = ' ' + bibdata.get('booktitle', '') return u'{authors} \"{title}\"{journal}{year}'.format( authors=color.dye(authors, color.grey, bold=True), - title=bibentry.get('title', ''), + title=bibdata.get('title', ''), journal=color.dye(journal, color.yellow), - year=' ({})'.format(bibentry['year']) if 'year' in bibentry else '', + year=' ({})'.format(bibdata['year']) if 'year' in bibdata else '', ) @@ -48,11 +49,11 @@ def bib_desc(bib_data): return s -def paper_oneliner(p, citekey_only = False): +def paper_oneliner(p, citekey_only=False): if citekey_only: return p.citekey else: - bibdesc = bib_oneliner(p.bibentry) + bibdesc = bib_oneliner(p.bibdata) tags = '' if len(p.tags) == 0 else '| {}'.format( ','.join(color.dye(t, color.tag) for t in sorted(p.tags))) return u'[{citekey}] {descr} {tags}'.format( diff --git a/pubs/repo.py b/pubs/repo.py index 5953c3b..a2cdfcc 100644 --- a/pubs/repo.py +++ b/pubs/repo.py @@ -58,9 +58,10 @@ class Repository(object): def pull_paper(self, citekey): """Load a paper by its citekey from disk, if necessary.""" if citekey in self: - return Paper(self.databroker.pull_bibdata(citekey), - citekey=citekey, - metadata=self.databroker.pull_metadata(citekey)) + return Paper.from_bibentry( + self.databroker.pull_bibentry(citekey), + citekey=citekey, + metadata=self.databroker.pull_metadata(citekey)) else: raise InvalidReference('{} citekey not found'.format(citekey)) @@ -75,7 +76,7 @@ class Repository(object): raise CiteKeyCollision('citekey {} already in use'.format(paper.citekey)) if not paper.added: paper.added = datetime.now() - self.databroker.push_bibdata(paper.citekey, paper.bibdata) + self.databroker.push_bibentry(paper.citekey, paper.bibentry) self.databroker.push_metadata(paper.citekey, paper.metadata) self.citekeys.add(paper.citekey) if event: diff --git a/tests/fake_env.py b/tests/fake_env.py index 4bd199b..abe357d 100644 --- a/tests/fake_env.py +++ b/tests/fake_env.py @@ -202,6 +202,9 @@ class FakeInput(): input() raises IndexError """ + class UnexpectedInput(Exception): + pass + def __init__(self, inputs, module_list=tuple()): self.inputs = list(inputs) or [] self.module_list = module_list @@ -218,9 +221,12 @@ class FakeInput(): self.inputs.append(inp) def __call__(self, *args, **kwargs): - inp = self.inputs[self._cursor] - self._cursor += 1 - return inp + try: + inp = self.inputs[self._cursor] + self._cursor += 1 + return inp + except IndexError: + raise self.UnexpectedInput('Unexpected user input in test.') class TestFakeFs(unittest.TestCase): diff --git a/tests/fixtures.py b/tests/fixtures.py index 6793a8f..b70691e 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -23,18 +23,18 @@ doe_bib = """ dummy_metadata = {'docfile': 'docsdir://hop.la', 'tags': set(['a', 'b'])} -franny_bibdata = coder.decode_bibdata(franny_bib) -franny_bibentry = franny_bibdata['Franny1961'] +franny_bibentry = coder.decode_bibdata(franny_bib) +franny_bibdata = franny_bibentry['Franny1961'] -doe_bibdata = coder.decode_bibdata(doe_bib) -doe_bibentry = doe_bibdata['Doe2013'] +doe_bibentry = coder.decode_bibdata(doe_bib) +doe_bibdata = doe_bibentry['Doe2013'] -turing_bibdata = coder.decode_bibdata(str_fixtures.turing_bib) -turing_bibentry = turing_bibdata['turing1950computing'] +turing_bibentry = coder.decode_bibdata(str_fixtures.turing_bib) +turing_bibdata = turing_bibentry['turing1950computing'] turing_metadata = coder.decode_metadata(str_fixtures.turing_meta) -page_bibdata = coder.decode_bibdata(str_fixtures.bibtex_raw0) -page_bibentry = page_bibdata['Page99'] +page_bibentry = coder.decode_bibdata(str_fixtures.bibtex_raw0) +page_bibdata = page_bibentry['Page99'] page_metadata = coder.decode_metadata(str_fixtures.metadata_raw0) page_metadata = coder.decode_metadata(str_fixtures.metadata_raw0) diff --git a/tests/test_bibstruct.py b/tests/test_bibstruct.py index 26e116d..63d8600 100644 --- a/tests/test_bibstruct.py +++ b/tests/test_bibstruct.py @@ -16,18 +16,19 @@ class TestGenerateCitekey(unittest.TestCase): bibstruct.generate_citekey(None) def test_escapes_chars(self): - doe_bibdata = copy.deepcopy(fixtures.doe_bibdata) - citekey, entry = bibstruct.get_entry(doe_bibdata) - entry['author'] = [u'Zôu\\@/ , John'] - key = bibstruct.generate_citekey(doe_bibdata) + doe_bibentry = copy.deepcopy(fixtures.doe_bibentry) + citekey, bibdata = bibstruct.get_entry(doe_bibentry) + bibdata['author'] = [u'Zôu\\@/ , John'] + key = bibstruct.generate_citekey(doe_bibentry) + self.assertEqual(key, 'Zou2013') def test_simple(self): - bibdata = copy.deepcopy(fixtures.doe_bibdata) - key = bibstruct.generate_citekey(bibdata) + bibentry = copy.deepcopy(fixtures.doe_bibentry) + key = bibstruct.generate_citekey(bibentry) self.assertEqual(key, 'Doe2013') - bibdata = copy.deepcopy(fixtures.franny_bibdata) - key = bibstruct.generate_citekey(bibdata) + bibentry = copy.deepcopy(fixtures.franny_bibentry) + key = bibstruct.generate_citekey(bibentry) self.assertEqual(key, 'Salinger1961') diff --git a/tests/test_databroker.py b/tests/test_databroker.py index 0e50367..e8bfa6e 100644 --- a/tests/test_databroker.py +++ b/tests/test_databroker.py @@ -17,7 +17,7 @@ class TestDataBroker(unittest.TestCase): ende = endecoder.EnDecoder() page99_metadata = ende.decode_metadata(str_fixtures.metadata_raw0) - page99_bibdata = ende.decode_bibdata(str_fixtures.bibtex_raw0) + page99_bibentry = ende.decode_bibdata(str_fixtures.bibtex_raw0) for db_class in [databroker.DataBroker, datacache.DataCache]: self.fs = fake_env.create_fake_fs([content, filebroker, configs]) @@ -28,22 +28,22 @@ class TestDataBroker(unittest.TestCase): self.assertFalse(db.exists('citekey1', meta_check=True)) self.assertFalse(db.exists('citekey1', meta_check=False)) - db.push_bibdata('citekey1', page99_bibdata) + db.push_bibentry('citekey1', page99_bibentry) self.assertTrue(db.exists('citekey1', meta_check=False)) self.assertTrue(db.exists('citekey1', meta_check=True)) self.assertEqual(db.pull_metadata('citekey1'), page99_metadata) - pulled = db.pull_bibdata('citekey1')['Page99'] + pulled = db.pull_bibentry('citekey1')['Page99'] for key, value in pulled.items(): - self.assertEqual(pulled[key], page99_bibdata['Page99'][key]) - self.assertEqual(db.pull_bibdata('citekey1'), page99_bibdata) + self.assertEqual(pulled[key], page99_bibentry['Page99'][key]) + self.assertEqual(db.pull_bibentry('citekey1'), page99_bibentry) fake_env.unset_fake_fs([content, filebroker]) def test_existing_data(self): ende = endecoder.EnDecoder() - page99_bibdata = ende.decode_bibdata(str_fixtures.bibtex_raw0) + page99_bibentry = ende.decode_bibdata(str_fixtures.bibtex_raw0) for db_class in [databroker.DataBroker, datacache.DataCache]: self.fs = fake_env.create_fake_fs([content, filebroker]) @@ -51,16 +51,16 @@ class TestDataBroker(unittest.TestCase): db = db_class('repo', create=False) - self.assertEqual(db.pull_bibdata('Page99'), page99_bibdata) + self.assertEqual(db.pull_bibentry('Page99'), page99_bibentry) for citekey in ['10.1371_journal.pone.0038236', '10.1371journal.pone.0063400', 'journal0063400']: - db.pull_bibdata(citekey) + db.pull_bibentry(citekey) db.pull_metadata(citekey) with self.assertRaises(IOError): - db.pull_bibdata('citekey') + db.pull_bibentry('citekey') with self.assertRaises(IOError): db.pull_metadata('citekey') diff --git a/tests/test_endecoder.py b/tests/test_endecoder.py index d5e51f1..4bf7a5f 100644 --- a/tests/test_endecoder.py +++ b/tests/test_endecoder.py @@ -86,9 +86,7 @@ class TestEnDecode(unittest.TestCase): biblines = turing_bib.splitlines() biblines.insert(-3, keyword_str) bibsrc = '\n'.join(biblines) - print(bibsrc) entry = decoder.decode_bibdata(bibsrc)['turing1950computing'] - print(entry) self.assertNotIn(u'keywords', entry) self.assertIn(u'keyword', entry) self.assertEqual(set(keywords), set(entry[u'keyword'])) diff --git a/tests/test_events.py b/tests/test_events.py index 8f09ea3..32e0a4c 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -75,19 +75,19 @@ class TestEvents(unittest.TestCase): correct = ['abcdefghijklmnopqrstuvwxyz 12 15', 'Helloword', 'one'] - self.assertEquals(_output, correct) + self.assertEqual(_output, correct) def test_listen_AddEvent(self): addevent = AddEvent() addevent.send() correct = [42] - self.assertEquals(_output, correct) + self.assertEqual(_output, correct) def test_listen_Info(self): Info('info').send() SpecificInfo('info', 'specific').send() correct = ['info', 'info', 'specific'] - self.assertEquals(_output, correct) + self.assertEqual(_output, correct) if __name__ == '__main__': diff --git a/tests/test_paper.py b/tests/test_paper.py index e865fae..cd2c94e 100644 --- a/tests/test_paper.py +++ b/tests/test_paper.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -import os + import unittest import dotdot @@ -9,38 +9,38 @@ from pubs.paper import Paper class TestAttributes(unittest.TestCase): + def setUp(self): + self.p = Paper.from_bibentry( + fixtures.page_bibentry, + metadata=fixtures.page_metadata).deepcopy() + def test_tags(self): - p = Paper(fixtures.page_bibdata, metadata=fixtures.page_metadata).deepcopy() - self.assertEqual(p.tags, set(['search', 'network'])) + self.assertEqual(self.p.tags, set(['search', 'network'])) def test_add_tag(self): - p = Paper(fixtures.page_bibdata, metadata=fixtures.page_metadata).deepcopy() - p.add_tag('algorithm') - self.assertEqual(p.tags, set(['search', 'network', 'algorithm'])) - p.add_tag('algorithm') - self.assertEqual(p.tags, set(['search', 'network', 'algorithm'])) + self.p.add_tag('algorithm') + self.assertEqual(self.p.tags, set(['search', 'network', 'algorithm'])) + self.p.add_tag('algorithm') + self.assertEqual(self.p.tags, set(['search', 'network', 'algorithm'])) def test_set_tags(self): - p = Paper(fixtures.page_bibdata, metadata=fixtures.page_metadata).deepcopy() - p.tags = ['algorithm'] - self.assertEqual(p.tags, set(['algorithm'])) + self.p.tags = ['algorithm'] + self.assertEqual(self.p.tags, set(['algorithm'])) def test_remove_tags(self): - p = Paper(fixtures.page_bibdata, metadata=fixtures.page_metadata).deepcopy() - p.remove_tag('network') - self.assertEqual(p.tags, set(['search'])) + self.p.remove_tag('network') + self.assertEqual(self.p.tags, set(['search'])) def test_mixed_tags(self): - p = Paper(fixtures.page_bibdata, metadata=fixtures.page_metadata).deepcopy() - p.add_tag('algorithm') - self.assertEqual(p.tags, set(['search', 'network', 'algorithm'])) - p.remove_tag('network') - self.assertEqual(p.tags, set(['search', 'algorithm'])) - p.tags = ['ranking'] - self.assertEqual(p.tags, set(['ranking'])) - p.remove_tag('ranking') - self.assertEqual(p.tags, set()) - p.remove_tag('ranking') + self.p.add_tag('algorithm') + self.assertEqual(self.p.tags, set(['search', 'network', 'algorithm'])) + self.p.remove_tag('network') + self.assertEqual(self.p.tags, set(['search', 'algorithm'])) + self.p.tags = ['ranking'] + self.assertEqual(self.p.tags, set(['ranking'])) + self.p.remove_tag('ranking') + self.assertEqual(self.p.tags, set()) + self.p.remove_tag('ranking') if __name__ == '__main__': diff --git a/tests/test_queries.py b/tests/test_queries.py index 0f9147f..6ea7a10 100644 --- a/tests/test_queries.py +++ b/tests/test_queries.py @@ -2,18 +2,19 @@ import unittest import dotdot from pubs.commands.list_cmd import (_check_author_match, - _check_field_match, - _check_query_block, - filter_paper, - InvalidQuery) + _check_field_match, + _check_query_block, + filter_paper, + InvalidQuery) from pubs.paper import Paper import fixtures -doe_paper = Paper(fixtures.doe_bibdata) -page_paper = Paper(fixtures.page_bibdata) -turing_paper = Paper(fixtures.turing_bibdata, metadata=fixtures.turing_metadata) +doe_paper = Paper.from_bibentry(fixtures.doe_bibentry) +page_paper = Paper.from_bibentry(fixtures.page_bibentry) +turing_paper = Paper.from_bibentry(fixtures.turing_bibentry, + metadata=fixtures.turing_metadata) class TestAuthorFilter(unittest.TestCase): diff --git a/tests/test_repo.py b/tests/test_repo.py index e1eaff7..b651caf 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -15,7 +15,7 @@ class TestRepo(fake_env.TestFakeFs): def setUp(self): super(TestRepo, self).setUp() self.repo = Repository(configs.Config(), create=True) - self.repo.push_paper(Paper(fixtures.turing_bibdata)) + self.repo.push_paper(Paper.from_bibentry(fixtures.turing_bibentry)) class TestCitekeyGeneration(TestRepo): @@ -27,9 +27,10 @@ class TestCitekeyGeneration(TestRepo): self.assertEqual(_base27(26 + i + 1), 'a' + chr(97 + i)) def test_generated_key_is_unique(self): - self.repo.push_paper(Paper(fixtures.doe_bibdata)) + self.repo.push_paper(Paper.from_bibentry(fixtures.doe_bibentry)) c = self.repo.unique_citekey('Doe2013') - self.repo.push_paper(Paper(fixtures.doe_bibdata, citekey='Doe2013a')) + self.repo.push_paper(Paper.from_bibentry(fixtures.doe_bibentry, + citekey='Doe2013a')) c = self.repo.unique_citekey('Doe2013') self.assertEqual(c, 'Doe2013b') @@ -38,25 +39,27 @@ class TestPushPaper(TestRepo): def test_raises_value_error_on_existing_key(self): with self.assertRaises(CiteKeyCollision): - self.repo.push_paper(Paper(fixtures.turing_bibdata)) + self.repo.push_paper(Paper.from_bibentry(fixtures.turing_bibentry)) def test_pushes_paper_bibdata(self): - orig = fixtures.doe_bibdata - self.repo.push_paper(Paper(orig)) - retrieved = self.repo.databroker.pull_bibdata('Doe2013') - self.assertEquals(orig, retrieved) + orig = fixtures.doe_bibentry + self.repo.push_paper(Paper.from_bibentry(orig)) + retrieved = self.repo.databroker.pull_bibentry('Doe2013') + self.assertEqual(orig, retrieved) def test_pushes_paper_metadata(self): orig = {'docfile': 'dummy', 'tags': set(['tag', 'another']), 'added': datetime(2012, 12, 12, 12, 12, 12, 12)} - self.repo.push_paper(Paper(fixtures.doe_bibdata, metadata=orig)) + self.repo.push_paper(Paper.from_bibentry(fixtures.doe_bibentry, + metadata=orig)) retrieved = self.repo.databroker.pull_metadata('Doe2013') - self.assertEquals(orig, retrieved) + self.assertEqual(orig, retrieved) def test_pushes_paper_metadata_set_added(self): orig = {'docfile': 'dummy', 'tags': set(['tag', 'another'])} now = datetime.now() - self.repo.push_paper(Paper(fixtures.doe_bibdata, metadata=orig)) + self.repo.push_paper(Paper.from_bibentry(fixtures.doe_bibentry, + metadata=orig)) retrieved = self.repo.databroker.pull_metadata('Doe2013') self.assertIn('added', retrieved) self.assertTrue(now < retrieved['added']) diff --git a/tests/test_usecase.py b/tests/test_usecase.py index 3e82b7b..b0542b9 100644 --- a/tests/test_usecase.py +++ b/tests/test_usecase.py @@ -29,7 +29,7 @@ class TestFakeInput(unittest.TestCase): input = fake_env.FakeInput(['yes', 'no']) self.assertEqual(input(), 'yes') self.assertEqual(input(), 'no') - with self.assertRaises(IndexError): + with self.assertRaises(fake_env.FakeInput.UnexpectedInput): input() def test_input2(self): @@ -37,7 +37,7 @@ class TestFakeInput(unittest.TestCase): other_input.as_global() self.assertEqual(color.input(), 'yes') self.assertEqual(color.input(), 'no') - with self.assertRaises(IndexError): + with self.assertRaises(fake_env.FakeInput.UnexpectedInput): color.input() def test_editor_input(self): @@ -46,7 +46,7 @@ class TestFakeInput(unittest.TestCase): other_input.as_global() self.assertEqual(content.editor_input(), 'yes') self.assertEqual(content.editor_input(), 'no') - with self.assertRaises(IndexError): + with self.assertRaises(fake_env.FakeInput.UnexpectedInput): color.input() @@ -66,35 +66,41 @@ class CommandTestCase(unittest.TestCase): In the latter case, the command is : 1. a string reprensenting the command to execute 2. the user inputs to feed to the command during execution - 3. the output expected, verified with assertEqual + 3. the output expected, verified with assertEqual. Always captures + output in this case. """ outs = [] for cmd in cmds: + inputs = [] + output = None + actual_cmd = cmd + current_capture_output = capture_output if not isinstance(cmd, p3.ustr): - if len(cmd) == 2: - input = fake_env.FakeInput(cmd[1], [content, uis, p3]) - input.as_global() - - if capture_output: - _, stdout, stderr = fake_env.redirect(pubs_cmd.execute)(cmd[0].split()) - if len(cmd) == 3 and capture_output: - actual_out = color.undye(stdout) - correct_out = color.undye(cmd[2]) + actual_cmd = cmd[0] + if len(cmd) == 2: # Inputs provided + inputs = cmd[1] + if len(cmd) == 3: # Expected output provided + current_capture_output = True + output = cmd[2] + # Always set fake input: test should not ask unexpected user input + input = fake_env.FakeInput(inputs, [content, uis, p3]) + input.as_global() + try: + if current_capture_output: + _, stdout, stderr = fake_env.redirect(pubs_cmd.execute)( + actual_cmd.split()) + self.assertEqual(stderr, '') + actual_out = color.undye(stdout) + if output is not None: + correct_out = color.undye(output) self.assertEqual(actual_out, correct_out) + outs.append(color.undye(actual_out)) else: pubs_cmd.execute(cmd.split()) - - else: - if capture_output: - assert p3.isbasestr(cmd) - _, stdout, stderr = fake_env.redirect(pubs_cmd.execute)(cmd.split()) - else: - pubs_cmd.execute(cmd.split()) - - if capture_output: - assert(stderr == '') - outs.append(color.undye(stdout)) + except fake_env.FakeInput.UnexpectedInput: + self.fail('Unexpected input asked by command: {}.'.format( + actual_cmd)) if PRINT_OUTPUT: print(outs) return outs @@ -161,7 +167,7 @@ class TestAdd(DataCommandTestCase): def test_add_doc_nocopy_does_not_copy(self): cmds = ['pubs init', - 'pubs add /data/pagerank.bib -C -d /data/pagerank.pdf', + 'pubs add /data/pagerank.bib --link -d /data/pagerank.pdf', ] self.execute_cmds(cmds) self.assertEqual(self.fs['os'].listdir( @@ -186,10 +192,8 @@ class TestList(DataCommandTestCase): 'pubs list', ] outs = self.execute_cmds(cmds) - print(outs[1].splitlines()) - self.assertEquals(0, len(outs[1].splitlines())) - print(outs[3].splitlines()) - self.assertEquals(1, len(outs[3].splitlines())) + self.assertEqual(0, len(outs[1].splitlines())) + self.assertEqual(1, len(outs[3].splitlines())) def test_list_several_no_date(self): self.execute_cmds(['pubs init -p /testrepo']) @@ -203,14 +207,11 @@ class TestList(DataCommandTestCase): 'pubs list', ] outs = self.execute_cmds(cmds) - print(outs[0].splitlines()) - self.assertEquals(4, len(outs[0].splitlines())) - print(outs[2].splitlines()) - self.assertEquals(3, len(outs[2].splitlines())) - print(outs[4].splitlines()) - self.assertEquals(4, len(outs[4].splitlines())) + self.assertEqual(4, len(outs[0].splitlines())) + self.assertEqual(3, len(outs[2].splitlines())) + self.assertEqual(4, len(outs[4].splitlines())) # Last added should be last - self.assertEquals('[Page99]', outs[4].splitlines()[-1][:8]) + self.assertEqual('[Page99]', outs[4].splitlines()[-1][:8]) def test_list_smart_case(self): cmds = ['pubs init', @@ -219,8 +220,7 @@ class TestList(DataCommandTestCase): 'pubs list title:language author:Saunders', ] outs = self.execute_cmds(cmds) - print(outs[-1]) - self.assertEquals(1, len(outs[-1].splitlines())) + self.assertEqual(1, len(outs[-1].splitlines())) def test_list_ignore_case(self): cmds = ['pubs init', @@ -229,8 +229,7 @@ class TestList(DataCommandTestCase): 'pubs list --ignore-case title:lAnguAge author:saunders', ] outs = self.execute_cmds(cmds) - print(outs[-1]) - self.assertEquals(1, len(outs[-1].splitlines())) + self.assertEqual(1, len(outs[-1].splitlines())) def test_list_force_case(self): cmds = ['pubs init', @@ -239,7 +238,7 @@ class TestList(DataCommandTestCase): 'pubs list --force-case title:Language author:saunders', ] outs = self.execute_cmds(cmds) - self.assertEquals(0 + 1, len(outs[-1].split('\n'))) + self.assertEqual(0 + 1, len(outs[-1].split('\n'))) @@ -247,12 +246,12 @@ class TestUsecase(DataCommandTestCase): def test_first(self): correct = ['Initializing pubs in /paper_first\n', - '', + '[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) \nwas added to pubs.\n', '[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) \n', '\n', '', 'network search\n', - '[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) network search\n' + '[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) | network,search\n', ] cmds = ['pubs init -p paper_first/', @@ -264,7 +263,7 @@ class TestUsecase(DataCommandTestCase): 'pubs tag search', ] - self.assertEqual(correct, self.execute_cmds(cmds)) + self.assertEqual(correct, self.execute_cmds(cmds, capture_output=True)) def test_second(self): cmds = ['pubs init -p paper_second/', @@ -290,7 +289,6 @@ class TestUsecase(DataCommandTestCase): ] self.execute_cmds(cmds) docdir = self.fs['os'].path.expanduser('~/.pubs/doc/') - print(self.fs['os'].listdir(docdir)) self.assertNotIn('turing-mind-1950.pdf', self.fs['os'].listdir(docdir)) @@ -364,7 +362,7 @@ class TestUsecase(DataCommandTestCase): ] outs = self.execute_cmds(cmds) self.assertEqual(endecoder.EnDecoder().decode_bibdata(outs[2]), - fixtures.page_bibdata) + fixtures.page_bibentry) def test_import(self): cmds = ['pubs init',