Skip to content

Commit 3254626

Browse files
committed
Fixed issue where ipy wasn't using the correct name for the PyscriptBridge
Renamed some class members for clarification purposes
1 parent 578593f commit 3254626

2 files changed

Lines changed: 55 additions & 40 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
sort, but it can be changed to a natural sort by setting the value to NATURAL_SORT_KEY.
3232
* `StatementParser` now expects shortcuts to be passed in as dictionary. This eliminates the step of converting the
3333
shortcuts dictionary into a tuple before creating `StatementParser`.
34+
* Renamed `Cmd.pyscript_name` to `Cmd.py_bridge_name`
35+
* Renamed `Cmd.pystate` to `Cmd.py_locals`
3436

3537
## 0.9.14 (June 29, 2019)
3638
* Enhancements

cmd2/cmd2.py

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,12 @@ def with_argument_list(*args: List[Callable], preserve_quotes: bool = False) ->
146146

147147
def arg_decorator(func: Callable):
148148
@functools.wraps(func)
149-
def cmd_wrapper(cmd2_instance, statement: Union[Statement, str]):
150-
_, parsed_arglist = cmd2_instance.statement_parser.get_command_arg_list(command_name,
151-
statement,
152-
preserve_quotes)
149+
def cmd_wrapper(cmd2_app, statement: Union[Statement, str]):
150+
_, parsed_arglist = cmd2_app.statement_parser.get_command_arg_list(command_name,
151+
statement,
152+
preserve_quotes)
153153

154-
return func(cmd2_instance, parsed_arglist)
154+
return func(cmd2_app, parsed_arglist)
155155

