* Completing initial version of interactive tool support: added interactive

mode detection (plain python, `python -i', and ipython supported),
  and my canned initialization for interactive python environment
  (like MYSELF, ARGV).
master
wirawan 14 years ago
parent 47f6bced79
commit 1e3d236b1c
  1. 110
      interactive_tools.py

@ -1,4 +1,4 @@
# $Id: interactive_tools.py,v 1.1 2010-01-22 18:46:27 wirawan Exp $ # $Id: interactive_tools.py,v 1.2 2011-07-18 15:48:52 wirawan Exp $
# #
# wpylib.interactive_tools # wpylib.interactive_tools
# Created: 20091204 # Created: 20091204
@ -7,26 +7,110 @@
# Simple and dirty tools for interactive python mode # Simple and dirty tools for interactive python mode
# #
import atexit
import inspect
import os
import sys import sys
def init_interactive(): MSGLOG = sys.stderr
def get_global_namespace_(global_ns):
"""Internal routine to get global namespace from another function
in this module.
BEWARE the limitation! This function is rather fragile and must be
called such that the stack order is like this (in descending
order):
* global module statement ...
* a function from this module
* this function
"""
import pprint
if global_ns == None:
# Use introspection to fetch the global namespace of the calling
# function:
from inspect import stack
caller_info = stack()[2] # by default, _two_ level up
caller_frame = caller_info[0] # get the frame record
g = caller_frame.f_globals
else:
g = global_ns
try:
builtin_ns = g['__builtins__']
except:
builtin_ns = None # this should not ever happen!
if False: # for debugging only
pprint.pprint(stack())
print "caller_info = ",
pprint.pprint(caller_info)
pprint (sorted(g.keys()))
pprint (g['__builtins__'])
return (g, builtin_ns)
def detect_interactive(global_ns=None):
"""Detects if we are in an interactive python session.
"""
"""The detection scheme is rather complex one because each mode has its
own way of flagging that it is ``interactive''.
See some discussions in:
http://stackoverflow.com/questions/1212779/detecting-when-a-python-script-is-being-run-interactively
These are some known cases:
* For ipython, see if "__IPYTHON__" is defined in the user's global
namespace.
* For "python -i" invocation, sys.flags.interactive will be set to True.
* For vanilla "python" invocation with no argument, then sys.ps1
variable exists.
"""
(g, b) = get_global_namespace_(global_ns)
if "__IPYTHON__" in g or hasattr(b, "__IPYTHON__"):
return {
'session': 'ipython',
}
elif sys.flags.interactive:
return {
'session': 'python -i',
}
elif hasattr(sys, 'ps1'):
return {
'session': 'python',
}
else:
return False
def init_interactive(use_readline=True, global_ns=None):
"""Perform standard initialization for my scripts.
Some options can be given to tweak the environment.
Under ipython
"""
# ERROR: this still does not work. we need to execute the statements # ERROR: this still does not work. we need to execute the statements
# in the global (base) namespace, not in this function's namespace. # in the global (base) namespace, not in this function's namespace.
(g, b) = get_global_namespace_(global_ns)
int_info = detect_interactive(g)
if use_readline:
# Assume interactive python, create a completer if it hasn't been # Assume interactive python, create a completer if it hasn't been
# loaded. This is needed for e.g. sciclone, jaguar with no ipython # loaded. This is needed for e.g. sciclone, jaguar with no ipython
# there. # there.
if 'rlcompleter' not in sys.modules \ if 'rlcompleter' not in sys.modules \
and 'IPython.ipy_completers' not in sys.modules: and 'IPython.ipy_completers' not in sys.modules:
try: try:
import readline import readline
except ImportError: except ImportError:
print "Module readline not available." print >>MSGLOG, "Module readline not available."
else: else:
print "Loading classic readline/rlcompleter." print "Loading classic readline/rlcompleter."
import rlcompleter import rlcompleter
readline.parse_and_bind("tab: complete") readline.parse_and_bind("tab: complete")
_histfile = os.path.join(os.environ["HOME"], ".pyhistory") _histfile = os.path.join(os.environ["HOME"], ".pyhistory")
# read history, if it exists # read history, if it exists
if os.path.exists(_histfile): if os.path.exists(_histfile):
@ -34,3 +118,19 @@ def init_interactive():
# register saving handler # register saving handler
atexit.register(readline.write_history_file, _histfile) atexit.register(readline.write_history_file, _histfile)
del _histfile del _histfile
# Interestingly, under ipython the sys.argv is only "correct" to extract
# the program name at the first loading of the script.
# So we must capture that:
if int_info['session'] == 'ipython' and 'ARGV' not in g:
g['ARGV'] = sys.argv
try:
g['MYSELF'] = os.path.abspath(sys.argv[0])
except:
pass
elif int_info['session'] in ('python', 'python -i'):
g.setdefault('MYSELF', sys.argv[0])
g.setdefault('ARGV', sys.argv)
#print "_-helo"

Loading…
Cancel
Save