diff --git a/papers/commands/edit_cmd.py b/papers/commands/edit_cmd.py index 2d379ca..6f45cc2 100644 --- a/papers/commands/edit_cmd.py +++ b/papers/commands/edit_cmd.py @@ -15,13 +15,12 @@ def parser(subparsers): def command(ui, meta, reference): - rp = repo.Repository.from_directory(config()) + rp = repo.Repository(config()) key = parse_reference(ui, rp, reference) paper = rp.get_paper(key) - to_edit = 'bib' + filepath = rp._bibfile(key) if meta: - to_edit = 'meta' - filepath = rp.path_to_paper_file(key, to_edit) + filepath = rp._metafile(key) with open(filepath) as f: content = f.read() while True: @@ -37,9 +36,9 @@ def command(ui, meta, reference): new_key, bib = get_bibentry_from_string(content) paper.update(key=new_key, bib=bib, meta=metadata) try: - rp.update(paper, old_citekey=key) + rp.update_paper(paper, old_citekey=key) break - except repo.CiteKeyAlreadyExists: + except repo.CiteKeyCollision: options = ['overwrite', 'edit again', 'abort'] choice = options[ui.input_choice( options, @@ -49,5 +48,6 @@ def command(ui, meta, reference): if choice == 'abort': break elif choice == 'overwrite': - rp.update(paper, old_citekey=key, overwrite=True) + rp.update_paper(paper, old_citekey=key, overwrite=True) + break # else edit again diff --git a/papers/files.py b/papers/files.py index 8d0d386..fa79d03 100644 --- a/papers/files.py +++ b/papers/files.py @@ -165,10 +165,16 @@ def parse_bibdata(content, format_ = None): # we need to reuse the content content = content if type(content) == str else str(content.read()) + # If you use StingIO from io then the content must be unicode + # Let call this quick fix a hack but we should think it more carefully + content = unicode(content) + # This bug was really a pain in the ass to discover because of the (old) except Expection below! + # I changed it to the only kind of error that can raise _parse_bibdata_formated_stream, which is a ValueError + for fmt in fmts: try: return _parse_bibdata_formated_stream(StringIO(content), fmt) - except Exception: + except ValueError: pass raise ValueError('content format is not recognized.') diff --git a/papers/repo.py b/papers/repo.py index b248fb8..6bda239 100644 --- a/papers/repo.py +++ b/papers/repo.py @@ -117,10 +117,11 @@ class Repository(object): def add_paper(self, p, overwrite = False): if p.citekey is None: # TODO also test if citekey is valid raise ValueError("Invalid citekey: {}.".format(p.citekey)) - if not overwrite and p.citekey in self: + if not overwrite and p.citekey in self.citekeys: raise CiteKeyCollision('citekey {} already in use'.format( p.citekey)) - self.citekeys.append(p.citekey) + if p.citekey not in self.citekeys: + self.citekeys.append(p.citekey) self.save_paper(p) self.save() # TODO change to logging system (17/12/2012) @@ -143,6 +144,38 @@ class Repository(object): self.add_paper(paper, overwrite = overwrite) self._move_doc(old_citekey, paper) + def update_paper(self, paper, old_citekey=None, overwrite=False): + """Updates a paper, eventually changing its citekey. + The paper should be in repository. If the citekey changes, + the new citekey should be free except if the overwrite argument + is set to True. + """ + if old_citekey is None: + old_citekey = paper.citekey + if old_citekey not in self.citekeys: + raise(ValueError, 'Paper not in repository. Add first') + else: + if paper.citekey == old_citekey: + self.save_paper(paper) + else: + if paper.citekey in self.citekeys: + if not overwrite: + raise(CiteKeyCollision, + "There is already a paper with citekey: %s." + % paper.citekey) + else: + self.save_paper(paper) + else: + self.add_paper(paper) + # Eventually move document file + paper = PaperInRepo.from_paper(paper, self) + try: + path = self.find_document(old_citekey) + self.import_document(paper.citekey, path) + except NoDocumentFile: + pass + self.remove_paper(old_citekey, remove_doc=True) + def _move_doc(self, old_citekey, paper): """Fragile. Make more robust""" try: @@ -160,7 +193,7 @@ class Repository(object): def _metafile(self, citekey): return os.path.join(self.meta_dir, citekey + '.meta') - def remove_paper(self, citekey, remove_doc = True): + def remove_paper(self, citekey, remove_doc=True): paper = self.get_paper(citekey) self.citekeys.remove(citekey) os.remove(self._metafile(citekey))