Merge branch 'beuerle-PR_resolve_citekey'
This commit is contained in:
commit
3209f35bd1
@ -71,7 +71,7 @@ def command(conf, args):
|
||||
# ui.exit()
|
||||
|
||||
if args.action == 'add':
|
||||
citekey = resolve_citekey(rp, args.citekey[0], ui=ui, exit_on_fail=True)
|
||||
citekey = resolve_citekey(rp, conf, args.citekey[0], ui=ui, exit_on_fail=True)
|
||||
paper = rp.pull_paper(citekey)
|
||||
|
||||
if paper.docpath is not None and not args.force:
|
||||
@ -98,7 +98,7 @@ def command(conf, args):
|
||||
|
||||
elif args.action == 'remove':
|
||||
|
||||
for key in resolve_citekey_list(rp, args.citekeys, ui=ui, exit_on_fail=True):
|
||||
for key in resolve_citekey_list(rp, conf, args.citekeys, ui=ui, exit_on_fail=True):
|
||||
paper = rp.pull_paper(key)
|
||||
|
||||
# if there is no document (and the user cares) -> inform + continue
|
||||
@ -126,7 +126,7 @@ def command(conf, args):
|
||||
color.dye_err(args.path[0], 'filepath')))
|
||||
ui.exit(1)
|
||||
|
||||
for key in resolve_citekey_list(rp, args.citekeys, ui=ui, exit_on_fail=True):
|
||||
for key in resolve_citekey_list(rp, conf, args.citekeys, ui=ui, exit_on_fail=True):
|
||||
try:
|
||||
paper = rp.pull_paper(key)
|
||||
doc = paper.docpath
|
||||
@ -143,7 +143,7 @@ def command(conf, args):
|
||||
|
||||
elif args.action == 'open':
|
||||
with_command = args.cmd
|
||||
citekey = resolve_citekey(rp, args.citekey[0], ui=ui, exit_on_fail=True)
|
||||
citekey = resolve_citekey(rp, conf, args.citekey[0], ui=ui, exit_on_fail=True)
|
||||
paper = rp.pull_paper(citekey)
|
||||
|
||||
if paper.docpath is None:
|
||||
|
@ -30,7 +30,7 @@ def command(conf, args):
|
||||
meta = args.meta
|
||||
|
||||
rp = repo.Repository(conf)
|
||||
citekey = resolve_citekey(rp, args.citekey, ui=ui, exit_on_fail=True)
|
||||
citekey = resolve_citekey(rp, conf, args.citekey, ui=ui, exit_on_fail=True)
|
||||
paper = rp.pull_paper(citekey)
|
||||
|
||||
coder = EnDecoder()
|
||||
|
@ -46,7 +46,7 @@ def command(conf, args):
|
||||
if len(args.citekeys) < 1:
|
||||
papers = rp.all_papers()
|
||||
else:
|
||||
for key in resolve_citekey_list(repo=rp, citekeys=args.citekeys, ui=ui, exit_on_fail=True):
|
||||
for key in resolve_citekey_list(rp, conf, args.citekeys, ui=ui, exit_on_fail=True):
|
||||
papers.append(rp.pull_paper(key))
|
||||
|
||||
bib = {}
|
||||
|
@ -23,7 +23,7 @@ def command(conf, args):
|
||||
|
||||
ui = get_ui()
|
||||
rp = repo.Repository(conf)
|
||||
citekey = resolve_citekey(rp, args.citekey, ui=ui, exit_on_fail=True)
|
||||
citekey = resolve_citekey(rp, conf, args.citekey, ui=ui, exit_on_fail=True)
|
||||
notepath = rp.databroker.real_notepath(citekey, rp.conf['main']['note_extension'])
|
||||
if args.append is None:
|
||||
ui.edit_file(notepath, temporary=False)
|
||||
|
@ -25,7 +25,7 @@ def command(conf, args):
|
||||
force = args.force
|
||||
rp = repo.Repository(conf)
|
||||
|
||||
keys = resolve_citekey_list(repo=rp, citekeys=args.citekeys, ui=ui, exit_on_fail=True)
|
||||
keys = resolve_citekey_list(rp, conf, args.citekeys, ui=ui, exit_on_fail=True)
|
||||
plural = 's' if len(keys) > 1 else ''
|
||||
|
||||
if force is None:
|
||||
|
@ -26,7 +26,7 @@ def command(conf, args):
|
||||
rp = repo.Repository(conf)
|
||||
|
||||
# TODO: here should be a test whether the new citekey is valid
|
||||
key = resolve_citekey(repo=rp, citekey=args.citekey, ui=ui, exit_on_fail=True)
|
||||
key = resolve_citekey(rp, conf, args.citekey, ui=ui, exit_on_fail=True)
|
||||
paper = rp.pull_paper(key)
|
||||
rp.rename_paper(paper, args.new_citekey)
|
||||
ui.message("The '{}' citekey has been renamed into '{}'".format(
|
||||
|
@ -55,6 +55,8 @@ def _parse_tag_seq(s):
|
||||
if last != 0:
|
||||
raise ValueError('could not match tag expression')
|
||||
else:
|
||||
tag = s[last:(m.start())]
|
||||
if len(tag) > 0:
|
||||
tags.append(s[last:(m.start())])
|
||||
last = m.start()
|
||||
if last == len(s):
|
||||
@ -89,7 +91,7 @@ def command(conf, args):
|
||||
else:
|
||||
not_citekey = False
|
||||
try:
|
||||
citekeyOrTag = resolve_citekey(repo=rp, citekey=citekeyOrTag, ui=ui, exit_on_fail=True)
|
||||
citekeyOrTag = resolve_citekey(rp, conf, citekeyOrTag, ui=ui, exit_on_fail=True)
|
||||
except SystemExit:
|
||||
not_citekey = True
|
||||
if not not_citekey:
|
||||
|
@ -22,7 +22,7 @@ def command(conf, args):
|
||||
ui = get_ui()
|
||||
rp = repo.Repository(conf)
|
||||
|
||||
for key in resolve_citekey_list(rp, args.citekey, ui=ui, exit_on_fail=False):
|
||||
for key in resolve_citekey_list(rp, conf, args.citekey, ui=ui, exit_on_fail=False):
|
||||
try:
|
||||
paper = rp.pull_paper(key)
|
||||
url = paper.bibdata['url']
|
||||
|
@ -7,7 +7,7 @@ from . import color
|
||||
from . import pretty
|
||||
|
||||
|
||||
def resolve_citekey(repo, citekey, ui=None, exit_on_fail=True):
|
||||
def resolve_citekey(repo, conf, citekey, ui=None, exit_on_fail=True):
|
||||
"""Check that a citekey exists, or autocompletes it if not ambiguous.
|
||||
:returns found citekey
|
||||
"""
|
||||
@ -29,22 +29,23 @@ def resolve_citekey(repo, citekey, ui=None, exit_on_fail=True):
|
||||
elif citekey not in citekeys:
|
||||
if ui is not None:
|
||||
citekeys = sorted(citekeys)
|
||||
ui.error("Be more specific; '{}' matches multiples "
|
||||
"citekeys:".format(citekey))
|
||||
msg = ["Be more specific; '{}' matches multiples citekeys:".format(citekey)]
|
||||
for c in citekeys:
|
||||
p = repo.pull_paper(c)
|
||||
ui.message(' {}'.format(pretty.paper_oneliner(p, max_authors=conf['main']['max_authors'])))
|
||||
paper_str = pretty.paper_oneliner(p, max_authors=conf['main']['max_authors'])
|
||||
msg.append(' {}'.format(paper_str))
|
||||
ui.error('\n'.join(msg))
|
||||
if exit_on_fail:
|
||||
ui.exit()
|
||||
return citekey
|
||||
|
||||
|
||||
def resolve_citekey_list(repo, citekeys, ui=None, exit_on_fail=True):
|
||||
def resolve_citekey_list(repo, conf, citekeys, ui=None, exit_on_fail=True):
|
||||
shutdown = False
|
||||
keys = []
|
||||
for key in citekeys:
|
||||
try:
|
||||
keys.append(resolve_citekey(repo, key, ui, exit_on_fail))
|
||||
keys.append(resolve_citekey(repo, conf, key, ui=ui, exit_on_fail=exit_on_fail))
|
||||
except SystemExit:
|
||||
shutdown = exit_on_fail
|
||||
|
||||
|
@ -9,7 +9,7 @@ import dotdot
|
||||
|
||||
from pyfakefs import fake_filesystem, fake_filesystem_unittest
|
||||
|
||||
from pubs.p3 import input, _fake_stdio, _get_fake_stdio_ucontent
|
||||
from pubs.p3 import input
|
||||
from pubs import content, filebroker, uis
|
||||
|
||||
# code for fake fs
|
||||
@ -29,29 +29,6 @@ original_exception_handler = uis.InputUI.handle_exception
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
|
||||
# capture output
|
||||
|
||||
def capture(f, verbose=False):
|
||||
"""Capture the stdout and stderr output.
|
||||
|
||||
Useful for comparing the output with the expected one during tests.
|
||||
|
||||
:param f: The function to capture output from.
|
||||
:param verbose: If True, print call will still display their outputs.
|
||||
If False, they will be silenced.
|
||||
|
||||
"""
|
||||
def newf(*args, **kwargs):
|
||||
old_stderr, old_stdout = sys.stderr, sys.stdout
|
||||
sys.stdout = _fake_stdio(additional_out=old_stdout if verbose else None)
|
||||
sys.stderr = _fake_stdio(additional_out=old_stderr if verbose else None)
|
||||
try:
|
||||
return f(*args, **kwargs), _get_fake_stdio_ucontent(sys.stdout), _get_fake_stdio_ucontent(sys.stderr)
|
||||
finally:
|
||||
sys.stderr, sys.stdout = old_stderr, old_stdout
|
||||
return newf
|
||||
|
||||
|
||||
# Test helpers
|
||||
|
||||
# automating input
|
||||
|
@ -46,7 +46,7 @@ class TestNoteAppend(DataCommandTestCase):
|
||||
# * Pass the command split into a command and its args to
|
||||
# execute_cmdsplit, which is called by execute_cmds:
|
||||
cmd_split = ['pubs', 'note', 'Page99', '-a', 'xxx yyy']
|
||||
self.execute_cmdsplit(cmd_split, expected_out=None, expected_err=None)
|
||||
self.execute_cmd_capture(cmd_split, expected_out=None, expected_err=None)
|
||||
note_lines.append('xxx yyy')
|
||||
self.assertFileContentEqual(fin_notes, self._get_note_content(note_lines))
|
||||
|
||||
|
@ -17,6 +17,7 @@ import dotdot
|
||||
import fake_env
|
||||
import mock_requests
|
||||
|
||||
|
||||
from pubs import pubs_cmd, color, content, uis, p3, endecoder
|
||||
from pubs.config import conf
|
||||
|
||||
@ -118,14 +119,12 @@ class CommandTestCase(fake_env.TestFakeFs):
|
||||
input.as_global()
|
||||
try:
|
||||
if capture_output:
|
||||
actual_out = self.execute_cmdsplit(
|
||||
actual_cmd.split(), expected_out, expected_err)
|
||||
actual_out = self.execute_cmd_capture(actual_cmd.split(), expected_out, expected_err)
|
||||
outs.append(color.undye(actual_out))
|
||||
else:
|
||||
pubs_cmd.execute(actual_cmd.split())
|
||||
except fake_env.FakeInput.UnexpectedInput:
|
||||
self.fail('Unexpected input asked by command: {}.'.format(
|
||||
actual_cmd))
|
||||
self.fail('Unexpected input asked by command: {}.'.format(actual_cmd))
|
||||
return outs
|
||||
except SystemExit as exc:
|
||||
exc_class, exc, tb = sys.exc_info()
|
||||
@ -145,21 +144,25 @@ class CommandTestCase(fake_env.TestFakeFs):
|
||||
pass
|
||||
return s
|
||||
|
||||
def execute_cmdsplit(self, actual_cmdlist, expected_out, expected_err):
|
||||
"""Run a single command, which has been split into a list containing cmd and args"""
|
||||
capture_wrap = fake_env.capture(pubs_cmd.execute,
|
||||
verbose=PRINT_OUTPUT)
|
||||
_, stdout, stderr = capture_wrap(actual_cmdlist)
|
||||
actual_out = self.normalize(stdout)
|
||||
actual_err = self.normalize(stderr)
|
||||
if expected_out is not None:
|
||||
self.assertEqual(p3.u_maybe(actual_out), p3.u_maybe(expected_out))
|
||||
if expected_err is not None:
|
||||
self.assertEqual(p3.u_maybe(actual_err), p3.u_maybe(expected_err))
|
||||
return actual_out
|
||||
def execute_cmd_capture(self, cmd, expected_out, expected_err):
|
||||
"""Run a single command, captures the output and and stderr and compare it to the expected ones"""
|
||||
sys_stdout, sys_stderr = sys.stdout, sys.stderr
|
||||
sys.stdout = p3._fake_stdio(additional_out=sys_stdout if PRINT_OUTPUT else None)
|
||||
sys.stderr = p3._fake_stdio(additional_out=sys_stderr if PRINT_OUTPUT else None)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
try:
|
||||
pubs_cmd.execute(cmd)
|
||||
finally:
|
||||
# capturing output even if exception was raised.
|
||||
self.captured_stdout = self.normalize(p3._get_fake_stdio_ucontent(sys.stdout))
|
||||
self.captured_stderr = self.normalize(p3._get_fake_stdio_ucontent(sys.stderr))
|
||||
sys.stderr, sys.stdout = sys_stderr, sys_stdout
|
||||
|
||||
if expected_out is not None:
|
||||
self.assertEqual(p3.u_maybe(self.captured_stdout), p3.u_maybe(expected_out))
|
||||
if expected_err is not None:
|
||||
self.assertEqual(p3.u_maybe(self.captured_stderr), p3.u_maybe(expected_err))
|
||||
return self.captured_stdout
|
||||
|
||||
def update_config(self, config_update, path=None):
|
||||
"""Allow to set the config parameters. Must have done a `pubs init` beforehand."""
|
||||
@ -624,6 +627,7 @@ class TestTag(DataCommandTestCase):
|
||||
with self.assertRaises(FakeSystemExit):
|
||||
self.execute_cmds(cmds)
|
||||
|
||||
|
||||
class TestURL(DataCommandTestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -1126,6 +1130,21 @@ class TestUsecase(DataCommandTestCase):
|
||||
self.execute_cmds(cmds, capture_output=True)
|
||||
# self.assertEqual(correct, self.execute_cmds(cmds, capture_output=True))
|
||||
|
||||
def test_ambiguous_citekey(self):
|
||||
cmds = ['pubs init',
|
||||
'pubs add data/pagerank.bib',
|
||||
'pubs add data/pagerank.bib', # now we have Page99 and Page99a
|
||||
'pubs edit Page',
|
||||
]
|
||||
output = '\n'.join(["error: Be more specific; 'Page' matches multiples citekeys:",
|
||||
" [Page99] Page, Lawrence et al. \"The PageRank Citation Ranking: Bringing Order to the Web.\" (1999) ",
|
||||
" [Page99a] Page, Lawrence et al. \"The PageRank Citation Ranking: Bringing Order to the Web.\" (1999) \n"])
|
||||
|
||||
with self.assertRaises(FakeSystemExit):
|
||||
self.execute_cmds(cmds)
|
||||
|
||||
self.assertEqual(self.captured_stderr, output)
|
||||
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
|
Loading…
x
Reference in New Issue
Block a user