From b413be687d545ebb5210052375b91d67a7df6852 Mon Sep 17 00:00:00 2001 From: Fabien Benureau Date: Wed, 10 Oct 2012 16:33:17 +0200 Subject: [PATCH 1/5] imcomplete implementation of Repository, Paper classes --- papers/commands/add_cmd.py | 7 +- papers/commands/init_cmd.py | 2 +- papers/commands/list_cmd.py | 21 +++--- papers/commands/open_cmd.py | 29 +++----- papers/files.py | 2 +- papers/paper.py | 23 +++++++ papers/pretty.py | 30 --------- papers/repo.py | 130 ++++++++++++++++++++++++++++++++++++ 8 files changed, 176 insertions(+), 68 deletions(-) create mode 100644 papers/paper.py create mode 100644 papers/repo.py diff --git a/papers/commands/add_cmd.py b/papers/commands/add_cmd.py index d870d3a..b73d599 100644 --- a/papers/commands/add_cmd.py +++ b/papers/commands/add_cmd.py @@ -7,6 +7,7 @@ except ImportError: from .. import color from .. import files from .. import pretty +from .. import repo def parser(subparsers, config): @@ -28,7 +29,7 @@ def command(config, pdffile, bibfile): files.check_file(fullbibpath) filename, ext = os.path.splitext(os.path.split(fullpdfpath)[1]) - if ext != '.pdf' and ext != '.ps': + if ext != '.pdf' and ext != '.ps': print('{}warning{}: extention {}{}{} not recognized{}'.format( color.yellow, color.grey, color.cyan, ext, color.grey, color.end)) @@ -53,8 +54,8 @@ def command(config, pdffile, bibfile): papers.set('header', 'count', int(count) + 1) citekey = pretty.create_citekey(bib_data) - papers.set('papers', citekey, filename) - papers.set('citekeys', 'ck' + count, citekey) + papers.set('citekeys', citekey, filename) + papers.set('numbers', 'ck' + count, citekey) files.write_papers(papers) files.write_meta(meta, filename) diff --git a/papers/commands/init_cmd.py b/papers/commands/init_cmd.py index 136c7bb..f38bc5e 100644 --- a/papers/commands/init_cmd.py +++ b/papers/commands/init_cmd.py @@ -29,8 +29,8 @@ def command(config): papers = configparser.ConfigParser() papers.add_section('header') papers.set('header', 'count', 0) - papers.add_section('papers') papers.add_section('citekeys') + papers.add_section('numbers') files.write_papers(papers) else: diff --git a/papers/commands/list_cmd.py b/papers/commands/list_cmd.py index f3e0dfe..fe8da92 100644 --- a/papers/commands/list_cmd.py +++ b/papers/commands/list_cmd.py @@ -1,24 +1,21 @@ -from .. import files -from .. import pretty -from .. import color - import subprocess import tempfile +from .. import pretty +from .. import color +from .. import repo + def parser(subparsers, config): parser = subparsers.add_parser('list', help="list all papers") return parser def command(config): - papers = files.load_papers() - + rp = repo.Repository() + articles = [] - for p in papers.options('citekeys'): - number = p[2:] - citekey = papers.get('citekeys', p) - filename = papers.get('papers', citekey) - bibdata = files.load_bibdata(filename + '.bibyaml') - bibdesc = pretty.bib_oneliner(bibdata) + for n in rp.numbers: + paper = paper_from_number(n, fatal = True) + bibdesc = pretty.bib_oneliner(paper.bibdata) articles.append('{:3d} {}{}{}{} {}'.format(int(number), color.purple, citekey, color.end, (8-len(citekey))*' ', bibdesc)) with tempfile.NamedTemporaryFile(suffix=".tmp", delete=True) as tmpf: diff --git a/papers/commands/open_cmd.py b/papers/commands/open_cmd.py index 983da8a..9780751 100644 --- a/papers/commands/open_cmd.py +++ b/papers/commands/open_cmd.py @@ -1,30 +1,17 @@ -try: - import ConfigParser as configparser -except ImportError: - import configparser import subprocess -from .. import files from .. import color +from .. import repo def parser(subparsers, config): - parser = subparsers.add_parser('open', help="open the paper in a pdf viewer") - parser.add_argument("citekey", help="the paper associated citekey") + parser = subparsers.add_parser('open', help='{}open the paper in a pdf viewer{}'.format(color.normal, color.end)) + parser.add_argument('citekey', help='{}the paper associated citekey{}'.format(color.normal, color.end)) return parser def command(config, citekey): - papers = files.load_papers() - try: - filename = papers.get('papers', str(citekey)) - except configparser.NoOptionError: - try: - ck = papers.get('citekeys', 'ck'+str(citekey)) - filename = papers.get('papers', str(ck)) - except configparser.NoOptionError: - print('{}error{}: paper with citekey or number {}{}{} not found{}'.format( - color.red, color.grey, color.cyan, citekey, color.grey, color.end)) - exit(-1) - meta_data = files.load_meta(filename) - filepath = meta_data.get('metadata', 'path') + rp = repo.Repository() + paper = rp.paper_from_any(citekey, fatal = True) + filepath = paper.metadata.get('metadata', 'path') + p = subprocess.Popen(['open', filepath]) - print('{}{}{} opened.{}'.format(color.cyan, filepath, color.grey, color.end)) \ No newline at end of file + print('{}{}{} opened.{}'.format(color.filepath, filepath, color.normal, color.end)) \ No newline at end of file diff --git a/papers/files.py b/papers/files.py index bbe2ef4..8245c9a 100644 --- a/papers/files.py +++ b/papers/files.py @@ -110,7 +110,7 @@ def load_papers(): return read_configfile(find_papersdir() + os.sep + 'papers') def load_bibdata(filename): - fullbibpath = find_papersdir() + os.sep + 'bibdata' + os.sep + filename + fullbibpath = find_papersdir() + os.sep + 'bibdata' + os.sep + filename + '.bibyaml' return load_externalbibfile(fullbibpath) def write_bibdata(bib_data, filename): diff --git a/papers/paper.py b/papers/paper.py new file mode 100644 index 0000000..305d0ed --- /dev/null +++ b/papers/paper.py @@ -0,0 +1,23 @@ +import files +import color + +class Paper(object): + """Paper class. The object is responsible for the integrity of its own data, + and for loading and writing it to disc. + """ + + @classmethod + def from_disc(cls, name): + p = Paper(name) + self.bib_data = files.load_bibdata(self.name) + self.metadata = files.load_meta(self.name) + self.citekey = self.metadata.get('metadata', 'citekey') + self.number = self.metadata.get('metadata', 'number') + return p + + def __init__(self, name): + self.name = name + + + + diff --git a/papers/pretty.py b/papers/pretty.py index 9b48790..bbad9aa 100644 --- a/papers/pretty.py +++ b/papers/pretty.py @@ -26,33 +26,3 @@ def bib_desc(bib_data): s += '\n' s += '\n'.join('{}: {}'.format(k, v) for k, v in article.fields.items()) return s - -alphabet = 'abcdefghijklmopqrstuvwxyz' - -try: - import ConfigParser as configparser -except ImportError: - import configparser -import files - -def create_citekey(bib_data): - """Create a cite key unique to the paper""" - article = bib_data.entries[list(bib_data.entries.keys())[0]] - first_author = article.persons['author'][0] - year = article.fields['year'] - prefix = '{}{}'.format(first_author.last()[0][:6], year[2:]) - - papers = files.load_papers() - letter = 0, False - citekey = None - - citekey = prefix - while not letter[1]: - try: - papers.get('papers', citekey) - citekey = prefix + alphabet[letter[0]] - letter = letter[0]+1, False - except configparser.NoOptionError: - letter = letter[0], True - - return citekey diff --git a/papers/repo.py b/papers/repo.py new file mode 100644 index 0000000..cf436ae --- /dev/null +++ b/papers/repo.py @@ -0,0 +1,130 @@ +try: + import ConfigParser as configparser +except ImportError: + import configparser + +from paper import Paper + +alphabet = 'abcdefghijklmopqrstuvwxyz' + + +class Repository(object): + + def __init__(self): + self.paperdir = files.find_papersdir() + self.papers_config = files.load_papers() + self.citekeys = dict(ck, None for ck in self.paper_config.options('citekeys') + self.numbers = sorted(n[2:] for n in self.paper_config.options('numbers')) + + # loading existing papers + + def paper_from_number(self, number, fatal = True): + try: + citekey = self.papers_config.get('numbers', 'ck'+number) + return self.load_paper(citekey) + except configparser.NoOptionError: + if fatal: + print('{}error{}: no paper with number {}{}{}'.format( + color.error, color.normal, color.citekey, citekey, color.end) + exit(-1) + raise IOError, 'file not found' + + def paper_from_citekey(self, citekey, fatal = True): + """Load a paper by its citekey from disk, if necessary.""" + try: + paper = self.citekeys[citekey] + if paper is None: + name = self.papers_config.get('citekeys', citekey) + paper = Paper.from_disc(name) + self.citekeys[citekey] = paper + return paper + except KeyError: + if fatal: + print('{}error{}: no paper with citekey {}{}{}'.format( + color.error, color.normal, color.citekey, citekey, color.end) + exit(-1) + raise IOError, 'file not found' + + def paper_from_any(self, key, fatal = True): + try: + return rp.paper_from_citekey(key, fatal = False) + except IOError: + try: + return rp.paper_from_number(key, fatal = False) + except IOError: + if fatal: + print('{}error{}: paper with citekey or number {}{}{} not found{}'.format( + color.error, color.normal, color.citekey, key, color.normal, color.end)) + exit(-1) + raise IOError, 'file not found' + + # creating new papers + + def add_paper(self, pdffile, bibfile): + + fullpdfpath = os.path.abspath(pdffile) + fullbibpath = os.path.abspath(bibfile) + files.check_file(fullpdfpath) + files.check_file(fullbibpath) + + name, ext = os.path.splitext(os.path.split(fullpdfpath)[1]) + if ext != '.pdf' and ext != '.ps': + print('{}warning{}: extension {}{}{} not recognized{}'.format( + color.yellow, color.grey, color.cyan, ext, color.grey, color.end)) + + # creating meta file + meta = create_meta(fullpdfpath, name, ext, bib_data) + + # creating bibyaml file + bib_data = files.load_externalbibfile(fullbibpath) + print('{}bibliographic data present in {}{}{}'.format( + color.grey, color.cyan, bibfile, color.end)) + print(pretty.bib_desc(bib_data)) + + # updating papersconfig + citekey = pretty.create_citekey(bib_data) + papers.set('citekeys', citekey, name) + papers.set('numbers', 'ck' + count, citekey) + + # writing all to disk + files.write_bibdata(bib_data, name) + files.write_papers(papers) + files.write_meta(meta, name) + + def create_meta(self, path, name, ext, bib_data): + citekey = create_citekey(bib_data, allowed = (,)) + number = create_number() + + meta = configparser.ConfigParser() + meta.add_section('metadata') + + meta.set('metadata', 'name', name) + meta.set('metadata', 'extension', ext) + meta.set('metadata', 'path', os.path.normpath(fullpdfpath)) + + meta.add_section('notes') + + return meta + + def create_citekey(self, bib_data, allowed = (,)): + """Create a cite key unique to a given bib_data""" + article = bib_data.entries[list(bib_data.entries.keys())[0]] + first_author = article.persons['author'][0] + year = article.fields['year'] + prefix = '{}{}'.format(first_author.last()[0][:6], year[2:]) + + letter = 0, False + citekey = None + + citekey = prefix + while citekey in self.citekeys and citekey not in allowed: + citekey = prefix + alphabet[letter[0]] + letter += 1 + + return citekey + + def create_number(self, bib_data, allowed = []): + count = self.papers_config.get('header', 'count') + self.papers_config.set('header', 'count', count + 1) + return count + \ No newline at end of file From cdd27966389e82863b0aa6d3eb4dd406a1288027 Mon Sep 17 00:00:00 2001 From: Fabien Benureau Date: Thu, 11 Oct 2012 09:26:46 +0200 Subject: [PATCH 2/5] finished implementing the classes a lowercase bug remain that force to move to another format than configparser. Which is just as well. --- .pit/pit-ac8c05c020d251c6 | 15 +++++++ papers/commands/add_cmd.py | 40 +---------------- papers/commands/list_cmd.py | 4 +- papers/files.py | 7 +++ papers/paper.py | 67 +++++++++++++++++++++++---- papers/repo.py | 90 ++++++++++++++----------------------- 6 files changed, 118 insertions(+), 105 deletions(-) create mode 100644 .pit/pit-ac8c05c020d251c6 diff --git a/.pit/pit-ac8c05c020d251c6 b/.pit/pit-ac8c05c020d251c6 new file mode 100644 index 0000000..14a1e05 --- /dev/null +++ b/.pit/pit-ac8c05c020d251c6 @@ -0,0 +1,15 @@ +[header] +title = remove configparser for internal mapping +id = ac8c05c020d251c6fa9ac5fc239038837b636b3b +status = open +type = bug +author = Fabien Benureau +mail = fabien.benureau+git@gmail.com +date = 2012-10-11 at 07:25 UCT + +[eventlog] +opened[0] = opened the 2012-10-11 at 07:25 UCT by Fabien Benureau + +[discussion] +desc = # enter your description here + diff --git a/papers/commands/add_cmd.py b/papers/commands/add_cmd.py index b73d599..0a0e55c 100644 --- a/papers/commands/add_cmd.py +++ b/papers/commands/add_cmd.py @@ -21,41 +21,5 @@ def command(config, pdffile, bibfile): :param pdffilepath path (no url yet) to a pdf or ps file :param bibtex bibtex file (in .bib, .bibml or .yaml format. """ - papersdir = files.find_papersdir() - - fullpdfpath = os.path.abspath(pdffile) - fullbibpath = os.path.abspath(bibfile) - files.check_file(fullpdfpath) - files.check_file(fullbibpath) - - filename, ext = os.path.splitext(os.path.split(fullpdfpath)[1]) - if ext != '.pdf' and ext != '.ps': - print('{}warning{}: extention {}{}{} not recognized{}'.format( - color.yellow, color.grey, color.cyan, ext, color.grey, color.end)) - - meta = configparser.ConfigParser() - meta.add_section('metadata') - - meta.set('metadata', 'filename', filename) - meta.set('metadata', 'extension', ext) - meta.set('metadata', 'path', os.path.normpath(fullpdfpath)) - - meta.add_section('notes') - - if bibfile is not None: - bib_data = files.load_externalbibfile(fullbibpath) - print('{}bibliographic data present in {}{}{}'.format( - color.grey, color.cyan, bibfile, color.end)) - print(pretty.bib_desc(bib_data)) - files.write_bibdata(bib_data, filename) - - papers = files.load_papers() - count = papers.get('header', 'count') - papers.set('header', 'count', int(count) + 1) - - citekey = pretty.create_citekey(bib_data) - papers.set('citekeys', citekey, filename) - papers.set('numbers', 'ck' + count, citekey) - - files.write_papers(papers) - files.write_meta(meta, filename) + rp = repo.Repository() + rp.add_paper(pdffile, bibfile) \ No newline at end of file diff --git a/papers/commands/list_cmd.py b/papers/commands/list_cmd.py index fe8da92..fc19cc3 100644 --- a/papers/commands/list_cmd.py +++ b/papers/commands/list_cmd.py @@ -14,9 +14,9 @@ def command(config): articles = [] for n in rp.numbers: - paper = paper_from_number(n, fatal = True) + paper = rp.paper_from_number(n, fatal = True) bibdesc = pretty.bib_oneliner(paper.bibdata) - articles.append('{:3d} {}{}{}{} {}'.format(int(number), color.purple, citekey, color.end, (8-len(citekey))*' ', bibdesc)) + articles.append('{:3d} {}{}{}{} {}'.format(int(paper.number), color.purple, citekey, color.end, (8-len(paper.citekey))*' ', bibdesc)) with tempfile.NamedTemporaryFile(suffix=".tmp", delete=True) as tmpf: tmpf.write('\n'.join(articles)) diff --git a/papers/files.py b/papers/files.py index 8245c9a..7673e39 100644 --- a/papers/files.py +++ b/papers/files.py @@ -49,6 +49,13 @@ def find_papersdir(): return _papersdir +def name_from_path(fullpdfpath, verbose = False): + name, ext = os.path.splitext(os.path.split(fullpdfpath)[1]) + if verbose: + if ext != '.pdf' and ext != '.ps': + print('{}warning{}: extension {}{}{} not recognized{}'.format( + color.yellow, color.grey, color.cyan, ext, color.grey, color.end)) + return name, ext def check_file(filepath): if not os.path.exists(filepath): diff --git a/papers/paper.py b/papers/paper.py index 305d0ed..19ad81f 100644 --- a/papers/paper.py +++ b/papers/paper.py @@ -1,5 +1,12 @@ +import os +try: + import ConfigParser as configparser +except ImportError: + import configparser + import files import color +import pretty class Paper(object): """Paper class. The object is responsible for the integrity of its own data, @@ -7,17 +14,61 @@ class Paper(object): """ @classmethod - def from_disc(cls, name): - p = Paper(name) - self.bib_data = files.load_bibdata(self.name) - self.metadata = files.load_meta(self.name) - self.citekey = self.metadata.get('metadata', 'citekey') - self.number = self.metadata.get('metadata', 'number') + def from_disc(cls, name, citekey = None, number = None): + bib_data = files.load_bibdata(self.name) + metadata = files.load_meta(self.name) + p = Paper(name, bib_data = bib_data, metadata = metadata, + citekey = citekey, number = number) return p - def __init__(self, name): - self.name = name + @classmethod + def from_bibpdffiles(cls, pdfpath, bibpath): + bib_data = cls.import_bibdata(bibpath) + name, meta = cls.import_meta(pdfpath, bib_data) + p = Paper(name, bib_data = bib_data, metadata = meta) + return p + + def __init__(self, name, bib_data = None, metadata = None, + citekey = None, number = None): + self.name = name + self.bib_data = bib_data + self.metadata = metadata + self.citekey = citekey + self.number = number + + def save_to_disc(self): + files.write_bibdata(self.bib_data, self.name) + files.write_meta(self.metadata, self.name) + + @classmethod + def import_bibdata(cls, bibfile): + """Import bibligraphic data from a .bibyaml, .bib or .bibtex file""" + fullbibpath = os.path.abspath(bibfile) + files.check_file(fullbibpath) + bib_data = files.load_externalbibfile(fullbibpath) + print('{}bibliographic data present in {}{}{}'.format( + color.grey, color.cyan, bibfile, color.end)) + print(pretty.bib_desc(bib_data)) + return bib_data + @classmethod + def import_meta(cls, pdfpath, bib_data): + + fullpdfpath = os.path.abspath(pdfpath) + files.check_file(fullpdfpath) + + name, ext = files.name_from_path(pdfpath) + + meta = configparser.ConfigParser() + meta.add_section('metadata') + + meta.set('metadata', 'name', name) + meta.set('metadata', 'extension', ext) + meta.set('metadata', 'path', os.path.normpath(fullpdfpath)) + + meta.add_section('notes') + + return name, meta diff --git a/papers/repo.py b/papers/repo.py index cf436ae..405691b 100644 --- a/papers/repo.py +++ b/papers/repo.py @@ -3,6 +3,8 @@ try: except ImportError: import configparser +import files +import color from paper import Paper alphabet = 'abcdefghijklmopqrstuvwxyz' @@ -13,19 +15,19 @@ class Repository(object): def __init__(self): self.paperdir = files.find_papersdir() self.papers_config = files.load_papers() - self.citekeys = dict(ck, None for ck in self.paper_config.options('citekeys') - self.numbers = sorted(n[2:] for n in self.paper_config.options('numbers')) + self.citekeys = dict((ck, name) for ck, name in self.papers_config.items('citekeys')) + self.numbers = sorted(n[2:] for n in self.papers_config.options('numbers')) # loading existing papers def paper_from_number(self, number, fatal = True): try: citekey = self.papers_config.get('numbers', 'ck'+number) - return self.load_paper(citekey) + return self.paper_from_citekey(citekey) except configparser.NoOptionError: if fatal: print('{}error{}: no paper with number {}{}{}'.format( - color.error, color.normal, color.citekey, citekey, color.end) + color.error, color.normal, color.citekey, citekey, color.end)) exit(-1) raise IOError, 'file not found' @@ -35,22 +37,22 @@ class Repository(object): paper = self.citekeys[citekey] if paper is None: name = self.papers_config.get('citekeys', citekey) - paper = Paper.from_disc(name) - self.citekeys[citekey] = paper - return paper + paper = Paper.from_disc(name, citekey = citekey) + self.citekeys[citekey] = paper + return paper except KeyError: if fatal: print('{}error{}: no paper with citekey {}{}{}'.format( - color.error, color.normal, color.citekey, citekey, color.end) + color.error, color.normal, color.citekey, citekey, color.end)) exit(-1) raise IOError, 'file not found' def paper_from_any(self, key, fatal = True): try: - return rp.paper_from_citekey(key, fatal = False) + return self.paper_from_citekey(key, fatal = False) except IOError: try: - return rp.paper_from_number(key, fatal = False) + return self.paper_from_number(key, fatal = False) except IOError: if fatal: print('{}error{}: paper with citekey or number {}{}{} not found{}'.format( @@ -60,53 +62,28 @@ class Repository(object): # creating new papers - def add_paper(self, pdffile, bibfile): - - fullpdfpath = os.path.abspath(pdffile) - fullbibpath = os.path.abspath(bibfile) - files.check_file(fullpdfpath) - files.check_file(fullbibpath) - - name, ext = os.path.splitext(os.path.split(fullpdfpath)[1]) - if ext != '.pdf' and ext != '.ps': - print('{}warning{}: extension {}{}{} not recognized{}'.format( - color.yellow, color.grey, color.cyan, ext, color.grey, color.end)) - - # creating meta file - meta = create_meta(fullpdfpath, name, ext, bib_data) - - # creating bibyaml file - bib_data = files.load_externalbibfile(fullbibpath) - print('{}bibliographic data present in {}{}{}'.format( - color.grey, color.cyan, bibfile, color.end)) - print(pretty.bib_desc(bib_data)) - - # updating papersconfig - citekey = pretty.create_citekey(bib_data) - papers.set('citekeys', citekey, name) - papers.set('numbers', 'ck' + count, citekey) + def add_paper(self, pdfpath, bibpath): + p = Paper.from_bibpdffiles(pdfpath, bibpath) + + # updating papersconfig + p.citekey = self.create_citekey(p.bib_data) + p.number = self.create_number() + + self.papers_config.set('citekeys', p.citekey, p.name) + self.papers_config.set('numbers', 'ck' + str(p.number), p.citekey) + + self.citekeys[p.citekey] = p.name + self.numbers.append(str(p.number)) + self.numbers.sort() + # writing all to disk - files.write_bibdata(bib_data, name) - files.write_papers(papers) - files.write_meta(meta, name) + files.write_papers(self.papers_config) + p.save_to_disc() - def create_meta(self, path, name, ext, bib_data): - citekey = create_citekey(bib_data, allowed = (,)) - number = create_number() - - meta = configparser.ConfigParser() - meta.add_section('metadata') - - meta.set('metadata', 'name', name) - meta.set('metadata', 'extension', ext) - meta.set('metadata', 'path', os.path.normpath(fullpdfpath)) - - meta.add_section('notes') - - return meta + return p - def create_citekey(self, bib_data, allowed = (,)): + def create_citekey(self, bib_data, allowed = tuple()): """Create a cite key unique to a given bib_data""" article = bib_data.entries[list(bib_data.entries.keys())[0]] first_author = article.persons['author'][0] @@ -123,8 +100,7 @@ class Repository(object): return citekey - def create_number(self, bib_data, allowed = []): - count = self.papers_config.get('header', 'count') + def create_number(self): + count = self.papers_config.getint('header', 'count') self.papers_config.set('header', 'count', count + 1) - return count - \ No newline at end of file + return count \ No newline at end of file From 09b737b2103fe2f19abad21201272589157588b8 Mon Sep 17 00:00:00 2001 From: Fabien Benureau Date: Thu, 11 Oct 2012 19:57:56 +0200 Subject: [PATCH 3/5] removed configparser in favor of yaml --- .pit/pit-956ed1a521100b3b | 3 +- .pit/pit-ac8c05c020d251c6 | 3 +- papers/commands/init_cmd.py | 11 ++++--- papers/commands/list_cmd.py | 6 ++-- papers/commands/open_cmd.py | 2 +- papers/files.py | 57 ++++++++++++++++++++----------------- papers/paper.py | 28 +++++++----------- papers/repo.py | 38 +++++++++++-------------- 8 files changed, 71 insertions(+), 77 deletions(-) diff --git a/.pit/pit-956ed1a521100b3b b/.pit/pit-956ed1a521100b3b index b4faf58..4dac007 100644 --- a/.pit/pit-956ed1a521100b3b +++ b/.pit/pit-956ed1a521100b3b @@ -1,7 +1,7 @@ [header] title = citekey support id = 956ed1a521100b3b0bb0638f61b3b5a03204ffa6 -status = open +status = closed type = feature author = Fabien Benureau mail = fabien.benureau+git@gmail.com @@ -9,6 +9,7 @@ date = 2012-10-05 at 15:00 UCT [eventlog] opened[0] = opened the 2012-10-05 at 15:00 UCT by Fabien Benureau +closed[1] = closed the 2012-10-11 at 17:57(UCT) by Fabien Benureau [discussion] desc = # enter your description here diff --git a/.pit/pit-ac8c05c020d251c6 b/.pit/pit-ac8c05c020d251c6 index 14a1e05..e753aba 100644 --- a/.pit/pit-ac8c05c020d251c6 +++ b/.pit/pit-ac8c05c020d251c6 @@ -1,7 +1,7 @@ [header] title = remove configparser for internal mapping id = ac8c05c020d251c6fa9ac5fc239038837b636b3b -status = open +status = closed type = bug author = Fabien Benureau mail = fabien.benureau+git@gmail.com @@ -9,6 +9,7 @@ date = 2012-10-11 at 07:25 UCT [eventlog] opened[0] = opened the 2012-10-11 at 07:25 UCT by Fabien Benureau +closed[1] = closed the 2012-10-11 at 17:57(UCT) by Fabien Benureau [discussion] desc = # enter your description here diff --git a/papers/commands/init_cmd.py b/papers/commands/init_cmd.py index f38bc5e..66fd3f9 100644 --- a/papers/commands/init_cmd.py +++ b/papers/commands/init_cmd.py @@ -26,12 +26,11 @@ def command(config): os.makedirs(papersdir+os.sep+'bibdata') os.makedirs(papersdir+os.sep+'meta') - papers = configparser.ConfigParser() - papers.add_section('header') - papers.set('header', 'count', 0) - papers.add_section('citekeys') - papers.add_section('numbers') - files.write_papers(papers) + papers = {} + papers['count'] = 0 + papers['citekeys'] = {} + papers['numbers'] = {} + files.save_papers(papers) else: print('{}error {} : papers already present in {}{}{}'.format( diff --git a/papers/commands/list_cmd.py b/papers/commands/list_cmd.py index fc19cc3..9e49bd5 100644 --- a/papers/commands/list_cmd.py +++ b/papers/commands/list_cmd.py @@ -13,10 +13,10 @@ def command(config): rp = repo.Repository() articles = [] - for n in rp.numbers: + for n in sorted(rp.numbers.keys()): paper = rp.paper_from_number(n, fatal = True) - bibdesc = pretty.bib_oneliner(paper.bibdata) - articles.append('{:3d} {}{}{}{} {}'.format(int(paper.number), color.purple, citekey, color.end, (8-len(paper.citekey))*' ', bibdesc)) + bibdesc = pretty.bib_oneliner(paper.bib_data) + articles.append('{:3d} {}{}{}{} {}'.format(int(paper.number), color.purple, paper.citekey, color.end, (8-len(paper.citekey))*' ', bibdesc)) with tempfile.NamedTemporaryFile(suffix=".tmp", delete=True) as tmpf: tmpf.write('\n'.join(articles)) diff --git a/papers/commands/open_cmd.py b/papers/commands/open_cmd.py index 9780751..8788a25 100644 --- a/papers/commands/open_cmd.py +++ b/papers/commands/open_cmd.py @@ -11,7 +11,7 @@ def parser(subparsers, config): def command(config, citekey): rp = repo.Repository() paper = rp.paper_from_any(citekey, fatal = True) - filepath = paper.metadata.get('metadata', 'path') + filepath = paper.metadata['path'] p = subprocess.Popen(['open', filepath]) print('{}{}{} opened.{}'.format(color.filepath, filepath, color.normal, color.end)) \ No newline at end of file diff --git a/papers/files.py b/papers/files.py index 7673e39..ee98ca7 100644 --- a/papers/files.py +++ b/papers/files.py @@ -8,6 +8,8 @@ try: except ImportError: import configparser +import yaml + import color try: @@ -66,29 +68,46 @@ def check_file(filepath): print '{}error{}: {}{}{} is not a file{}'.format( color.red, color.grey, color.cyan, filepath, color.grey, color.end) exit(-1) + +# yaml I/O -def write_configfile(config, filepath): +def write_yamlfile(filepath, datamap): try: with open(filepath, 'w') as f: - config.write(f) + yaml.dump(datamap, f) except IOError as e: - print '{}error{} : impossible to write on file {}{:s}{}'.format( + print '{}error{} : impossible to read file {}{:s}{}'.format( color.red, color.grey, color.cyan, filepath, color.end) - print 'Verify permissions' exit(-1) -def read_configfile(filepath): +def read_yamlfile(filepath): + check_file(filepath) try: with open(filepath, 'r') as f: - config = configparser.ConfigParser() - config.readfp(f) - return config + return yaml.load(f) except IOError as e: print '{}error{} : impossible to read file {}{:s}{}'.format( - color.red, color.grey, color.cyan, filepath, color.end) - print 'Verify permissions' + color.red, color.grey, color.cyan, paperdir, color.end) exit(-1) +def save_papers(datamap): + paperyaml = find_papersdir() + os.sep + 'papers.yaml' + write_yamlfile(paperyaml, datamap) + +def load_papers(): + paperyaml = find_papersdir() + os.sep + 'papers.yaml' + return read_yamlfile(paperyaml) + +def save_meta(meta_data, filename): + filepath = find_papersdir() + os.sep + 'meta' + os.sep + filename + '.meta' + write_yamlfile(filepath, meta_data) + +def load_meta(filename): + filepath = find_papersdir() + os.sep + 'meta' + os.sep + filename + '.meta' + return read_yamlfile(filepath) + +# specific to bibliography data + def load_externalbibfile(fullbibpath): check_file(fullbibpath) @@ -109,31 +128,17 @@ def load_externalbibfile(fullbibpath): return bib_data - -def write_papers(config): - write_configfile(config, find_papersdir() + os.sep + 'papers') - -def load_papers(): - return read_configfile(find_papersdir() + os.sep + 'papers') - def load_bibdata(filename): fullbibpath = find_papersdir() + os.sep + 'bibdata' + os.sep + filename + '.bibyaml' return load_externalbibfile(fullbibpath) -def write_bibdata(bib_data, filename): +def save_bibdata(bib_data, filename): filepath = find_papersdir() + os.sep + 'bibdata' + os.sep + filename + '.bibyaml' with open(filepath, 'w') as f: parser = pybtex.database.output.bibyaml.Writer() parser.write_stream(bib_data, f) -def write_meta(meta_data, filename): - filepath = find_papersdir() + os.sep + 'meta' + os.sep + filename + '.meta' - write_configfile(meta_data, filepath) - -def load_meta(filename): - filepath = find_papersdir() + os.sep + 'meta' + os.sep + filename + '.meta' - return read_configfile(filepath) - +# vim input try: EDITOR = os.environ['EDITOR'] diff --git a/papers/paper.py b/papers/paper.py index 19ad81f..2ad9073 100644 --- a/papers/paper.py +++ b/papers/paper.py @@ -1,8 +1,4 @@ import os -try: - import ConfigParser as configparser -except ImportError: - import configparser import files import color @@ -15,8 +11,8 @@ class Paper(object): @classmethod def from_disc(cls, name, citekey = None, number = None): - bib_data = files.load_bibdata(self.name) - metadata = files.load_meta(self.name) + bib_data = files.load_bibdata(name) + metadata = files.load_meta(name) p = Paper(name, bib_data = bib_data, metadata = metadata, citekey = citekey, number = number) return p @@ -24,7 +20,7 @@ class Paper(object): @classmethod def from_bibpdffiles(cls, pdfpath, bibpath): bib_data = cls.import_bibdata(bibpath) - name, meta = cls.import_meta(pdfpath, bib_data) + name, meta = cls.create_meta(pdfpath, bib_data) p = Paper(name, bib_data = bib_data, metadata = meta) return p @@ -38,14 +34,13 @@ class Paper(object): self.number = number def save_to_disc(self): - files.write_bibdata(self.bib_data, self.name) - files.write_meta(self.metadata, self.name) + files.save_bibdata(self.bib_data, self.name) + files.save_meta(self.metadata, self.name) @classmethod def import_bibdata(cls, bibfile): """Import bibligraphic data from a .bibyaml, .bib or .bibtex file""" fullbibpath = os.path.abspath(bibfile) - files.check_file(fullbibpath) bib_data = files.load_externalbibfile(fullbibpath) print('{}bibliographic data present in {}{}{}'.format( @@ -55,20 +50,19 @@ class Paper(object): return bib_data @classmethod - def import_meta(cls, pdfpath, bib_data): + def create_meta(cls, pdfpath, bib_data): fullpdfpath = os.path.abspath(pdfpath) files.check_file(fullpdfpath) name, ext = files.name_from_path(pdfpath) - meta = configparser.ConfigParser() - meta.add_section('metadata') + meta = {} - meta.set('metadata', 'name', name) - meta.set('metadata', 'extension', ext) - meta.set('metadata', 'path', os.path.normpath(fullpdfpath)) + meta['name'] = name + meta['extension'] = ext + meta['path'] = fullpdfpath - meta.add_section('notes') + meta['notes'] = [] return name, meta diff --git a/papers/repo.py b/papers/repo.py index 405691b..9fdb980 100644 --- a/papers/repo.py +++ b/papers/repo.py @@ -1,8 +1,3 @@ -try: - import ConfigParser as configparser -except ImportError: - import configparser - import files import color from paper import Paper @@ -15,16 +10,18 @@ class Repository(object): def __init__(self): self.paperdir = files.find_papersdir() self.papers_config = files.load_papers() - self.citekeys = dict((ck, name) for ck, name in self.papers_config.items('citekeys')) - self.numbers = sorted(n[2:] for n in self.papers_config.options('numbers')) + self.citekeys = self.papers_config['citekeys'] + self.numbers = self.papers_config['numbers'] # loading existing papers def paper_from_number(self, number, fatal = True): try: - citekey = self.papers_config.get('numbers', 'ck'+number) - return self.paper_from_citekey(citekey) - except configparser.NoOptionError: + citekey = self.numbers[int(number)] + paper = self.paper_from_citekey(citekey) + paper.number = int(number) + return paper + except KeyError: if fatal: print('{}error{}: no paper with number {}{}{}'.format( color.error, color.normal, color.citekey, citekey, color.end)) @@ -34,11 +31,9 @@ class Repository(object): def paper_from_citekey(self, citekey, fatal = True): """Load a paper by its citekey from disk, if necessary.""" try: - paper = self.citekeys[citekey] - if paper is None: - name = self.papers_config.get('citekeys', citekey) - paper = Paper.from_disc(name, citekey = citekey) - self.citekeys[citekey] = paper + name = self.citekeys[citekey] + paper = Paper.from_disc(name, citekey = citekey) + paper.citekey = citekey return paper except KeyError: if fatal: @@ -70,15 +65,14 @@ class Repository(object): p.citekey = self.create_citekey(p.bib_data) p.number = self.create_number() - self.papers_config.set('citekeys', p.citekey, p.name) - self.papers_config.set('numbers', 'ck' + str(p.number), p.citekey) + self.papers_config['citekeys'][p.citekey] = p.name + self.papers_config['numbers'][p.number] = p.citekey self.citekeys[p.citekey] = p.name - self.numbers.append(str(p.number)) - self.numbers.sort() + self.numbers[p.number] = p.citekey # writing all to disk - files.write_papers(self.papers_config) + files.save_papers(self.papers_config) p.save_to_disc() return p @@ -101,6 +95,6 @@ class Repository(object): return citekey def create_number(self): - count = self.papers_config.getint('header', 'count') - self.papers_config.set('header', 'count', count + 1) + count = int(self.papers_config['count']) + self.papers_config['count'] = count + 1 return count \ No newline at end of file From 443329d7cf8006c3d52b0de75825ce33e39c5ed5 Mon Sep 17 00:00:00 2001 From: Olivier Mangin Date: Mon, 22 Oct 2012 04:09:12 +0200 Subject: [PATCH 4/5] Fix bug in citekey generation. --- papers/repo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/papers/repo.py b/papers/repo.py index 9fdb980..99f85d3 100644 --- a/papers/repo.py +++ b/papers/repo.py @@ -84,12 +84,12 @@ class Repository(object): year = article.fields['year'] prefix = '{}{}'.format(first_author.last()[0][:6], year[2:]) - letter = 0, False + letter = 0 citekey = None citekey = prefix while citekey in self.citekeys and citekey not in allowed: - citekey = prefix + alphabet[letter[0]] + citekey = prefix + alphabet[letter] letter += 1 return citekey @@ -97,4 +97,4 @@ class Repository(object): def create_number(self): count = int(self.papers_config['count']) self.papers_config['count'] = count + 1 - return count \ No newline at end of file + return count From 2d57a2080c1a912b8575f67dc9f0e852dfdca43f Mon Sep 17 00:00:00 2001 From: Olivier Mangin Date: Mon, 22 Oct 2012 05:00:04 +0200 Subject: [PATCH 5/5] Adds handling of the case where no document file is defined. --- papers/commands/open_cmd.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/papers/commands/open_cmd.py b/papers/commands/open_cmd.py index 8788a25..b1dd0bf 100644 --- a/papers/commands/open_cmd.py +++ b/papers/commands/open_cmd.py @@ -2,6 +2,7 @@ import subprocess from .. import color from .. import repo +from ..paper import NoDocumentFile def parser(subparsers, config): parser = subparsers.add_parser('open', help='{}open the paper in a pdf viewer{}'.format(color.normal, color.end)) @@ -11,7 +12,15 @@ def parser(subparsers, config): def command(config, citekey): rp = repo.Repository() paper = rp.paper_from_any(citekey, fatal = True) - filepath = paper.metadata['path'] + try: + if paper.check_file(): + filepath = paper.get_file_path() + + p = subprocess.Popen(['open', filepath]) + print('{}{}{} opened.{}'.format( + color.filepath, filepath, color.normal, color.end)) + except NoDocumentFile: + print('{}error{}: No document associated to this entry {}{}{}'.format( + color.error, color.normal, color.citekey, citekey, color.end)) + exit(-1) - p = subprocess.Popen(['open', filepath]) - print('{}{}{} opened.{}'.format(color.filepath, filepath, color.normal, color.end)) \ No newline at end of file