diff --git a/pubs/commands/__init__.py b/pubs/commands/__init__.py index bc524c7..a68ab16 100644 --- a/pubs/commands/__init__.py +++ b/pubs/commands/__init__.py @@ -15,5 +15,5 @@ import import_cmd # bonus import websearch_cmd -# import edit_cmd +import edit_cmd # import update_cmd diff --git a/pubs/commands/add_cmd.py b/pubs/commands/add_cmd.py index 6dfc5ce..6212daa 100644 --- a/pubs/commands/add_cmd.py +++ b/pubs/commands/add_cmd.py @@ -72,7 +72,7 @@ def command(args): if bibfile is None: bibdata = bibdata_from_editor(ui, rp) else: - bibdata_raw = content.get_content(bibfile) + bibdata_raw = content.get_content(bibfile, ui=ui) bibdata = rp.databroker.verify(bibdata_raw) if bibdata is None: ui.error('invalid bibfile {}.'.format(bibfile)) diff --git a/pubs/commands/edit_cmd.py b/pubs/commands/edit_cmd.py index ae703fd..cd78dd7 100644 --- a/pubs/commands/edit_cmd.py +++ b/pubs/commands/edit_cmd.py @@ -1,8 +1,8 @@ -from ..content import editor_input +from ..paper import Paper from .. import repo -from ..paper import get_bibentry_from_string, get_safe_metadata_from_content from ..configs import config from ..uis import get_ui +from ..endecoder import EnDecoder def parser(subparsers): @@ -15,24 +15,6 @@ def parser(subparsers): return parser -def edit_meta(citekey): - rp = repo.Repository(config()) - coder = endecoder.EnDecoder() - filepath = os.path.join(rp.databroker.databroker.filebroker.metadir(), citekey+'.yaml') - with open(filepath) as f: - content = f.read() - - - -def edit_bib(citekey): - rp = repo.Repository(config()) - coder = endecoder.EnDecoder() - filepath = os.path.join(rp.databroker.databroker.filebroker.bibdir(), citekey+'.bib') - with open(filepath) as f: - content = f.read() - - - def command(args): ui = get_ui() @@ -40,41 +22,46 @@ def command(args): citekey = args.citekey rp = repo.Repository(config()) - coder = endecoder.EnDecoder() + paper = rp.pull_paper(citekey) + + coder = EnDecoder() if meta: - filepath = os.path.join(rp.databroker.databroker.filebroker.metadir(), citekey+'.yaml') + encode = coder.encode_metadata + decode = coder.decode_metadata + suffix = '.yaml' + raw_content = encode(paper.metadata) else: - filepath = os.path.join(rp.databroker.databroker.filebroker.bibdir(), citekey+'.bib') - - with open(filepath) as f: - content = f.read() + encode = coder.encode_bibdata + decode = coder.decode_bibdata + suffix = '.bib' + raw_content = encode(paper.bibdata) while True: # Get new content from user - content = editor_input(config().edit_cmd, content) - new_key = key - bib = None - metadata = None + raw_content = ui.editor_input(initial=raw_content, suffix=suffix) # Parse new content - if meta: - metadata = get_safe_metadata_from_content(content) - else: - new_key, bib = get_bibentry_from_string(content) - paper.update(key=new_key, bib=bib, meta=metadata) - try: - paper = rp.save_paper(paper, old_citekey=key) + content = decode(raw_content) + + if meta: + new_paper = Paper(paper.bibdata, citekey=paper.citekey, + metadata=content) + else: + new_paper = Paper(content, metadata=paper.metadata) + rp.rename_paper(new_paper, old_citekey=paper.citekey) break + except repo.CiteKeyCollision: options = ['overwrite', 'edit again', 'abort'] choice = options[ui.input_choice( - options, ['o', 'e', 'a'], - question='A paper already exists with this citekey.' - )] + options, ['o', 'e', 'a'], + question='A paper already exists with this citekey.' + )] if choice == 'abort': break elif choice == 'overwrite': - paper = rp.save_paper(paper, old_citekey=key, overwrite=True) + paper = rp.push_paper(paper, overwrite=True) break # else edit again + # Also handle malformed bibtex and metadata diff --git a/pubs/content.py b/pubs/content.py index 7197889..f2fb038 100644 --- a/pubs/content.py +++ b/pubs/content.py @@ -7,10 +7,8 @@ import urlparse import httplib import urllib2 -import uis - - # files i/o +# files i/o def check_file(path, fail=True): if fail: @@ -44,7 +42,7 @@ def write_file(filepath, data): f.write(data) - # dealing with formatless content +# dealing with formatless content def content_type(path): parsed = urlparse.urlparse(path) @@ -68,10 +66,11 @@ def check_content(path): else: return check_file(path) -def get_content(path): +def get_content(path, ui=None): """Will be useful when we need to get content from url""" if content_type(path) == 'url': - uis.get_ui().print_('dowloading {}'.format(path)) + if ui is not None: + ui.print_('dowloading {}'.format(path)) response = urllib2.urlopen(path) return response.read() else: @@ -92,24 +91,20 @@ def copy_content(source, target, overwrite = False): shutil.copy(source, target) - # editor input - -def editor_input(editor, initial="", suffix=None): +def editor_input(editor, initial="", suffix='.tmp'): """Use an editor to get input""" - if suffix is None: - suffix = '.tmp' with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as temp_file: tfile_name = temp_file.name temp_file.write(initial) - temp_file.flush() - cmd = editor.split() # this enable editor command with option, e.g. gvim -f - cmd.append(tfile_name) - subprocess.call(cmd) + cmd = editor.split() # this enable editor command with option, e.g. gvim -f + cmd.append(tfile_name) + subprocess.call(cmd) with open(tfile_name) as temp_file: content = temp_file.read() - os.remove(tfile_name) + os.remove(tfile_name) return content + def edit_file(editor, path_to_file, temporary=True): if temporary: check_file(path_to_file, fail=True) diff --git a/pubs/pubs_cmd.py b/pubs/pubs_cmd.py index 7f513e7..7be1dbd 100644 --- a/pubs/pubs_cmd.py +++ b/pubs/pubs_cmd.py @@ -28,7 +28,7 @@ CORE_CMDS = collections.OrderedDict([ ('import', commands.import_cmd), ('websearch', commands.websearch_cmd), - # ('edit', commands.edit_cmd), + ('edit', commands.edit_cmd), # ('update', commands.update_cmd), ]) diff --git a/pubs/repo.py b/pubs/repo.py index 87a1859..da9dccc 100644 --- a/pubs/repo.py +++ b/pubs/repo.py @@ -2,7 +2,7 @@ import itertools from . import bibstruct from . import events -from . import datacache +from datacache import DataCache from .paper import Paper @@ -23,8 +23,7 @@ class Repository(object): def __init__(self, config, create=False): self.config = config self._citekeys = None - self.databroker = datacache.DataCache(self.config.pubsdir, - create=create) + self.databroker = DataCache(self.config.pubsdir, create=create) @property def citekeys(self): @@ -92,19 +91,19 @@ class Repository(object): self.citekeys.remove(citekey) self.databroker.remove(citekey) - def rename_paper(self, paper, new_citekey): - old_citekey = paper.citekey + def rename_paper(self, paper, new_citekey=None, old_citekey=None): + if old_citekey is None: + old_citekey = paper.citekey + if new_citekey is None: + new_citekey = paper.citekey + paper.citekey = new_citekey # check if new_citekey is not the same as paper.citekey if old_citekey == new_citekey: - push_paper(paper, overwrite=True, event=False) + self.push_paper(paper, overwrite=True, event=False) else: # check if new_citekey does not exists - if self.databroker.exists(new_citekey, both=False): - raise IOError("can't rename paper to {}, conflicting files exists".format(new_citekey)) - - new_bibdata = {} - new_bibdata[new_citekey] = paper.bibdata[old_citekey] - paper.bibdata = new_bibdata + if new_citekey in self: + raise CiteKeyCollision("can't rename paper to {}, conflicting files exists".format(new_citekey)) # move doc file if necessary if self.databroker.in_docsdir(paper.docpath): @@ -116,8 +115,6 @@ class Repository(object): except IOError: pass - # push_paper to new_citekey - paper.citekey = new_citekey self.push_paper(paper, event=False) # remove_paper of old_citekey self.remove_paper(old_citekey, event=False) diff --git a/pubs/uis.py b/pubs/uis.py index b9194b6..f24432a 100644 --- a/pubs/uis.py +++ b/pubs/uis.py @@ -3,6 +3,7 @@ from __future__ import print_function import sys from .beets_ui import _encoding, input_ +from .content import editor_input from . import color # package-shared ui that can be accessed using : @@ -30,6 +31,7 @@ class UI: def __init__(self, config): self.encoding = _encoding(config) color.setup(config.color) + self.editor = config.edit_cmd def print_(self, *strings): """Like print, but rather than raising an error when a character @@ -86,3 +88,6 @@ class UI: def warning(self, message): self.print_("%s: %s" % (color.dye('warning', color.yellow), message)) + + def editor_input(self, initial="", suffix='.tmp'): + return editor_input(self.editor, initial=initial, suffix=suffix) diff --git a/tests/test_usecase.py b/tests/test_usecase.py index fb75782..d1a14ea 100644 --- a/tests/test_usecase.py +++ b/tests/test_usecase.py @@ -92,6 +92,7 @@ class CommandTestCase(unittest.TestCase): def tearDown(self): fake_env.unset_fake_fs([content, filebroker]) + class DataCommandTestCase(CommandTestCase): """Abstract TestCase intializing the fake filesystem and copying fake data. @@ -118,6 +119,7 @@ class TestInit(CommandTestCase): self.assertEqual(set(self.fs['os'].listdir(pubsdir)), {'bib', 'doc', 'meta', 'notes'}) + class TestAdd(DataCommandTestCase): def test_add(self): @@ -246,7 +248,7 @@ class TestUsecase(DataCommandTestCase): line = '[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) \n' line1 = re.sub('1999', '2007', line) - line2 = re.sub('L. Page', 'L. Ridge', line1) + line2 = re.sub('Page,', 'Ridge,', line1) line3 = re.sub('Page99', 'Ridge07', line2) cmds = ['pubs init', @@ -259,7 +261,6 @@ class TestUsecase(DataCommandTestCase): ('pubs edit Page99', [bib3]), ('pubs list', [], line3), ] - self.execute_cmds(cmds) def test_export(self):