summaryrefslogtreecommitdiff
path: root/cmd2/cmd2.py
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2019-07-20 16:10:23 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2019-07-20 16:10:23 -0400
commit3254626f8d7c5a353b3f615fc80fa716006137fd (patch)
tree4b3e766851f4054d1b073244b5e4506e1738b2e3 /cmd2/cmd2.py
parent578593f8a9011ad71d78cd30f231c79af570987e (diff)
downloadcmd2-git-3254626f8d7c5a353b3f615fc80fa716006137fd.tar.gz
Fixed issue where ipy wasn't using the correct name for the PyscriptBridge
Renamed some class members for clarification purposes
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r--cmd2/cmd2.py93
1 files changed, 53 insertions, 40 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 788e0294..ae79339f 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -146,12 +146,12 @@ 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)
+ def cmd_wrapper(cmd2_app, statement: Union[Statement, str]):
+ _, parsed_arglist = cmd2_app.statement_parser.get_command_arg_list(command_name,
+ statement,
+ preserve_quotes)
- return func(cmd2_instance, parsed_arglist)
+ return func(cmd2_app, parsed_arglist)
command_name = func.__name__[len(COMMAND_FUNC_PREFIX):]
cmd_wrapper.__doc__ = func.__doc__
@@ -185,15 +185,15 @@ def with_argparser_and_unknown_args(argparser: argparse.ArgumentParser, *,
# noinspection PyProtectedMember
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)
+ def cmd_wrapper(cmd2_app, statement: Union[Statement, str]):
+ statement, parsed_arglist = cmd2_app.statement_parser.get_command_arg_list(command_name,
+ statement,
+ preserve_quotes)
if ns_provider is None:
namespace = None
else:
- namespace = ns_provider(cmd2_instance)
+ namespace = ns_provider(cmd2_app)
try:
args, unknown = argparser.parse_known_args(parsed_arglist, namespace)
@@ -201,7 +201,7 @@ def with_argparser_and_unknown_args(argparser: argparse.ArgumentParser, *,
return
else:
setattr(args, '__statement__', statement)
- return func(cmd2_instance, args, unknown)
+ return func(cmd2_app, args, unknown)
# argparser defaults the program name to sys.argv[0]
# we want it to be the name of our command
@@ -243,15 +243,15 @@ def with_argparser(argparser: argparse.ArgumentParser, *,
# noinspection PyProtectedMember
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)
+ def cmd_wrapper(cmd2_app, statement: Union[Statement, str]):
+ statement, parsed_arglist = cmd2_app.statement_parser.get_command_arg_list(command_name,
+ statement,
+ preserve_quotes)
if ns_provider is None:
namespace = None
else:
- namespace = ns_provider(cmd2_instance)
+ namespace = ns_provider(cmd2_app)
try:
args = argparser.parse_args(parsed_arglist, namespace)
@@ -259,7 +259,7 @@ def with_argparser(argparser: argparse.ArgumentParser, *,
return
else:
setattr(args, '__statement__', statement)
- return func(cmd2_instance, args)
+ return func(cmd2_app, args)
# argparser defaults the program name to sys.argv[0]
# we want it to be the name of our command
@@ -412,9 +412,14 @@ class Cmd(cmd.Cmd):
# Command aliases and macros
self.macros = dict()
- self._pystate = {}
+ # Keeps track of typed command history in the Python shell
self._py_history = []
- self.pyscript_name = 'app'
+
+ # The name by which Python and IPython environments refer to the PyscriptBridge to call app commands
+ self.py_bridge_name = 'app'
+
+ # Defines app-specific variables/functions available in Python shells and pyscripts
+ self.py_locals = {}
self.statement_parser = StatementParser(allow_redirection=allow_redirection,
terminators=terminators,
@@ -3231,17 +3236,17 @@ class Cmd(cmd.Cmd):
raise EmbeddedConsoleExit
# Set up Python environment
- self._pystate[self.pyscript_name] = bridge
- self._pystate['run'] = py_run
- self._pystate['quit'] = py_quit
- self._pystate['exit'] = py_quit
+ self.py_locals[self.py_bridge_name] = bridge
+ self.py_locals['run'] = py_run
+ self.py_locals['quit'] = py_quit
+ self.py_locals['exit'] = py_quit
if self.locals_in_py:
- self._pystate['self'] = self
- elif 'self' in self._pystate:
- del self._pystate['self']
+ self.py_locals['self'] = self
+ elif 'self' in self.py_locals:
+ del self.py_locals['self']
- localvars = self._pystate
+ localvars = self.py_locals
interp = InteractiveConsole(locals=localvars)
interp.runcode('import sys, os;sys.path.insert(0, os.getcwd())')
@@ -3268,7 +3273,7 @@ class Cmd(cmd.Cmd):
instructions = ('End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, `exit()`.\n'
'Non-Python commands can be issued with: {}("your command")\n'
'Run Python code from external script files with: run("script.py")'
- .format(self.pyscript_name))
+ .format(self.py_bridge_name))
saved_cmd2_env = None
@@ -3335,22 +3340,30 @@ class Cmd(cmd.Cmd):
def do_ipy(self, _: argparse.Namespace) -> None:
"""Enter an interactive IPython shell"""
from .pyscript_bridge import PyscriptBridge
- bridge = PyscriptBridge(self)
-
banner = ('Entering an embedded IPython shell. Type quit or <Ctrl>-d to exit.\n'
'Run Python code from external files with: run filename.py\n')
exit_msg = 'Leaving IPython, back to {}'.format(sys.argv[0])
- if self.locals_in_py:
- # noinspection PyUnusedLocal
- def load_ipy(cmd2_instance, app):
- embed(banner1=banner, exit_msg=exit_msg)
- load_ipy(self, bridge)
- else:
- # noinspection PyUnusedLocal
- def load_ipy(app):
- embed(banner1=banner, exit_msg=exit_msg)
- load_ipy(bridge)
+ def load_ipy(cmd2_app: Cmd):
+ """
+ Embed an IPython shell in an environment that is restricted to only the variables in this function
+ :param cmd2_app: the instance of the cmd2 app
+ """
+ # Create a variable pointing to the PyscriptBridge and name it using the value of py_bridge_name
+ bridge = PyscriptBridge(cmd2_app)
+ exec("{} = bridge".format(cmd2_app.py_bridge_name))
+
+ # Add self variable pointing to cmd2_app, if allowed
+ if cmd2_app.locals_in_py:
+ exec("self = cmd2_app")
+
+ # Delete these names from the environment
+ del bridge
+ del cmd2_app
+
+ embed(banner1=banner, exit_msg=exit_msg)
+
+ load_ipy(self)
history_description = "View, run, edit, save, or clear previously entered commands"