156156
command_name = func.__name__[len(COMMAND_FUNC_PREFIX):]
157157
cmd_wrapper.__doc__ = func.__doc__
@@ -185,23 +185,23 @@ def with_argparser_and_unknown_args(argparser: argparse.ArgumentParser, *,
185185
# noinspection PyProtectedMember
186186
def arg_decorator(func: Callable):
187187
@functools.wraps(func)
188-
def cmd_wrapper(cmd2_instance, statement: Union[Statement, str]):
189-
statement, parsed_arglist = cmd2_instance.statement_parser.get_command_arg_list(command_name,
190-
statement,
191-
preserve_quotes)
188+
def cmd_wrapper(cmd2_app, statement: Union[Statement, str]):
189+
statement, parsed_arglist = cmd2_app.statement_parser.get_command_arg_list(command_name,
190+
statement,
191+
preserve_quotes)
192192

193193
if ns_provider is None:
194194
namespace = None
195195
else:
196-
namespace = ns_provider(cmd2_instance)
196+
namespace = ns_provider(cmd2_app)
197197

198198
try:
199199
args, unknown = argparser.parse_known_args(parsed_arglist, namespace)
200200
except SystemExit:
201201
return
202202
else:
203203
setattr(args, '__statement__', statement)
204-
return func(cmd2_instance, args, unknown)
204+
return func(cmd2_app, args, unknown)
205205

206206
# argparser defaults the program name to sys.argv[0]
207207
# we want it to be the name of our command
@@ -243,23 +243,23 @@ def with_argparser(argparser: argparse.ArgumentParser, *,
243243
# noinspection PyProtectedMember
244244
def arg_decorator(func: Callable):
245245
@functools.wraps(func)
246-
def cmd_wrapper(cmd2_instance, statement: Union[Statement, str]):
247-
statement, parsed_arglist = cmd2_instance.statement_parser.get_command_arg_list(command_name,
248-
statement,
249-
preserve_quotes)
246+
def cmd_wrapper(cmd2_app, statement: Union[Statement, str]):
247+
statement, parsed_arglist = cmd2_app.statement_parser.get_command_arg_list(command_name,
248+
statement,
249+
preserve_quotes)
250250

251251
if ns_provider is None:
252252
namespace = None
253253
else:
254-
namespace = ns_provider(cmd2_instance)
254+
namespace = ns_provider(cmd2_app)
255255

256256
try:
257257
args = argparser.parse_args(parsed_arglist, namespace)
258258
except SystemExit:
259259
return
260260
else:
261261
setattr(args, '__statement__', statement)
262-
return func(cmd2_instance, args)
262+
return func(cmd2_app, args)
263263

264264
# argparser defaults the program name to sys.argv[0]
265265
# we want it to be the name of our command
@@ -412,9 +412,14 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
412412
# Command aliases and macros
413413
self.macros = dict()
414414

415-
self._pystate = {}
415+
# Keeps track of typed command history in the Python shell
416416
self._py_history = []
417-
self.pyscript_name = 'app'
417+
418+
# The name by which Python and IPython environments refer to the PyscriptBridge to call app commands
419+
self.py_bridge_name = 'app'
420+
421+
# Defines app-specific variables/functions available in Python shells and pyscripts
422+
self.py_locals = {}
418423

419424
self.statement_parser = StatementParser(allow_redirection=allow_redirection,
420425
terminators=terminators,
@@ -3231,17 +3236,17 @@ def py_quit():
32313236
raise EmbeddedConsoleExit
32323237

32333238
# Set up Python environment
3234-
self._pystate[self.pyscript_name] = bridge
3235-
self._pystate['run'] = py_run
3236-
self._pystate['quit'] = py_quit
3237-
self._pystate['exit'] = py_quit
3239+
self.py_locals[self.py_bridge_name] = bridge
3240+
self.py_locals['run'] = py_run
3241+
self.py_locals['quit'] = py_quit
3242+
self.py_locals['exit'] = py_quit
32383243

32393244
if self.locals_in_py:
3240-
self._pystate['self'] = self
3241-
elif 'self' in self._pystate:
3242-
del self._pystate['self']
3245+
self.py_locals['self'] = self
3246+
elif 'self' in self.py_locals:
3247+
del self.py_locals['self']
32433248

3244-
localvars = self._pystate
3249+
localvars = self.py_locals
32453250
interp = InteractiveConsole(locals=localvars)
32463251
interp.runcode('import sys, os;sys.path.insert(0, os.getcwd())')
32473252

@@ -3268,7 +3273,7 @@ def py_quit():
32683273
instructions = ('End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, `exit()`.\n'
32693274
'Non-Python commands can be issued with: {}("your command")\n'
32703275
'Run Python code from external script files with: run("script.py")'
3271-
.format(self.pyscript_name))
3276+
.format(self.py_bridge_name))
32723277

32733278
saved_cmd2_env = None
32743279

@@ -3335,22 +3340,30 @@ def do_run_pyscript(self, args: argparse.Namespace) -> bool:
33353340
def do_ipy(self, _: argparse.Namespace) -> None:
33363341
"""Enter an interactive IPython shell"""
33373342
from .pyscript_bridge import PyscriptBridge
3338-
bridge = PyscriptBridge(self)
3339-
33403343
banner = ('Entering an embedded IPython shell. Type quit or <Ctrl>-d to exit.\n'
33413344
'Run Python code from external files with: run filename.py\n')
33423345
exit_msg = 'Leaving IPython, back to {}'.format(sys.argv[0])
33433346

3344-
if self.locals_in_py:
3345-
# noinspection PyUnusedLocal
3346-
def load_ipy(cmd2_instance, app):
3347-
embed(banner1=banner, exit_msg=exit_msg)
3348-
load_ipy(self, bridge)
3349-
else:
3350-
# noinspection PyUnusedLocal
3351-
def load_ipy(app):
3352-
embed(banner1=banner, exit_msg=exit_msg)
3353-
load_ipy(bridge)
3347+
def load_ipy(cmd2_app: Cmd):
3348+
"""
3349+
Embed an IPython shell in an environment that is restricted to only the variables in this function
3350+
:param cmd2_app: the instance of the cmd2 app
3351+
"""
3352+
# Create a variable pointing to the PyscriptBridge and name it using the value of py_bridge_name
3353+
bridge = PyscriptBridge(cmd2_app)
3354+
exec("{} = bridge".format(cmd2_app.py_bridge_name))
3355+
3356+
# Add self variable pointing to cmd2_app, if allowed
3357+
if cmd2_app.locals_in_py:
3358+
exec("self = cmd2_app")
3359+
3360+
# Delete these names from the environment
3361+
del bridge
3362+
del cmd2_app
3363+
3364+
embed(banner1=banner, exit_msg=exit_msg)
3365+
3366+
load_ipy(self)
33543367

33553368
history_description = "View, run, edit, save, or clear previously entered commands"
33563369

0 commit comments

Comments
 (0)