Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
* `pyscript` - replaced by `run_pyscript`
* We apologize for any inconvenience, but the new names are more self-descriptive
* Lots of end users were confused particularly about what exactly `load` should be loading
* Breaking Changes
* Restored `cmd2.Cmd.statement_parser` to be a public attribute (no underscore)
* Since it can be useful for creating [post-parsing hooks](https://cmd2.readthedocs.io/en/latest/features/hooks.html#postparsing-hooks)


## 0.9.14 (June 29, 2019)
* Enhancements
Expand Down
56 changes: 28 additions & 28 deletions cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ def with_argument_list(*args: List[Callable], preserve_quotes: bool = False) ->
def arg_decorator(func: Callable):
@functools.wraps(func)
def cmd_wrapper(cmd2_instance, statement: Union[Statement, str]):
_, parsed_arglist = cmd2_instance._statement_parser.get_command_arg_list(command_name,
statement,
preserve_quotes)
_, parsed_arglist = cmd2_instance.statement_parser.get_command_arg_list(command_name,
statement,
preserve_quotes)

return func(cmd2_instance, parsed_arglist)

Expand Down Expand Up @@ -185,9 +185,9 @@ def with_argparser_and_unknown_args(argparser: argparse.ArgumentParser, *,
def arg_decorator(func: Callable):
@functools.wraps(func)
def cmd_wrapper(cmd2_instance, statement: Union[Statement, str]):
statement, parsed_arglist = cmd2_instance._statement_parser.get_command_arg_list(command_name,
statement,
preserve_quotes)
statement, parsed_arglist = cmd2_instance.statement_parser.get_command_arg_list(command_name,
statement,
preserve_quotes)

if ns_provider is None:
namespace = None
Expand Down Expand Up @@ -243,9 +243,9 @@ def with_argparser(argparser: argparse.ArgumentParser, *,
def arg_decorator(func: Callable):
@functools.wraps(func)
def cmd_wrapper(cmd2_instance, statement: Union[Statement, str]):
statement, parsed_arglist = cmd2_instance._statement_parser.get_command_arg_list(command_name,
statement,
preserve_quotes)
statement, parsed_arglist = cmd2_instance.statement_parser.get_command_arg_list(command_name,
statement,
preserve_quotes)

if ns_provider is None:
namespace = None
Expand Down Expand Up @@ -393,10 +393,10 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
if shortcuts is None:
shortcuts = constants.DEFAULT_SHORTCUTS
shortcuts = sorted(shortcuts.items(), reverse=True)
self._statement_parser = StatementParser(allow_redirection=allow_redirection,
terminators=terminators,
multiline_commands=multiline_commands,
shortcuts=shortcuts)
self.statement_parser = StatementParser(allow_redirection=allow_redirection,
terminators=terminators,
multiline_commands=multiline_commands,
shortcuts=shortcuts)

# True if running inside a Python script or interactive console, False otherwise
self._in_py = False
Expand Down Expand Up @@ -561,17 +561,17 @@ def visible_prompt(self) -> str:
@property
def aliases(self) -> Dict[str, str]:
"""Read-only property to access the aliases stored in the StatementParser."""
return self._statement_parser.aliases
return self.statement_parser.aliases

@property
def allow_redirection(self) -> bool:
"""Getter for the allow_redirection property that determines whether or not redirection of stdout is allowed."""
return self._statement_parser.allow_redirection
return self.statement_parser.allow_redirection

@allow_redirection.setter
def allow_redirection(self, value: bool) -> None:
"""Setter for the allow_redirection property that determines whether or not redirection of stdout is allowed."""
self._statement_parser.allow_redirection = value
self.statement_parser.allow_redirection = value

def poutput(self, msg: Any, *, end: str = '\n') -> None:
"""Print message to self.stdout and appends a newline by default
Expand Down Expand Up @@ -1385,7 +1385,7 @@ def _complete_worker(self, text: str, state: int) -> Optional[str]:
# from text and update the indexes. This only applies if we are at the the beginning of the line.
shortcut_to_restore = ''
if begidx == 0:
for (shortcut, _) in self._statement_parser.shortcuts:
for (shortcut, _) in self.statement_parser.shortcuts:
if text.startswith(shortcut):
# Save the shortcut to restore later
shortcut_to_restore = shortcut
Expand All @@ -1399,7 +1399,7 @@ def _complete_worker(self, text: str, state: int) -> Optional[str]:
if begidx > 0:

# Parse the command line
statement = self._statement_parser.parse_command_only(line)
statement = self.statement_parser.parse_command_only(line)
command = statement.command
expanded_line = statement.command_and_args

Expand Down Expand Up @@ -1678,7 +1678,7 @@ def parseline(self, line: str) -> Tuple[str, str, str]:
:param line: line read by readline
:return: tuple containing (command, args, line)
"""
statement = self._statement_parser.parse_command_only(line)
statement = self.statement_parser.parse_command_only(line)
return statement.command, statement.args, statement.command_and_args

def onecmd_plus_hooks(self, line: str, pyscript_bridge_call: bool = False) -> bool:
Expand Down Expand Up @@ -1842,7 +1842,7 @@ def _complete_statement(self, line: str) -> Statement:
"""
while True:
try:
statement = self._statement_parser.parse(line)
statement = self.statement_parser.parse(line)
if statement.multiline_command and statement.terminator:
# we have a completed multiline command, we are done
break
Expand All @@ -1853,7 +1853,7 @@ def _complete_statement(self, line: str) -> Statement:
except ValueError:
# we have unclosed quotation marks, lets parse only the command
# and see if it's a multiline
statement = self._statement_parser.parse_command_only(line)
statement = self.statement_parser.parse_command_only(line)
if not statement.multiline_command:
# not a multiline command, so raise the exception
raise
Expand All @@ -1877,7 +1877,7 @@ def _complete_statement(self, line: str) -> Statement:
raise ex
else:
self.poutput('^C')
statement = self._statement_parser.parse('')
statement = self.statement_parser.parse('')
break
finally:
self._at_continuation_prompt = False
Expand Down Expand Up @@ -2290,7 +2290,7 @@ def _alias_create(self, args: argparse.Namespace) -> None:
"""Create or overwrite an alias"""

# Validate the alias name
valid, errmsg = self._statement_parser.is_valid_command(args.name)
valid, errmsg = self.statement_parser.is_valid_command(args.name)
if not valid:
self.perror("Invalid alias name: {}".format(errmsg))
return
Expand All @@ -2301,7 +2301,7 @@ def _alias_create(self, args: argparse.Namespace) -> None:

# Unquote redirection and terminator tokens
tokens_to_unquote = constants.REDIRECTION_TOKENS
tokens_to_unquote.extend(self._statement_parser.terminators)
tokens_to_unquote.extend(self.statement_parser.terminators)
utils.unquote_specific_tokens(args.command_args, tokens_to_unquote)

# Build the alias value string
Expand Down Expand Up @@ -2421,7 +2421,7 @@ def _macro_create(self, args: argparse.Namespace) -> None:
"""Create or overwrite a macro"""

# Validate the macro name
valid, errmsg = self._statement_parser.is_valid_command(args.name)
valid, errmsg = self.statement_parser.is_valid_command(args.name)
if not valid:
self.perror("Invalid macro name: {}".format(errmsg))
return
Expand All @@ -2436,7 +2436,7 @@ def _macro_create(self, args: argparse.Namespace) -> None:

# Unquote redirection and terminator tokens
tokens_to_unquote = constants.REDIRECTION_TOKENS
tokens_to_unquote.extend(self._statement_parser.terminators)
tokens_to_unquote.extend(self.statement_parser.terminators)
utils.unquote_specific_tokens(args.command_args, tokens_to_unquote)

# Build the macro value string
Expand Down Expand Up @@ -2830,7 +2830,7 @@ def _print_topics(self, header: str, cmds: List[str], verbose: bool) -> None:
@with_argparser(ACArgumentParser())
def do_shortcuts(self, _: argparse.Namespace) -> None:
"""List available shortcuts"""
result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in sorted(self._statement_parser.shortcuts))
result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in sorted(self.statement_parser.shortcuts))
self.poutput("Shortcuts for other commands:\n{}".format(result))

@with_argparser(ACArgumentParser(epilog=INTERNAL_COMMAND_EPILOG))
Expand Down Expand Up @@ -2899,7 +2899,7 @@ def _cmdenvironment(self) -> str:
read_only_settings = """
Commands may be terminated with: {}
Output redirection and pipes allowed: {}"""
return read_only_settings.format(str(self._statement_parser.terminators), self.allow_redirection)
return read_only_settings.format(str(self.statement_parser.terminators), self.allow_redirection)

def _show(self, args: argparse.Namespace, parameter: str = '') -> None:
"""Shows current settings of parameters.
Expand Down
2 changes: 1 addition & 1 deletion cmd2/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def is_valid_command(self, word: str) -> Tuple[bool, str]:
This string is suitable for inclusion in an error message of your
choice:

valid, errmsg = _statement_parser.is_valid_command('>')
valid, errmsg = statement_parser.is_valid_command('>')
if not valid:
errmsg = "Alias {}".format(errmsg)
"""
Expand Down
6 changes: 3 additions & 3 deletions examples/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def add_whitespace_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.
command_pattern = re.compile(r'^([^\s\d]+)(\d+)')
match = command_pattern.search(command)
if match:
data.statement = self._statement_parser.parse("{} {} {}".format(
data.statement = self.statement_parser.parse("{} {} {}".format(
match.group(1),
match.group(2),
'' if data.statement.args is None else data.statement.args
Expand All @@ -71,7 +71,7 @@ def add_whitespace_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.
def downcase_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.PostparsingData:
"""A hook to make uppercase commands lowercase."""
command = data.statement.command.lower()
data.statement = self._statement_parser.parse("{} {}".format(
data.statement = self.statement_parser.parse("{} {}".format(
command,
'' if data.statement.args is None else data.statement.args
))
Expand All @@ -85,7 +85,7 @@ def abbrev_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.Postpars
possible_cmds = [cmd for cmd in self.get_all_commands() if cmd.startswith(data.statement.command)]
if len(possible_cmds) == 1:
raw = data.statement.raw.replace(data.statement.command, possible_cmds[0], 1)
data.statement = self._statement_parser.parse(raw)
data.statement = self.statement_parser.parse(raw)
return data

@cmd2.with_argument_list
Expand Down
4 changes: 2 additions & 2 deletions tests/test_cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def test_base_show_readonly(base_app):
expected = normalize(SHOW_TXT + '\nRead only settings:' + """
Commands may be terminated with: {}
Output redirection and pipes allowed: {}
""".format(base_app._statement_parser.terminators, base_app.allow_redirection))
""".format(base_app.statement_parser.terminators, base_app.allow_redirection))
assert out == expected


Expand Down Expand Up @@ -532,7 +532,7 @@ def test_feedback_to_output_false(base_app):

def test_disallow_redirection(base_app):
# Set allow_redirection to False
base_app._statement_parser.allow_redirection = False
base_app.statement_parser.allow_redirection = False

filename = 'test_allow_redirect.txt'

Expand Down
4 changes: 2 additions & 2 deletions tests/test_completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ def test_tokens_for_completion_quoted_redirect(cmd2_app):
endidx = len(line)
begidx = endidx - len(text)

cmd2_app._statement_parser.redirection = True
cmd2_app.statement_parser.redirection = True
expected_tokens = ['command', '>file']
expected_raw_tokens = ['command', '">file']

Expand All @@ -717,7 +717,7 @@ def test_tokens_for_completion_redirect_off(cmd2_app):
endidx = len(line)
begidx = endidx - len(text)

cmd2_app._statement_parser.allow_redirection = False
cmd2_app.statement_parser.allow_redirection = False
expected_tokens = ['command', '>file']
expected_raw_tokens = ['command', '>file']

Expand Down