Improves repo.py, adds tests. Still things to clean and decide...

main
Olivier Mangin 12 years ago
parent b08133bd1d
commit 1fad286517

@ -6,29 +6,24 @@ try:
except ImportError:
import configparser
from ..repo import Repository
from .. import color
from .. import files
def parser(subparsers, config):
parser = subparsers.add_parser('init', help="initialize the .papers directory")
return parser
def command(config):
"""Create a .papers directory"""
# create dir
papersdir = os.getcwd() + '/.papers'
if not os.path.exists(papersdir):
print('{}initializing papers in {}{}{}'.format(
color.grey, color.cyan, papersdir, color.end))
os.makedirs(os.path.join(papersdir, 'bibdata'))
os.makedirs(os.path.join(papersdir, 'meta'))
papers = {}
papers['citekeys'] = []
files.save_papers(papers)
repo = Repository(papersdir=papersdir)
repo.init() # Creates directories
repo.save() # Saves empty repository description
else:
print('{}error {} : papers already present in {}{}{}'.format(
color.red, color.grey, color.cyan, papersdir, color.end))

@ -98,34 +98,21 @@ def read_yamlfile(filepath):
exit(-1)
def save_papers(datamap):
paperyaml = find_papersdir() + os.sep + 'papers.yaml'
write_yamlfile(paperyaml, datamap)
def load_papers():
paperyaml = os.path.join(find_papersdir(), 'papers.yaml')
return read_yamlfile(paperyaml)
def load_bibdata(filename, filepath):
return load_externalbibfile(filepath)
def path_to_paper_file(name, file_, path_to_repo=None):
if path_to_repo is None:
path_to_repo = find_papersdir()
if file_ == 'bib':
return os.path.join(path_to_repo, 'bibdata', name + '.bibyaml')
elif file_ == 'meta':
return os.path.join(path_to_repo, 'meta', name + '.meta')
else:
raise(ValueError, "%s is not a valid paper file." % file_)
def save_bibdata(bib_data, filepath):
with open(filepath, 'w') as f:
parser = pybtex.database.output.bibyaml.Writer()
parser.write_stream(bib_data, f)
def save_meta(meta_data, filename, path=None):
filepath = path_to_paper_file(filename, 'meta', path_to_repo=path)
def save_meta(meta_data, filepath):
write_yamlfile(filepath, meta_data)
def load_meta(filename, path=None):
filepath = path_to_paper_file(filename, 'meta', path_to_repo=path)
def load_meta(filepath):
return read_yamlfile(filepath)
@ -152,18 +139,6 @@ def load_externalbibfile(fullbibpath):
return bib_data
def load_bibdata(filename, path=None):
filepath = path_to_paper_file(filename, 'bib', path_to_repo=path)
return load_externalbibfile(filepath)
def save_bibdata(bib_data, filename, path=None):
filepath = path_to_paper_file(filename, 'bib', path_to_repo=path)
with open(filepath, 'w') as f:
parser = pybtex.database.output.bibyaml.Writer()
parser.write_stream(bib_data, f)
# vim input
def vim_input(initial=""):

