Change repo and removed the update function and the rename function. Now only the save_paper function must be used

main
jgrizou 12 years ago
parent 843d81a0e8
commit 7b555abf92

@ -5,9 +5,7 @@ import itertools
from . import files from . import files
from .paper import PaperInRepo, NoDocumentFile from .paper import PaperInRepo, NoDocumentFile
from . import configs from .events import RemoveEvent, RenameEvent
BASE_FILE = 'papers.yaml' BASE_FILE = 'papers.yaml'
BIB_DIR = 'bibdata' BIB_DIR = 'bibdata'
@ -25,7 +23,7 @@ class InvalidReference(Exception):
class Repository(object): class Repository(object):
def __init__(self, config, load = True): def __init__(self, config, load=True):
"""Initialize the repository. """Initialize the repository.
:param load: if load is True, load the repository from disk, :param load: if load is True, load the repository from disk,
@ -52,20 +50,18 @@ class Repository(object):
def __len__(self): def __len__(self):
return len(self.citekeys) return len(self.citekeys)
# load, save repo # load, save repo
def _init_dirs(self, autodoc=True):
def _init_dirs(self, autodoc = True):
"""Create, if necessary, the repository directories. """Create, if necessary, the repository directories.
Should only be called by load or save. Should only be called by load or save.
""" """
self.bib_dir = files.clean_path(self.config.papers_dir, BIB_DIR) self.bib_dir = files.clean_path(self.config.papers_dir, BIB_DIR)
self.meta_dir = files.clean_path(self.config.papers_dir, META_DIR) self.meta_dir = files.clean_path(self.config.papers_dir, META_DIR)
if self.config.doc_dir == 'doc': if self.config.doc_dir == 'doc':
self.doc_dir = files.clean_path(self.config.papers_dir, DOC_DIR) self.doc_dir = files.clean_path(self.config.papers_dir, DOC_DIR)
else: else:
self.doc_dir = files.clean_path(self.config.doc_dir) self.doc_dir = files.clean_path(self.config.doc_dir)
self.cfg_path = files.clean_path(self.config.papers_dir, 'papers.yaml') self.cfg_path = files.clean_path(self.config.papers_dir, 'papers.yaml')
for d in [self.bib_dir, self.meta_dir, self.doc_dir]: for d in [self.bib_dir, self.meta_dir, self.doc_dir]:
@ -84,9 +80,7 @@ class Repository(object):
repo_cfg = {'citekeys': self.citekeys} repo_cfg = {'citekeys': self.citekeys}
files.write_yamlfile(self.cfg_path, repo_cfg) files.write_yamlfile(self.cfg_path, repo_cfg)
# reference # reference
def ref2citekey(self, ref): def ref2citekey(self, ref):
"""Tries to get citekey from given reference. """Tries to get citekey from given reference.
Ref can be a citekey or a number. Ref can be a citekey or a number.
@ -99,9 +93,7 @@ class Repository(object):
except (IndexError, ValueError): except (IndexError, ValueError):
raise InvalidReference raise InvalidReference
# papers # papers
def all_papers(self): def all_papers(self):
for key in self.citekeys: for key in self.citekeys:
yield self.get_paper(key) yield self.get_paper(key)
@ -109,12 +101,10 @@ class Repository(object):
def get_paper(self, citekey): def get_paper(self, citekey):
"""Load a paper by its citekey from disk, if necessary.""" """Load a paper by its citekey from disk, if necessary."""
return PaperInRepo.load(self, self._bibfile(citekey), return PaperInRepo.load(self, self._bibfile(citekey),
self._metafile(citekey)) self._metafile(citekey))
# add, remove papers # add, remove papers
def add_paper(self, p, overwrite=False):
def add_paper(self, p, overwrite = False):
if p.citekey is None: # TODO also test if citekey is valid if p.citekey is None: # TODO also test if citekey is valid
raise ValueError("Invalid citekey: {}.".format(p.citekey)) raise ValueError("Invalid citekey: {}.".format(p.citekey))
if not overwrite and p.citekey in self.citekeys: if not overwrite and p.citekey in self.citekeys:
@ -128,53 +118,22 @@ class Repository(object):
print('Added: {}'.format(p.citekey)) print('Added: {}'.format(p.citekey))
return p return p
def rename_paper(self, paper, new_citekey, overwrite=False): def save_paper(self, paper, old_citekey=None, overwrite=False):
"""Modify the citekey of a paper, and propagate changes to disk""" if (not paper.citekey in self.citekeys and
if paper.citekey not in self: not old_citekey in self.citekeys):
raise ValueError( raise ValueError('Paper not in repository, first add it.')
'paper {} not in repository'.format(paper.citekey)) if old_citekey is None or old_citekey == paper.citekey:
if (not overwrite and paper.citekey != new_citekey paper.save(self._bibfile(paper.citekey),
and new_citekey in self): self._metafile(paper.citekey))
raise CiteKeyCollision('citekey {} already in use'.format( else: # paper has changed citekey, raise RenameEvent
new_citekey)) if (not overwrite and paper.citekey in self.citekeys):
raise CiteKeyCollision('citekey {} already in use'.format(
self.remove_paper(paper.citekey, remove_doc = False) paper.citekey))
old_citekey = paper.citekey
paper.citekey = new_citekey RenameEvent(old_citekey, paper.citekey)
self.add_paper(paper, overwrite = overwrite) self._remove_paper(old_citekey, remove_doc=False)
self._move_doc(old_citekey, paper) 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): def _move_doc(self, old_citekey, paper):
"""Fragile. Make more robust""" """Fragile. Make more robust"""
@ -194,6 +153,12 @@ class Repository(object):
return os.path.join(self.meta_dir, citekey + '.meta') 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):
RemoveEvent(citekey).send()
self._remove_paper(citekey, remove_doc)
def _remove_paper(self, citekey, remove_doc=True):
""" This version of remove is not meant to be accessed from outside.
It removes paper without raising the Remove Event"""
paper = self.get_paper(citekey) paper = self.get_paper(citekey)
self.citekeys.remove(citekey) self.citekeys.remove(citekey)
os.remove(self._metafile(citekey)) os.remove(self._metafile(citekey))
@ -209,12 +174,6 @@ class Repository(object):
self.save() self.save()
def save_paper(self, paper):
if not paper.citekey in self:
raise ValueError('Paper not in repository, first add it.')
paper.save(self._bibfile(paper.citekey),
self._metafile(paper.citekey))
def generate_citekey(self, paper, citekey=None): def generate_citekey(self, paper, citekey=None):
"""Create a unique citekey for the given paper.""" """Create a unique citekey for the given paper."""
if citekey is None: if citekey is None:
@ -247,10 +206,9 @@ class Repository(object):
return tags return tags
def _base27(n): def _base27(n):
return _base27((n-1) // 26) + chr(97+((n-1)% 26)) if n else '' return _base27((n - 1) // 26) + chr(ord('a') + ((n - 1) % 26)) if n else ''
def _base(num, b): def _base(num, b):
q, r = divmod(num - 1, len(b)) q, r = divmod(num - 1, len(b))

@ -3,23 +3,22 @@ import tempfile
import shutil import shutil
import os import os
import testenv
import fixtures import fixtures
from papers.repo import (Repository, _base27, BIB_DIR, META_DIR, from papers.repo import (Repository, _base27, BIB_DIR, META_DIR,
CiteKeyCollision) CiteKeyCollision)
from papers.paper import PaperInRepo from papers.paper import PaperInRepo
from papers import configs, files from papers import configs, files
class TestCitekeyGeneration(unittest.TestCase):
class TestCitekeyGeneration(unittest.TestCase):
def test_string_increment(self): def test_string_increment(self):
self.assertEqual(_base27(0), '') self.assertEqual(_base27(0), '')
for i in range(26): for i in range(26):
self.assertEqual(_base27(i+1), chr(97+i)) self.assertEqual(_base27(i + 1), chr(97 + i))
self.assertEqual(_base27(26+i+1), 'a' + chr(97+i)) self.assertEqual(_base27(26 + i + 1), 'a' + chr(97 + i))
def test_generated_key_is_unique(self): def test_generated_key_is_unique(self):
repo = Repository(configs.Config(), load = False) repo = Repository(configs.Config(), load=False)
repo.citekeys = ['Turing1950', 'Doe2003'] repo.citekeys = ['Turing1950', 'Doe2003']
c = repo.generate_citekey(fixtures.turing1950) c = repo.generate_citekey(fixtures.turing1950)
repo.citekeys.append('Turing1950a') repo.citekeys.append('Turing1950a')
@ -31,7 +30,7 @@ class TestRepo(unittest.TestCase):
def setUp(self): def setUp(self):
self.tmpdir = tempfile.mkdtemp() self.tmpdir = tempfile.mkdtemp()
self.repo = Repository(configs.Config(papers_dir = self.tmpdir), load = False) self.repo = Repository(configs.Config(papers_dir=self.tmpdir), load=False)
self.repo.save() self.repo.save()
self.repo.add_paper(fixtures.turing1950) self.repo.add_paper(fixtures.turing1950)
@ -64,12 +63,12 @@ class TestUpdatePaper(TestRepo):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
self.repo.save_paper(fixtures.doe2013) self.repo.save_paper(fixtures.doe2013)
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
self.repo.rename_paper(fixtures.doe2013, 'zou') self.repo.save_paper(fixtures.doe2013, 'zou')
def test_error_on_existing_destination(self): def test_error_on_existing_destination(self):
self.repo.add_paper(fixtures.doe2013) self.repo.add_paper(fixtures.doe2013)
with self.assertRaises(CiteKeyCollision): with self.assertRaises(CiteKeyCollision):
self.repo.rename_paper(fixtures.turing1950, 'Doe2013') self.repo.save_paper(fixtures.turing1950, old_citekey='Doe2013')
def test_updates_same_key(self): def test_updates_same_key(self):
new = self.repo.get_paper('Turing1950') new = self.repo.get_paper('Turing1950')
@ -80,13 +79,14 @@ class TestUpdatePaper(TestRepo):
def test_updates_same_key_with_old_arg(self): def test_updates_same_key_with_old_arg(self):
new = self.repo.get_paper('Turing1950') new = self.repo.get_paper('Turing1950')
new.bibentry.fields['journal'] = u'Mind' new.bibentry.fields['journal'] = u'Mind'
self.repo.rename_paper(new, 'Turing1950') self.repo.save_paper(new, old_citekey='Turing1950')
self.assertEqual(new, self.repo.get_paper('Turing1950')) self.assertEqual(new, self.repo.get_paper('Turing1950'))
def test_update_new_key_removes_old(self): def test_update_new_key_removes_old(self):
self.repo.add_paper(fixtures.doe2013) self.repo.add_paper(fixtures.doe2013)
self.repo.rename_paper(fixtures.doe2013, 'JohnDoe2003') fixtures.doe2013.update(key='JohnDoe2003')
self.assertFalse('Doe2003' in self.repo) self.repo.save_paper(fixtures.doe2013, old_citekey='Doe2013')
self.assertFalse('Doe2013' in self.repo)
def test_update_new_key_updates(self): def test_update_new_key_updates(self):
# self.repo.rename(fixtures.doe2013, old_citekey='Turing1950') # self.repo.rename(fixtures.doe2013, old_citekey='Turing1950')
@ -100,7 +100,9 @@ class TestUpdatePaper(TestRepo):
self.repo.import_document('Turing1950', self.repo.import_document('Turing1950',
os.path.join(os.path.dirname(__file__), os.path.join(os.path.dirname(__file__),
'data/pagerank.pdf')) 'data/pagerank.pdf'))
self.repo.rename_paper(self.repo.get_paper('Turing1950'), 'Doe2003') paper = self.repo.get_paper('Turing1950')
paper.update('Doe2003')
self.repo.save_paper(paper, old_citekey='Turing1950')
self.assertFalse(os.path.exists(os.path.join( self.assertFalse(os.path.exists(os.path.join(
self.repo.doc_dir, 'Turing1950.pdf'))) self.repo.doc_dir, 'Turing1950.pdf')))
self.assertTrue(os.path.exists(os.path.join( self.assertTrue(os.path.exists(os.path.join(

Loading…
Cancel
Save