17
17
from spyderlib.qt.compat import getexistingdirectory
20
from spyderlib.utils.qthelpers import (create_toolbutton, create_action,
21
get_std_icon, DialogManager,
20
from spyderlib.utils.qthelpers import (get_icon, get_std_icon, add_actions,
21
create_toolbutton, create_action,
23
23
from spyderlib.utils.environ import RemoteEnvDialog
24
24
from spyderlib.utils.programs import get_python_args
25
25
from spyderlib.utils.misc import get_python_executable
26
from spyderlib.baseconfig import _, get_module_source_path
27
from spyderlib.config import get_icon
26
from spyderlib.baseconfig import _, get_module_source_path, DEBUG
28
27
from spyderlib.widgets.shell import PythonShellWidget
29
28
from spyderlib.widgets.externalshell.namespacebrowser import NamespaceBrowser
30
29
from spyderlib.widgets.externalshell.monitor import communicate, write_packet
36
35
class ExtPythonShellWidget(PythonShellWidget):
37
def __init__(self, parent, history_filename, debug=False, profile=False):
38
PythonShellWidget.__init__(self, parent, history_filename,
36
def __init__(self, parent, history_filename, profile=False):
37
PythonShellWidget.__init__(self, parent, history_filename, profile)
41
40
def set_externalshell(self, externalshell):
42
41
# ExternalShellBase instance:
119
118
"""Return True if object is defined"""
120
119
return self.ask_monitor("isdefined('%s', force_import=%s)"
121
120
% (objtxt, force_import))
123
def get_completion(self, objtxt):
124
"""Return completion list associated to object name"""
125
return self.ask_monitor("getcomplist('%s')" % objtxt)
127
122
def get_module_completion(self, objtxt):
128
123
"""Return module completion list associated to object name"""
129
return self.ask_monitor("getmodcomplist('%s')" % objtxt)
124
return self.ask_monitor("getmodcomplist('%s', %s)" % \
131
127
def get_cwd(self):
132
128
"""Return shell current working directory"""
148
144
"""Return sys.path[:]"""
149
145
return self.ask_monitor("getsyspath()")
147
def set_spyder_breakpoints(self):
148
"""Set Spyder breakpoints into debugging session"""
149
return self.ask_monitor("set_spyder_breakpoints()")
152
152
class ExternalPythonShell(ExternalShellBase):
153
153
"""External Shell widget: execute Python script in a separate process"""
154
154
SHELL_CLASS = ExtPythonShellWidget
155
155
def __init__(self, parent=None, fname=None, wdir=None,
156
156
interact=False, debug=False, path=[], python_args='',
157
ipython_shell=False, ipython_kernel=False,
158
arguments='', stand_alone=None,
157
ipykernel=False, arguments='', stand_alone=None,
159
158
umd_enabled=True, umd_namelist=[], umd_verbose=True,
160
159
pythonstartup=None, pythonexecutable=None,
161
160
monitor_enabled=True, mpl_patch_enabled=True,
214
213
assert isinstance(arguments, basestring)
215
214
self.arguments = arguments
217
self.is_ipython_shell = ipython_shell
218
self.is_ipython_kernel = ipython_kernel
219
if self.is_ipython_shell or self.is_ipython_kernel:
216
self.connection_file = None
217
self.is_ipykernel = ipykernel
218
if self.is_ipykernel:
221
# Running our custom startup script for IPython sessions:
222
# (see spyderlib/widgets/externalshell/startup.py)
220
# Running our custom startup script for IPython kernels:
221
# (see spyderlib/widgets/externalshell/start_ipython_kernel.py)
223
222
self.fname = get_module_source_path(
224
'spyderlib.widgets.externalshell', 'startup.py')
223
'spyderlib.widgets.externalshell', 'start_ipython_kernel.py')
226
225
self.shell.set_externalshell(self)
309
309
def is_interpreter(self):
310
"""Return True if shellwidget is a Python/IPython interpreter"""
310
"""Return True if shellwidget is a Python interpreter"""
311
311
return self.is_interpreter
313
313
def get_shell_widget(self):
340
340
ExternalShellBase.set_buttons_runnning_state(self, state)
341
341
self.interact_action.setEnabled(not state and not self.is_interpreter)
342
342
self.debug_action.setEnabled(not state and not self.is_interpreter)
343
self.args_action.setEnabled(not state and
344
(not self.is_interpreter or\
345
self.is_ipython_shell))
343
self.args_action.setEnabled(not state and not self.is_interpreter)
347
345
if self.arguments:
348
346
argstr = _("Arguments: %s") % self.arguments
380
378
self.shell.clear()
382
380
self.process = QProcess(self)
383
if self.merge_output_channels or self.is_ipython_shell:
381
if self.merge_output_channels:
384
382
self.process.setProcessChannelMode(QProcess.MergedChannels)
386
384
self.process.setProcessChannelMode(QProcess.SeparateChannels)
394
392
#-------------------------Python specific-------------------------------
395
393
# Python arguments
396
p_args = ['-u'] + get_python_args(self.fname, self.python_args,
397
self.interact_action.isChecked(),
398
self.debug_action.isChecked(),
397
p_args += get_python_args(self.fname, self.python_args,
398
self.interact_action.isChecked(),
399
self.debug_action.isChecked(),
401
402
env = [unicode(_path) for _path in self.process.systemEnvironment()]
402
404
if self.pythonstartup:
403
405
env.append('PYTHONSTARTUP=%s' % self.pythonstartup)
418
420
self.connect(self.notification_thread,
419
421
SIGNAL('new_ipython_kernel(QString)'),
421
self.emit(SIGNAL('create_ipython_frontend(QString)'),
423
self.emit(SIGNAL('create_ipython_client(QString)'),
423
425
self.connect(self.notification_thread,
424
426
SIGNAL('open_file(QString,int)'),
454
456
env.append('UMD_ENABLED=%r' % self.umd_enabled)
455
457
env.append('UMD_NAMELIST=%s' % ','.join(self.umd_namelist))
456
458
env.append('UMD_VERBOSE=%r' % self.umd_verbose)
458
# IPython related configuration
459
if self.is_ipython_shell:
460
env.append('IPYTHON=True')
461
# Do not call msvcrt.getch in IPython.genutils.page_more:
462
env.append('TERM=emacs')
463
elif self.is_ipython_kernel:
464
env.append('IPYTHON_KERNEL=True')
461
env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel)
475
472
# Adding path list to PYTHONPATH environment variable
476
473
add_pathlist_to_PYTHONPATH(env, pathlist)
478
self.process.setEnvironment(env)
479
475
#-------------------------Python specific-------------------------------
481
477
self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
496
492
executable = self.pythonexecutable
497
493
if executable is None:
498
494
executable = get_python_executable()
496
# Fixes for our Mac app:
497
# 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app,
498
# but their values are messing sys.path for external interpreters
499
# (e.g. EPD) so we need to remove them from the environment.
500
# 2. Add this file's dir to PYTHONPATH. This will make every external
501
# interpreter to use our sitecustomize script.
502
# 3. Remove PYTHONOPTIMIZE from env so that we can have assert
503
# statements working with our interpreters (See Issue 1281)
504
if sys.platform == 'darwin' and 'Spyder.app' in __file__:
505
env.append('SPYDER_INTERPRETER=%s' % executable)
506
if 'Spyder.app' not in executable:
507
env = [p for p in env if not (p.startswith('PYTHONPATH') or \
508
p.startswith('PYTHONHOME'))] # 1.
510
env.append('PYTHONPATH=%s' % osp.dirname(__file__)) # 2.
512
env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')] # 3.
514
self.process.setEnvironment(env)
499
515
self.process.start(executable, p_args)
500
516
#-------------------------Python specific-------------------------------
509
525
self.emit(SIGNAL('started()'))
511
527
return self.process
529
def finished(self, exit_code, exit_status):
530
"""Reimplement ExternalShellBase method"""
531
ExternalShellBase.finished(self, exit_code, exit_status)
532
self.introspection_socket = None
513
535
#===============================================================================
524
546
QApplication.processEvents()
526
548
def send_to_process(self, text):
549
if not self.is_running():
527
552
if not isinstance(text, basestring):
528
553
text = unicode(text)
529
if self.install_qt_inputhook and not self.is_ipython_shell:
530
# For now, the Spyder's input hook does not work with IPython:
531
# with IPython v0.10 or non-Windows platforms, this is not a
532
# problem. However, with IPython v0.11 on Windows, this will be
533
# fixed by patching IPython to force it to use our inputhook.
534
if self.introspection_socket is not None:
535
communicate(self.introspection_socket,
536
"toggle_inputhook_flag(True)")
554
if self.install_qt_inputhook and self.introspection_socket is not None:
555
communicate(self.introspection_socket,
556
"toggle_inputhook_flag(True)")
537
557
# # Socket-based alternative (see input hook in sitecustomize.py):
538
558
# while self.local_server.hasPendingConnections():
539
559
# self.local_server.nextPendingConnection().write('go!')
540
if not self.is_ipython_shell and text.startswith(('%', '!')):
560
if text.startswith(('%', '!')):
541
561
text = 'evalsc(r"%s")\n' % text
542
562
if not text.endswith('\n'):