@ -37,16 +37,6 @@ class Paper(object):
biblography data and an additional dictionary to store meta data.
"""
@classmethod
def load(cls, bibpath, metapath):
bib_data = files.load_externalbibfile(bibpath)
metadata = files.read_yamlfile(metapath)
# Extract first entry (supposed to be the only one)
first_key = bib_data.entries.keys()[0]
first_entry = bib_data.entries[first_key]
p = Paper(bibentry=first_entry, metadata=metadata, citekey=first_key)
return p
# @classmethod
# def from_bibpdffiles(cls, pdfpath, bibpath):
# bib_data = cls.import_bibdata(bibpath)
@ -62,6 +52,9 @@ class Paper(object):
if not metadata:
metadata = Paper.create_meta()
self.metadata = metadata
# TODO This is not the right way to test that (17/12/2012)
if unicode(citekey) != str2citekey(citekey):
raise(ValueError, "Wrong citekey: %s" % citekey)
self.citekey = citekey
def __eq__(self, other):
@ -114,7 +107,7 @@ class Paper(object):
citekey = u'{}{}'.format(u''.join(first_author.last()), year)
return str2citekey(citekey)
def save_to_disc(self, path):
def save_to_disc(self, bib_filepath, meta_filepath):
"""Creates a BibliographyData object containing a single entry and
saves it to disc.
"""
@ -122,9 +115,18 @@ class Paper(object):
raise(ValueError,
'No valid citekey initialized. Cannot save paper')
bibdata = BibliographyData(entries={self.citekey: self.bibentry})
files.save_bibdata(bibdata, self.citekey, path=path)
files.save_meta(self.metadata, self.citekey, path=path)
# TODO move to repo
files.save_bibdata(bibdata, bib_filepath)
files.save_meta(self.metadata, meta_filepath)
@classmethod
def load(cls, bibpath, metapath):
bib_data = files.load_externalbibfile(bibpath)
metadata = files.read_yamlfile(metapath)
# Extract first entry (supposed to be the only one)
first_key = bib_data.entries.keys()[0]
first_entry = bib_data.entries[first_key]
p = Paper(bibentry=first_entry, metadata=metadata, citekey=first_key)
return p
@classmethod
def import_bibdata(cls, bibfile):

@ -1,21 +1,24 @@
import files
import color
import os
import files
from paper import Paper
ALPHABET = 'abcdefghijklmopqrstuvwxyz'
BASE_FILE = 'papers.yaml'
BIB_DIR = 'bibdata'
META_DIR = 'meta'
class Repository(object):
def __init__(self, paperdir=None):
if paperdir:
self.paperdir = paperdir
def __init__(self, papersdir=None):
if papersdir:
self.papersdir = papersdir
else:
self.paperdir = files.find_papersdir()
self.papers_config = files.load_papers()
self.citekeys = self.papers_config['citekeys']
self.papersdir = files.find_papersdir()
self.citekeys = []
# loading existing papers
@ -34,9 +37,10 @@ class Repository(object):
def paper_from_citekey(self, citekey, fatal=True):
"""Load a paper by its citekey from disk, if necessary."""
try:
return Paper.load(citekey)
except KeyError:
if citekey in self.citekeys:
return Paper.load(self.path_to_paper_file(citekey, 'bib'),
self.path_to_paper_file(citekey, 'meta'))
else:
if fatal:
print('{}error{}: no paper with citekey {}{}{}'.format(
color.error, color.normal, color.citekey, citekey,
@ -64,28 +68,36 @@ class Repository(object):
self.add_paper(p)
def add_paper(self, p):
# updating papersconfig
bib_data_entry = p.bib_data.entries[list(p.bib_data.entries.keys())[0]]
p.citekey = self.get_valid_citekey(bib_data_entry)
self.papers_config['citekeys'].append(p.citekey)
if p.citekey is None: # TODO also test if citekey is valid
raise(ValueError, "Invalid citekey: %s." % p.citekey)
elif p.citekey in self.citekeys:
raise(ValueError, "Citekey already exists in repository: %s"
% p.citekey)
self.citekeys.append(p.citekey)
# writing all to disk
# TODO Update by giving filename (17/12/2012)
p.save_to_disc()
files.save_papers(self.papers_config)
# write paper files
self.save_paper(p)
# update repository files
self.save()
# TODO change to logging system (17/12/2012)
print "Added: %s" % p.citekey
return p
def add_or_update(self, paper):
if not paper.citekey in self.citekeys:
self.add_paper(paper)
else:
paper.save_paper(paper)
def save_paper(self, paper):
if not paper.citekey in self.citekeys:
raise(ValueError, 'Paper not in repository, first add it.')
paper.save_to_disc(self.path_to_paper_file(paper.citekey, 'bib'),
self.path_to_paper_file(paper.citekey, 'meta'))
def add_papers(self, bibpath):
bib_data = Paper.import_bibdata(bibpath)
for k in bib_data.entries:
sub_bib = type(bib_data)(preamble=bib_data._preamble)
sub_bib.add_entry(k, bib_data.entries[k])
meta = Paper.create_meta(pdfpath=None)
name = meta['filename']
p = Paper(name, bib_data=sub_bib, metadata=meta)
p = Paper(bibentry=sub_bib, citekey=k)
self.add_paper(p)
def get_free_citekey(self, paper, citekey=None):
@ -93,14 +105,44 @@ class Repository(object):
"""
if citekey is None:
citekey = paper.generate_citekey()
suffix = ''
while citekey + suffix in self.citekeys:
_str_incr(suffix)
return citekey + suffix
num = []
while citekey + _to_suffix(num) in self.citekeys:
_str_incr(num)
return citekey + _to_suffix(num)
def base_file_path(self):
return os.path.join(self.papersdir, 'papers.yaml')
def size(self):
return len(self.citekeys)
def save(self):
papers_config = {'citekeys': self.citekeys}
files.write_yamlfile(self.base_file_path(), papers_config)
def load(self):
papers_config = files.read_yamlfile(self.base_file_path())
self.citekeys = papers_config['citekeys']
def init(self):
os.makedirs(os.path.join(self.papersdir, BIB_DIR))
os.makedirs(os.path.join(self.papersdir, META_DIR))
self.save()
def path_to_paper_file(self, citekey, file_):
if file_ == 'bib':
return os.path.join(self.papersdir, BIB_DIR, citekey + '.bibyaml')
elif file_ == 'meta':
return os.path.join(self.papersdir, META_DIR, citekey + '.meta')
else:
raise(ValueError, "%s is not a valid paper file." % file_)
@classmethod
def from_directory(cls, papersdir=None):
repo = cls.__init__(papersdir=papersdir)
repo.load()
return repo
def _char_incr(c):
return chr(ord(c) + 1)

@ -0,0 +1,17 @@
from pybtex.database import Person
from papers.paper import Paper
turing1950 = Paper()
turing1950.bibentry.fields['title'] = u'Computing machinery and intelligence.'
turing1950.bibentry.fields['year'] = u'1950'
turing1950.bibentry.persons['author'] = [Person(u'Alan Turing')]
turing1950.citekey = turing1950.generate_citekey()
doe2013 = Paper()
doe2013.bibentry.fields['title'] = u'Nice title.'
doe2013.bibentry.fields['year'] = u'2013'
doe2013.bibentry.persons['author'] = [Person(u'John Doe')]
doe2013.citekey = doe2013.generate_citekey()

