made doc parsing error more helpful

This commit is contained in:
Lex Berezhny 2020-09-04 10:17:45 -04:00
parent 0f63103db5
commit b4ee07162d
2 changed files with 41 additions and 41 deletions

View file

@ -160,7 +160,9 @@ def parse_method(method, expanders: dict) -> dict:
for expanded in expanders[expander_name]: for expanded in expanders[expander_name]:
if expanded['name'] in known_names: if expanded['name'] in known_names:
raise Exception( raise Exception(
f"Expander '{expander_name}' argument repeated '{expanded['name']}' used by {d['name']}." f"Duplicate argument '{expanded['name']}' in '{d['name']}'. "
f"Expander '{expander_name}' is attempting to add an argument which is "
f"already defined in the '{d['name']}' command (possibly by another expander)."
) )
d['arguments'].append(expanded) d['arguments'].append(expanded)
d['kwargs'].append(expanded) d['kwargs'].append(expanded)
@ -217,11 +219,14 @@ def generate_options(method, indent) -> List[str]:
text += f" [default: {arg['default']}]" text += f" [default: {arg['default']}]"
wrapped = textwrap.wrap(text, LINE_WIDTH-len(left), break_long_words=False) wrapped = textwrap.wrap(text, LINE_WIDTH-len(left), break_long_words=False)
lines = [f"{left}{wrapped.pop(0)}"] lines = [f"{left}{wrapped.pop(0)}"]
# dont break on -- or docopt will parse as a new option
for line in wrapped: for line in wrapped:
if line.strip().startswith('--'): if line.strip().startswith('--'):
print(f"Full text before continuation error: \"{text}\"") raise Exception(
raise Exception(f"Continuation line starts with -- on {method['cli']}: \"{line.strip()}\"") f"Word wrapping the description for argument '{arg['name']}' in method "
f"'{method['method'].__name__}' resulted in a line which starts with '--' and this will "
f"break docopt. Try wrapping the '--' in quotes. Instead of --foo do \"--foo\". "
f"Line which caused this issue is:\n{line.strip()}"
)
lines.append(f"{' '*len(left)} {line}") lines.append(f"{' '*len(left)} {line}")
options.extend(lines) options.extend(lines)
return options return options

View file

@ -7,21 +7,6 @@ from lbry.service.parser import (
) )
@expander
def test_kwargs(somevalue=1):
pass
@expander
def another_test_kwargs(
somevalue=1,
repeated=2,
bad_description=3, # using linebreaks makes docopt very very --angry
angry=4
):
pass
class FakeAPI: class FakeAPI:
THING_DOC = "thing doc" THING_DOC = "thing doc"
@ -72,23 +57,29 @@ class FakeAPI:
""" """
class BadAPI(FakeAPI): @expander
def thing_search( def test_kwargs(
self, somevalue=1
query='a', ):
**test_and_another_test_kwargs) -> Wallet: pass
"""
search command doc
Usage:
thing search [--query=<query>]
{kwargs}
"""
class BadContinuationAPI(FakeAPI): @expander
def thing_save(self, **another_test_kwargs): def another_test_kwargs(
"""save command doc""" somevalue=1,
bad_description=3, # using linebreaks makes docopt very very --angry
):
pass
class CommandWithRepeatedArgs(FakeAPI):
def thing_bad(self, **test_and_another_test_kwargs) -> Wallet:
"""bad thing"""
class CommandWithDoubleDashAtLineStart(FakeAPI):
def thing_bad(self, **another_test_kwargs):
"""bad thing"""
class TestParser(TestCase): class TestParser(TestCase):
@ -96,19 +87,23 @@ class TestParser(TestCase):
def test_parse_does_not_allow_duplicate_arguments(self): def test_parse_does_not_allow_duplicate_arguments(self):
with self.assertRaises(Exception) as exc: with self.assertRaises(Exception) as exc:
parse_method(BadAPI.thing_search, get_expanders()) parse_method(CommandWithRepeatedArgs.thing_bad, get_expanders())
self.assertEqual( self.assertEqual(
exc.exception.args[0], exc.exception.args[0],
"Expander 'another_test' argument repeated 'somevalue' used by thing_search." "Duplicate argument 'somevalue' in 'thing_bad'. "
"Expander 'another_test' is attempting to add an argument which is already defined "
"in the 'thing_bad' command (possibly by another expander)."
) )
def test_parse_does_not_allow_line_break_with_two_dashes(self): def test_parse_does_not_allow_two_dashes_at_start_of_line(self):
# breaking with two dashes breaks docopt parsing
with self.assertRaises(Exception) as exc: with self.assertRaises(Exception) as exc:
get_api_definitions(BadContinuationAPI) get_api_definitions(CommandWithDoubleDashAtLineStart)
self.assertEqual( self.assertEqual(
exc.exception.args[0], exc.exception.args[0],
"Continuation line starts with -- on thing save: \"--angry [default: 3]\"" "Word wrapping the description for argument 'bad_description' in method 'thing_bad' "
"resulted in a line which starts with '--' and this will break docopt. Try wrapping "
"the '--' in quotes. Instead of --foo do \"--foo\". Line which caused this issue is:"
"\n--angry [default: 3]"
) )
def test_parse_method(self): def test_parse_method(self):