Improves repo.py, adds tests. Still things to clean and decide...
This commit is contained in:
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_bibdata(filename, filepath):
|
||||
return load_externalbibfile(filepath)
|
||||
|
||||
|
||||
def load_papers():
|
||||
paperyaml = os.path.join(find_papersdir(), 'papers.yaml')
|
||||
return read_yamlfile(paperyaml)
|
||||
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 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_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):
|
||||
|
100
papers/repo.py
100
papers/repo.py
@ -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)
|
||||
|
17
tests/fixtures.py
Normal file
17
tests/fixtures.py
Normal file
@ -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…
x
Reference in New Issue
Block a user