@ -7,8 +7,8 @@ import shutil
import yaml
from pybtex.database import Person
import fixtures
from papers.paper import Paper
from papers import files
BIB = """
@ -64,50 +64,39 @@ class TestSaveLoad(unittest.TestCase):
self.metafile = os.path.join(self.tmpdir, 'meta.meta')
with open(self.metafile, 'w') as f:
f.write(META)
self.turing1950 = Paper()
self.turing1950.bibentry.fields['title'] = u'Computing machinery and intelligence.'
self.turing1950.bibentry.fields['year'] = u'1950'
self.turing1950.bibentry.persons['author'] = [Person(u'Alan Turing')]
self.turing1950.citekey = self.turing1950.generate_citekey()
self.dest_bibfile = os.path.join(self.tmpdir, 'written_bib.yaml')
self.dest_metafile = os.path.join(self.tmpdir, 'written_meta.yaml')
def test_load_valid(self):
p = Paper.load(self.bibfile, self.metafile)
self.assertEqual(self.turing1950, p)
self.assertEqual(fixtures.turing1950, p)
def test_save_fails_with_no_citekey(self):
p = Paper()
with self.assertRaises(ValueError):
p.save_to_disc(self.tmpdir)
p.save_to_disc(self.dest_bibfile, self.dest_metafile)
def test_save_creates_bib(self):
self.turing1950.save_to_disc(self.tmpdir)
bibfile = files.path_to_paper_file('Turing1950', 'bib',
path_to_repo=self.tmpdir)
self.assertTrue(os.path.exists(bibfile))
fixtures.turing1950.save_to_disc(self.dest_bibfile, self.dest_metafile)
self.assertTrue(os.path.exists(self.dest_bibfile))
def test_save_creates_meta(self):
self.turing1950.save_to_disc(self.tmpdir)
metafile = files.path_to_paper_file('Turing1950', 'meta',
path_to_repo=self.tmpdir)
self.assertTrue(os.path.exists(metafile))
fixtures.turing1950.save_to_disc(self.dest_bibfile, self.dest_metafile)
self.assertTrue(os.path.exists(self.dest_metafile))
def test_save_right_bib(self):
self.turing1950.save_to_disc(self.tmpdir)
bibfile = files.path_to_paper_file('Turing1950', 'bib',
path_to_repo=self.tmpdir)
with open(bibfile, 'r') as f:
fixtures.turing1950.save_to_disc(self.dest_bibfile, self.dest_metafile)
with open(self.dest_bibfile, 'r') as f:
written = yaml.load(f)
ok = yaml.load(BIB)
self.assertEqual(written, ok)
def test_save_right_meta(self):
self.turing1950.save_to_disc(self.tmpdir)
metafile = files.path_to_paper_file('Turing1950', 'meta',
path_to_repo=self.tmpdir)
with open(metafile, 'r') as f:
fixtures.turing1950.save_to_disc(self.dest_bibfile, self.dest_metafile)
with open(self.dest_metafile, 'r') as f:
written = yaml.load(f)
ok = yaml.load(META)
self.assertEqual(written, ok)
def teardown(self):
def tearDown(self):
shutil.rmtree(self.tmpdir)

@ -1,6 +1,10 @@
import unittest
import tempfile
import shutil
import os
from papers.repo import Repository, _str_incr, _to_suffix
import fixtures
from papers.repo import Repository, _str_incr, _to_suffix, BIB_DIR, META_DIR
class TestCitekeyGeneration(unittest.TestCase):
@ -17,4 +21,36 @@ class TestCitekeyGeneration(unittest.TestCase):
self.assertEqual(_to_suffix(l), 'aa')
def test_generated_key_is_unique(self):
pass
repo = Repository()
repo.add_paper(fixtures.turing1950)
repo.add_paper(fixtures.doe2013)
c = repo.get_free_citekey(fixtures.turing1950)
self.assertEqual(c, 'Turing1950a')
fixtures.turing1950.citekey = 'Turing1950a'
repo.add_paper(fixtures.turing1950)
c = repo.get_free_citekey(fixtures.turing1950)
self.assertEqual(c, 'Turing1950b')
class TestAddPaper(unittest.TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
self.repo = Repository(papersdir=self.tmpdir)
self.repo.init()
self.repo.add_paper(fixtures.turing1950)
def test_raises_value_error_on_existing_key(self):
with self.assertRaises(ValueError):
self.repo.add_paper(fixtures.turing1950)
def test_saves_bib(self):
self.assertTrue(os.path.exists(os.path.join(self.tmpdir, BIB_DIR,
'Turing1950.bibyaml')))
def test_saves_meta(self):
self.assertTrue(os.path.exists(os.path.join(self.tmpdir, META_DIR,
'Turing1950.meta')))
def tearDown(self):
shutil.rmtree(self.tmpdir)

Loading…
Cancel
Save