New PyCrust from Patrick O'Brien
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15058 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -3,18 +3,18 @@
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython.wx import *
|
||||
from crust import CrustFrame
|
||||
from PyCrust.crust import CrustFrame
|
||||
|
||||
|
||||
class App(wxApp):
|
||||
"""PyCrust standalone application."""
|
||||
|
||||
|
||||
def OnInit(self):
|
||||
locals = {'__app__': 'PyCrust Standalone Application'}
|
||||
self.crustFrame = CrustFrame(locals=locals, size=(800,600))
|
||||
self.crustFrame = CrustFrame(locals=locals)
|
||||
self.crustFrame.Show(true)
|
||||
self.SetTopWindow(self.crustFrame)
|
||||
# Add the application object to the sys module's namespace.
|
||||
@@ -33,4 +33,4 @@ def main():
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
@@ -3,19 +3,19 @@
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
# We use this object to get more introspection when run standalone.
|
||||
application = None
|
||||
|
||||
import filling
|
||||
from PyCrust import filling
|
||||
|
||||
# These are imported just to have something interesting to inspect.
|
||||
import crust
|
||||
import interpreter
|
||||
import introspect
|
||||
import pseudo
|
||||
import shell
|
||||
from PyCrust import crust
|
||||
from PyCrust import interpreter
|
||||
from PyCrust import introspect
|
||||
from PyCrust import pseudo
|
||||
from PyCrust import shell
|
||||
import sys
|
||||
from wxPython import wx
|
||||
|
||||
@@ -32,4 +32,4 @@ def main():
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
@@ -23,12 +23,6 @@ Have you ever tried to bake a pie without one? Well, you
|
||||
shouldn't build a Python program without a PyCrust either.
|
||||
|
||||
|
||||
Where can I get the latest release of PyCrust?
|
||||
----------------------------------------------
|
||||
The latest PyCrust releases are available at:
|
||||
http://sourceforge.net/project/showfiles.php?group_id=31263
|
||||
|
||||
|
||||
What else do I need to use PyCrust?
|
||||
-----------------------------------
|
||||
PyCrust requires Python 2.1 or later, and wxPython 2.3.1 or later.
|
||||
@@ -37,32 +31,36 @@ Python is available at http://www.python.org/.
|
||||
wxPython is available at http://www.wxpython.org/.
|
||||
|
||||
|
||||
Where can I get the latest version of PyCrust?
|
||||
----------------------------------------------
|
||||
The latest production version ships with wxPython.
|
||||
The latest developer version is available in CVS at:
|
||||
http://sourceforge.net/cvs/?group_id=31263
|
||||
|
||||
|
||||
Where is the PyCrust project hosted?
|
||||
------------------------------------
|
||||
At SourceForge, of course. The SourceForge summary page:
|
||||
http://sourceforge.net/projects/pycrust/
|
||||
|
||||
|
||||
I found a bug in PyCrust, what do I do with it?
|
||||
-----------------------------------------------
|
||||
You can send it to me at pobrien@orbtech.com.
|
||||
|
||||
|
||||
I want a new feature added to PyCrust. Will you do it?
|
||||
------------------------------------------------------
|
||||
Flattery and money will get you anything. Short of that, you
|
||||
can send me a request and I'll see what I can do.
|
||||
|
||||
|
||||
Does PyCrust have a mailing list full of wonderful people?
|
||||
----------------------------------------------------------
|
||||
As a matter of fact, we do. Join the PyCrust mailing lists at:
|
||||
http://sourceforge.net/mail/?group_id=31263
|
||||
|
||||
|
||||
I found a bug in PyCrust, what do I do with it?
|
||||
-----------------------------------------------
|
||||
You can send it to me at pobrien@orbtech.com, or, preferably,
|
||||
submit a bug report on our bug tracker at SourceForge:
|
||||
http://sourceforge.net/tracker/?group_id=31263
|
||||
|
||||
|
||||
I want a new feature added to PyCrust. Will you do it?
|
||||
------------------------------------------------------
|
||||
Flattery and money will get you anything. Short of that, you
|
||||
can try posting a request on our feature tracker at SourceForge:
|
||||
http://sourceforge.net/tracker/?group_id=31263
|
||||
|
||||
|
||||
What is the CVS information for this README file?
|
||||
-------------------------------------------------
|
||||
$Date$
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython.wx import *
|
||||
from shell import Shell
|
||||
@@ -14,7 +14,7 @@ class Crust(wxSplitterWindow):
|
||||
"""PyCrust Crust based on wxSplitterWindow."""
|
||||
|
||||
name = 'PyCrust Crust'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
||||
size=wxDefaultSize, style=wxSP_3D, name='Crust Window', \
|
||||
@@ -42,7 +42,7 @@ class CrustFrame(wxFrame, ShellMenu):
|
||||
"""Frame containing all the PyCrust components."""
|
||||
|
||||
name = 'PyCrust Frame'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent=None, id=-1, title='PyCrust', \
|
||||
pos=wxDefaultPosition, size=wxDefaultSize, \
|
||||
@@ -52,7 +52,7 @@ class CrustFrame(wxFrame, ShellMenu):
|
||||
"""Create a PyCrust CrustFrame instance."""
|
||||
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||
intro += '\nSponsored by Orbtech - Your Source For Python Development Services'
|
||||
intro += '\nSponsored by Orbtech - Specializing in Python Application Development'
|
||||
self.CreateStatusBar()
|
||||
self.SetStatusText(intro.replace('\n', ', '))
|
||||
if wxPlatform == '__WXMSW__':
|
||||
|
@@ -3,7 +3,7 @@ the local namespace or any object."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython.wx import *
|
||||
from wxPython.stc import *
|
||||
@@ -19,7 +19,7 @@ class FillingTree(wxTreeCtrl):
|
||||
"""PyCrust FillingTree based on wxTreeCtrl."""
|
||||
|
||||
name = 'PyCrust Filling Tree'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
||||
size=wxDefaultSize, style=wxTR_HAS_BUTTONS, \
|
||||
@@ -203,7 +203,7 @@ class FillingText(wxStyledTextCtrl):
|
||||
"""PyCrust FillingText based on wxStyledTextCtrl."""
|
||||
|
||||
name = 'PyCrust Filling Text'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
||||
size=wxDefaultSize, style=wxCLIP_CHILDREN):
|
||||
@@ -265,7 +265,7 @@ class Filling(wxSplitterWindow):
|
||||
"""PyCrust Filling based on wxSplitterWindow."""
|
||||
|
||||
name = 'PyCrust Filling'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
||||
size=wxDefaultSize, style=wxSP_3D, name='Filling Window', \
|
||||
@@ -288,7 +288,7 @@ class FillingFrame(wxFrame):
|
||||
"""Frame containing the PyCrust filling, or namespace tree component."""
|
||||
|
||||
name = 'PyCrust Filling Frame'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent=None, id=-1, title='PyFilling', \
|
||||
pos=wxDefaultPosition, size=wxDefaultSize, \
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -13,7 +13,7 @@ import introspect
|
||||
class Interpreter(InteractiveInterpreter):
|
||||
"""PyCrust Interpreter based on code.InteractiveInterpreter."""
|
||||
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, locals=None, rawin=None, \
|
||||
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr):
|
||||
@@ -102,4 +102,4 @@ class InterpreterAlaCarte(Interpreter):
|
||||
sys.ps1 = ps1
|
||||
sys.ps2 = ps2
|
||||
|
||||
|
||||
|
||||
|
@@ -3,7 +3,7 @@ like call tips and command auto completion."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
import inspect
|
||||
import string
|
||||
@@ -14,117 +14,128 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1, \
|
||||
"""Return list of auto-completion options for command.
|
||||
|
||||
The list of options will be based on the locals namespace."""
|
||||
|
||||
attributes = []
|
||||
# Get the proper chunk of code from the command.
|
||||
root = getRoot(command, terminator='.')
|
||||
try:
|
||||
object = eval(root, locals)
|
||||
if locals is not None:
|
||||
object = eval(root, locals)
|
||||
else:
|
||||
object = eval(root)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
attributes = getAttributeNames(object, includeMagic, \
|
||||
includeSingle, includeDouble)
|
||||
return attributes
|
||||
except:
|
||||
return []
|
||||
return attributes
|
||||
|
||||
def getAttributeNames(object, includeMagic=1, includeSingle=1, includeDouble=1):
|
||||
"""Return list of unique attributes, including inherited, for an object."""
|
||||
attributes = []
|
||||
dict = {}
|
||||
if not hasattrAlwaysReturnsTrue(object):
|
||||
# Add some attributes that don't always get picked up.
|
||||
# If they don't apply, they'll get filtered out at the end.
|
||||
attributes += ['__bases__', '__class__', '__dict__', '__name__', \
|
||||
'func_closure', 'func_code', 'func_defaults', \
|
||||
'func_dict', 'func_doc', 'func_globals', 'func_name']
|
||||
if includeMagic:
|
||||
try: attributes += object._getAttributeNames()
|
||||
except: pass
|
||||
# Get all attribute names, removing duplicates from the attribute list.
|
||||
for item in getAllAttributeNames(object):
|
||||
# Get all attribute names.
|
||||
attrdict = getAllAttributeNames(object)
|
||||
for attrlist in attrdict.values():
|
||||
attributes += attrlist
|
||||
# Remove duplicates from the attribute list.
|
||||
for item in attributes:
|
||||
dict[item] = None
|
||||
attributes += dict.keys()
|
||||
attributes = dict.keys()
|
||||
attributes.sort(lambda x, y: cmp(x.upper(), y.upper()))
|
||||
if not includeSingle:
|
||||
attributes = filter(lambda item: item[0]!='_' or item[1]=='_', attributes)
|
||||
attributes = filter(lambda item: item[0]!='_' \
|
||||
or item[1]=='_', attributes)
|
||||
if not includeDouble:
|
||||
attributes = filter(lambda item: item[:2]!='__', attributes)
|
||||
# Make sure we haven't picked up any bogus attributes somehow.
|
||||
attributes = [attribute for attribute in attributes if hasattr(object, attribute)]
|
||||
attributes = [attribute for attribute in attributes \
|
||||
if hasattr(object, attribute)]
|
||||
return attributes
|
||||
|
||||
def hasattrAlwaysReturnsTrue(object):
|
||||
return hasattr(object, 'bogu5_123_aTTri8ute')
|
||||
|
||||
def getAllAttributeNames(object):
|
||||
"""Return list of all attributes, including inherited, for an object.
|
||||
"""Return mapping of all attributes, including inherited, for an object.
|
||||
|
||||
Recursively walk through a class and all base classes.
|
||||
"""
|
||||
attrdict = {} # (object, technique, count): [list of attributes]
|
||||
# !!!
|
||||
# !!! Do Not use hasattr() as a test anywhere in this function,
|
||||
# !!! because it is unreliable with remote objects - xmlrpc, soap, etc.
|
||||
# !!! They always return true for hasattr().
|
||||
# !!!
|
||||
attributes = []
|
||||
key = str(object)
|
||||
# Wake up sleepy objects - a hack for ZODB objects in "ghost" state.
|
||||
wakeupcall = dir(object)
|
||||
del wakeupcall
|
||||
# Get attributes available through the normal convention.
|
||||
attributes += dir(object)
|
||||
attributes = dir(object)
|
||||
attrdict[(key, 'dir', len(attributes))] = attributes
|
||||
# Get attributes from the object's dictionary, if it has one.
|
||||
try:
|
||||
keys = object.__dict__.keys()
|
||||
except:
|
||||
attributes = object.__dict__.keys()
|
||||
attributes.sort()
|
||||
except: # Must catch all because object might have __getattr__.
|
||||
pass
|
||||
else:
|
||||
attributes += keys
|
||||
attrdict[(key, '__dict__', len(attributes))] = attributes
|
||||
# For a class instance, get the attributes for the class.
|
||||
if hasattr(object, '__class__'):
|
||||
# Break a circular reference. This happens with extension classes.
|
||||
if object.__class__ is object:
|
||||
try:
|
||||
klass = object.__class__
|
||||
except: # Must catch all because object might have __getattr__.
|
||||
pass
|
||||
else:
|
||||
if klass is object:
|
||||
# Break a circular reference. This happens with extension classes.
|
||||
pass
|
||||
else:
|
||||
attributes += getAllAttributeNames(object.__class__)
|
||||
attrdict.update(getAllAttributeNames(klass))
|
||||
# Also get attributes from any and all parent classes.
|
||||
try:
|
||||
bases = object.__bases__
|
||||
except:
|
||||
except: # Must catch all because object might have __getattr__.
|
||||
pass
|
||||
else:
|
||||
if isinstance(bases, type(())):
|
||||
if isinstance(bases, types.TupleType):
|
||||
for base in bases:
|
||||
if type(base) is types.TypeType:
|
||||
# Break a circular reference. Happens in Python 2.2.
|
||||
pass
|
||||
else:
|
||||
attributes += getAllAttributeNames(base)
|
||||
return attributes
|
||||
attrdict.update(getAllAttributeNames(base))
|
||||
return attrdict
|
||||
|
||||
def getCallTip(command='', locals=None):
|
||||
"""Return call tip text for a command.
|
||||
"""For a command, return a tuple of object name, argspec, tip text.
|
||||
|
||||
The call tip information will be based on the locals namespace."""
|
||||
|
||||
calltip = ('', '', '')
|
||||
calltip = ('', '', '') # object name, argspec, tip text.
|
||||
# Get the proper chunk of code from the command.
|
||||
root = getRoot(command, terminator='(')
|
||||
try:
|
||||
object = eval(root, locals)
|
||||
if locals is not None:
|
||||
object = eval(root, locals)
|
||||
else:
|
||||
object = eval(root)
|
||||
except:
|
||||
return calltip
|
||||
name = ''
|
||||
dropSelf = 1
|
||||
# Switch to the object that has the information we need.
|
||||
if inspect.isbuiltin(object):
|
||||
# Builtin functions don't have an argspec that we can get.
|
||||
pass
|
||||
elif inspect.ismethod(object) or hasattr(object, 'im_func'):
|
||||
# Get the function from the object otherwise inspect.getargspec()
|
||||
# complains that the object isn't a Python function.
|
||||
object = object.im_func
|
||||
elif inspect.isclass(object):
|
||||
# Get the __init__ method function for the class.
|
||||
constructor = getConstructor(object)
|
||||
if constructor is not None:
|
||||
object = constructor
|
||||
elif callable(object):
|
||||
# Get the __call__ method instead.
|
||||
try:
|
||||
object = object.__call__.im_func
|
||||
except:
|
||||
dropSelf = 0
|
||||
else:
|
||||
dropSelf = 0
|
||||
if hasattr(object, '__name__'):
|
||||
object, dropSelf = getBaseObject(object)
|
||||
try:
|
||||
name = object.__name__
|
||||
except AttributeError:
|
||||
pass
|
||||
tip1 = ''
|
||||
argspec = ''
|
||||
if inspect.isbuiltin(object):
|
||||
@@ -134,8 +145,8 @@ def getCallTip(command='', locals=None):
|
||||
# tip1 is a string like: "getCallTip(command='', locals=None)"
|
||||
argspec = apply(inspect.formatargspec, inspect.getargspec(object))
|
||||
if dropSelf:
|
||||
# The first parameter to a method is a reference to the
|
||||
# instance, usually coded as "self", and is passed
|
||||
# The first parameter to a method is a reference to an
|
||||
# instance, usually coded as "self", and is usually passed
|
||||
# automatically by Python and therefore we want to drop it.
|
||||
temp = argspec.split(',')
|
||||
if len(temp) == 1: # No other arguments.
|
||||
@@ -158,6 +169,89 @@ def getCallTip(command='', locals=None):
|
||||
calltip = (name, argspec[1:-1], tip.strip())
|
||||
return calltip
|
||||
|
||||
def getRoot(command, terminator=None):
|
||||
"""Return the rightmost root portion of an arbitrary Python command.
|
||||
|
||||
Return only the root portion that can be eval()'d without side effects.
|
||||
The command would normally terminate with a "(" or ".". The terminator
|
||||
and anything after the terminator will be dropped."""
|
||||
root = ''
|
||||
validChars = "._" + string.uppercase + string.lowercase + string.digits
|
||||
emptyTypes = ("''", '""', '""""""', "''''''", '[]', '()', '{}')
|
||||
validSeparators = string.whitespace + ',+-*/=%<>&|^~:([{'
|
||||
# Drop the final terminator and anything that follows.
|
||||
command = rtrimTerminus(command, terminator)
|
||||
if len(command) == 0:
|
||||
root = ''
|
||||
elif command in emptyTypes and terminator in ('.', '', None):
|
||||
# Let empty type delimiter pairs go through.
|
||||
root = command
|
||||
else:
|
||||
# Go backward through the command until we hit an "invalid" character.
|
||||
i = len(command)
|
||||
while i and command[i-1] in validChars:
|
||||
i -= 1
|
||||
# Default to everything from the "invalid" character to the end.
|
||||
root = command[i:]
|
||||
# Override certain exceptions.
|
||||
if i > 0 and command[i-1] in ("'", '"'):
|
||||
# Detect situations where we are in the middle of a string.
|
||||
# This code catches the simplest case, but needs to catch others.
|
||||
root = ''
|
||||
elif ((2 <= i < len(command) and command[i] == '.') \
|
||||
or (2 <= i <= len(command) and terminator in ('.', '', None))) \
|
||||
and command[i-2:i] in emptyTypes:
|
||||
# Allow empty types to get through.
|
||||
# Don't confuse an empty tupple with an argumentless callable.
|
||||
if i == 2 or (i >= 3 and command[i-3] in validSeparators):
|
||||
root = command[i-2:]
|
||||
return root
|
||||
|
||||
def rtrimTerminus(command, terminator=None):
|
||||
"""Return command minus the final terminator and anything that follows."""
|
||||
if terminator:
|
||||
pieces = command.split(terminator)
|
||||
if len(pieces) > 1:
|
||||
command = terminator.join(pieces[:-1])
|
||||
return command
|
||||
|
||||
def getBaseObject(object):
|
||||
"""Return base object and dropSelf indicator for an object."""
|
||||
if inspect.isbuiltin(object):
|
||||
# Builtin functions don't have an argspec that we can get.
|
||||
dropSelf = 0
|
||||
elif inspect.ismethod(object):
|
||||
# Get the function from the object otherwise inspect.getargspec()
|
||||
# complains that the object isn't a Python function.
|
||||
try:
|
||||
if object.im_self is None:
|
||||
# This is an unbound method so we do not drop self from the
|
||||
# argspec, since an instance must be passed as the first arg.
|
||||
dropSelf = 0
|
||||
else:
|
||||
dropSelf = 1
|
||||
object = object.im_func
|
||||
except AttributeError:
|
||||
dropSelf = 0
|
||||
elif inspect.isclass(object):
|
||||
# Get the __init__ method function for the class.
|
||||
constructor = getConstructor(object)
|
||||
if constructor is not None:
|
||||
object = constructor
|
||||
dropSelf = 1
|
||||
else:
|
||||
dropSelf = 0
|
||||
elif callable(object):
|
||||
# Get the __call__ method instead.
|
||||
try:
|
||||
object = object.__call__.im_func
|
||||
dropSelf = 1
|
||||
except AttributeError:
|
||||
dropSelf = 0
|
||||
else:
|
||||
dropSelf = 0
|
||||
return object, dropSelf
|
||||
|
||||
def getConstructor(object):
|
||||
"""Return constructor for class object, or None if there isn't one."""
|
||||
try:
|
||||
@@ -169,40 +263,5 @@ def getConstructor(object):
|
||||
return constructor
|
||||
return None
|
||||
|
||||
def getRoot(command, terminator=None):
|
||||
"""Return the rightmost root portion of an arbitrary Python command.
|
||||
|
||||
The command would normally terminate with a "(" or ".". Anything after
|
||||
the terminator will be dropped, allowing you to get back to the root.
|
||||
Return only the root portion that can be eval()'d without side effects.
|
||||
"""
|
||||
root = ''
|
||||
validChars = "._" + string.uppercase + string.lowercase + string.digits
|
||||
if terminator:
|
||||
# Drop the final terminator and anything that follows.
|
||||
pieces = command.split(terminator)
|
||||
if len(pieces) > 1:
|
||||
command = terminator.join(pieces[:-1])
|
||||
if len(command) == 0:
|
||||
root = ''
|
||||
elif command in ("''", '""', '""""""', '[]', '()', '{}'):
|
||||
# Let empty type delimiter pairs go through.
|
||||
root = command
|
||||
else:
|
||||
# Go backward through the command until we hit an "invalid" character.
|
||||
i = len(command)
|
||||
while i and command[i-1] in validChars:
|
||||
i -= 1
|
||||
# Detect situations where we are in the middle of a string.
|
||||
# This code catches the simplest case, but needs to catch others.
|
||||
if command[i-1] in ("'", '"'):
|
||||
# We're in the middle of a string so we aren't dealing with an
|
||||
# object and it would be misleading to return anything here.
|
||||
root = ''
|
||||
else:
|
||||
# Grab everything from the "invalid" character to the end.
|
||||
root = command[i:]
|
||||
return root
|
||||
|
||||
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
class PseudoKeyword:
|
||||
"""A callable class that calls a method passed as a parameter.
|
||||
@@ -27,8 +27,10 @@ class PseudoKeyword:
|
||||
def __init__(self, method):
|
||||
"""Create a callable object that executes method when called."""
|
||||
|
||||
# XXX Should probably check that this is a callable object.
|
||||
self.method = method
|
||||
if callable(method):
|
||||
self.method = method
|
||||
else:
|
||||
raise ValueError, 'method must be callable'
|
||||
|
||||
def __call__(self, *args, **kwds):
|
||||
self.method(*args, **kwds)
|
||||
@@ -63,7 +65,10 @@ class PseudoFile:
|
||||
class PseudoFileIn(PseudoFile):
|
||||
|
||||
def __init__(self, readline):
|
||||
self.readline = readline
|
||||
if callable(readline):
|
||||
self.readline = readline
|
||||
else:
|
||||
raise ValueError, 'readline must be callable'
|
||||
|
||||
def isatty(self):
|
||||
return 1
|
||||
@@ -72,7 +77,10 @@ class PseudoFileIn(PseudoFile):
|
||||
class PseudoFileOut(PseudoFile):
|
||||
|
||||
def __init__(self, write):
|
||||
self.write = write
|
||||
if callable(write):
|
||||
self.write = write
|
||||
else:
|
||||
raise ValueError, 'write must be callable'
|
||||
|
||||
def isatty(self):
|
||||
return 1
|
||||
@@ -81,10 +89,13 @@ class PseudoFileOut(PseudoFile):
|
||||
class PseudoFileErr(PseudoFile):
|
||||
|
||||
def __init__(self, write):
|
||||
self.write = write
|
||||
if callable(write):
|
||||
self.write = write
|
||||
else:
|
||||
raise ValueError, 'write must be callable'
|
||||
|
||||
def isatty(self):
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -6,7 +6,7 @@ Sponsored by Orbtech - Your Source For Python Development Services"""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
from wxPython.wx import *
|
||||
from wxPython.stc import *
|
||||
@@ -52,7 +52,7 @@ class ShellFacade:
|
||||
still accessible, even though only some are visible to the user."""
|
||||
|
||||
name = 'PyCrust Shell Interface'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, other):
|
||||
"""Create a ShellFacade instance."""
|
||||
@@ -128,7 +128,7 @@ class Shell(wxStyledTextCtrl):
|
||||
"""PyCrust Shell based on wxStyledTextCtrl."""
|
||||
|
||||
name = 'PyCrust Shell'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
||||
size=wxDefaultSize, style=wxCLIP_CHILDREN, introText='', \
|
||||
@@ -231,18 +231,9 @@ class Shell(wxStyledTextCtrl):
|
||||
def setBuiltinKeywords(self):
|
||||
"""Create pseudo keywords as part of builtins.
|
||||
|
||||
This is a rather clever hack that sets "close", "exit" and "quit"
|
||||
to a PseudoKeyword object so that we can make them do what we want.
|
||||
In this case what we want is to call our self.quit() method.
|
||||
The user can type "close", "exit" or "quit" without the final parens.
|
||||
This simply sets "close", "exit" and "quit" to a helpful string.
|
||||
"""
|
||||
## POB: This is having some weird side-effects so I'm taking it out.
|
||||
## import __builtin__
|
||||
## from pseudo import PseudoKeyword
|
||||
## __builtin__.close = __builtin__.exit = __builtin__.quit = \
|
||||
## PseudoKeyword(self.quit)
|
||||
import __builtin__
|
||||
from pseudo import PseudoKeyword
|
||||
__builtin__.close = __builtin__.exit = __builtin__.quit = \
|
||||
'Click on the close button to leave the application.'
|
||||
|
||||
@@ -322,6 +313,7 @@ class Shell(wxStyledTextCtrl):
|
||||
if self.AutoCompActive(): self.AutoCompCancel()
|
||||
# Get the command between the prompt and the cursor.
|
||||
# Add the '(' to the end of the command.
|
||||
self.ReplaceSelection('')
|
||||
command = self.GetTextRange(stoppos, currpos) + '('
|
||||
self.write('(')
|
||||
if self.autoCallTip: self.autoCallTipShow(command)
|
||||
@@ -939,21 +931,17 @@ class ShellMenu:
|
||||
|
||||
m = self.autocompMenu = wxMenu()
|
||||
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion', \
|
||||
'Show auto completion during dot syntax', \
|
||||
kind=wxITEM_CHECK)
|
||||
'Show auto completion during dot syntax', 1)
|
||||
m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes', \
|
||||
'Include attributes visible to __getattr__ and __setattr__', \
|
||||
kind=wxITEM_CHECK)
|
||||
'Include attributes visible to __getattr__ and __setattr__', 1)
|
||||
m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores', \
|
||||
'Include attibutes prefixed by a single underscore', \
|
||||
kind=wxITEM_CHECK)
|
||||
'Include attibutes prefixed by a single underscore', 1)
|
||||
m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores', \
|
||||
'Include attibutes prefixed by a double underscore', \
|
||||
kind=wxITEM_CHECK)
|
||||
'Include attibutes prefixed by a double underscore', 1)
|
||||
|
||||
m = self.calltipsMenu = wxMenu()
|
||||
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips', \
|
||||
'Show call tips with argument specifications', kind=wxITEM_CHECK)
|
||||
'Show call tips with argument specifications', 1)
|
||||
|
||||
m = self.optionsMenu = wxMenu()
|
||||
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu, \
|
||||
@@ -1091,7 +1079,7 @@ class ShellFrame(wxFrame, ShellMenu):
|
||||
"""Frame containing the PyCrust shell component."""
|
||||
|
||||
name = 'PyCrust Shell Frame'
|
||||
revision = __version__
|
||||
revision = __revision__
|
||||
|
||||
def __init__(self, parent=None, id=-1, title='PyShell', \
|
||||
pos=wxDefaultPosition, size=wxDefaultSize, \
|
||||
@@ -1100,7 +1088,7 @@ class ShellFrame(wxFrame, ShellMenu):
|
||||
"""Create a PyCrust ShellFrame instance."""
|
||||
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||
intro += '\nSponsored by Orbtech - Your Source For Python Development Services'
|
||||
intro += '\nSponsored by Orbtech - Specializing in Python Application Development'
|
||||
self.CreateStatusBar()
|
||||
self.SetStatusText(intro.replace('\n', ', '))
|
||||
if wxPlatform == '__WXMSW__':
|
||||
|
@@ -4,7 +4,7 @@ interpreter, each have a revision property based on the CVS Revision."""
|
||||
|
||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||
__cvsid__ = "$Id$"
|
||||
__version__ = "$Revision$"[11:-2]
|
||||
__revision__ = "$Revision$"[11:-2]
|
||||
|
||||
VERSION = '0.7.1'
|
||||
VERSION = '0.7.2'
|
||||
|
||||
|
Reference in New Issue
Block a user