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:
Robin Dunn
2002-04-09 21:57:35 +00:00
parent aacd7bb647
commit 31fa82942c
10 changed files with 223 additions and 167 deletions

View File

@@ -3,10 +3,10 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
from crust import CrustFrame from PyCrust.crust import CrustFrame
class App(wxApp): class App(wxApp):
@@ -14,7 +14,7 @@ class App(wxApp):
def OnInit(self): def OnInit(self):
locals = {'__app__': 'PyCrust Standalone Application'} locals = {'__app__': 'PyCrust Standalone Application'}
self.crustFrame = CrustFrame(locals=locals, size=(800,600)) self.crustFrame = CrustFrame(locals=locals)
self.crustFrame.Show(true) self.crustFrame.Show(true)
self.SetTopWindow(self.crustFrame) self.SetTopWindow(self.crustFrame)
# Add the application object to the sys module's namespace. # Add the application object to the sys module's namespace.

View File

@@ -3,19 +3,19 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
# We use this object to get more introspection when run standalone. # We use this object to get more introspection when run standalone.
application = None application = None
import filling from PyCrust import filling
# These are imported just to have something interesting to inspect. # These are imported just to have something interesting to inspect.
import crust from PyCrust import crust
import interpreter from PyCrust import interpreter
import introspect from PyCrust import introspect
import pseudo from PyCrust import pseudo
import shell from PyCrust import shell
import sys import sys
from wxPython import wx from wxPython import wx

View File

@@ -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. 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? What else do I need to use PyCrust?
----------------------------------- -----------------------------------
PyCrust requires Python 2.1 or later, and wxPython 2.3.1 or later. 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/. 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? Where is the PyCrust project hosted?
------------------------------------ ------------------------------------
At SourceForge, of course. The SourceForge summary page: At SourceForge, of course. The SourceForge summary page:
http://sourceforge.net/projects/pycrust/ 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? Does PyCrust have a mailing list full of wonderful people?
---------------------------------------------------------- ----------------------------------------------------------
As a matter of fact, we do. Join the PyCrust mailing lists at: As a matter of fact, we do. Join the PyCrust mailing lists at:
http://sourceforge.net/mail/?group_id=31263 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? What is the CVS information for this README file?
------------------------------------------------- -------------------------------------------------
$Date$ $Date$

View File

@@ -2,7 +2,7 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
from shell import Shell from shell import Shell
@@ -14,7 +14,7 @@ class Crust(wxSplitterWindow):
"""PyCrust Crust based on wxSplitterWindow.""" """PyCrust Crust based on wxSplitterWindow."""
name = 'PyCrust Crust' name = 'PyCrust Crust'
revision = __version__ revision = __revision__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \ def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxSP_3D, name='Crust Window', \ size=wxDefaultSize, style=wxSP_3D, name='Crust Window', \
@@ -42,7 +42,7 @@ class CrustFrame(wxFrame, ShellMenu):
"""Frame containing all the PyCrust components.""" """Frame containing all the PyCrust components."""
name = 'PyCrust Frame' name = 'PyCrust Frame'
revision = __version__ revision = __revision__
def __init__(self, parent=None, id=-1, title='PyCrust', \ def __init__(self, parent=None, id=-1, title='PyCrust', \
pos=wxDefaultPosition, size=wxDefaultSize, \ pos=wxDefaultPosition, size=wxDefaultSize, \
@@ -52,7 +52,7 @@ class CrustFrame(wxFrame, ShellMenu):
"""Create a PyCrust CrustFrame instance.""" """Create a PyCrust CrustFrame instance."""
wxFrame.__init__(self, parent, id, title, pos, size, style) wxFrame.__init__(self, parent, id, title, pos, size, style)
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION 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.CreateStatusBar()
self.SetStatusText(intro.replace('\n', ', ')) self.SetStatusText(intro.replace('\n', ', '))
if wxPlatform == '__WXMSW__': if wxPlatform == '__WXMSW__':

View File

@@ -3,7 +3,7 @@ the local namespace or any object."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
from wxPython.stc import * from wxPython.stc import *
@@ -19,7 +19,7 @@ class FillingTree(wxTreeCtrl):
"""PyCrust FillingTree based on wxTreeCtrl.""" """PyCrust FillingTree based on wxTreeCtrl."""
name = 'PyCrust Filling Tree' name = 'PyCrust Filling Tree'
revision = __version__ revision = __revision__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \ def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxTR_HAS_BUTTONS, \ size=wxDefaultSize, style=wxTR_HAS_BUTTONS, \
@@ -203,7 +203,7 @@ class FillingText(wxStyledTextCtrl):
"""PyCrust FillingText based on wxStyledTextCtrl.""" """PyCrust FillingText based on wxStyledTextCtrl."""
name = 'PyCrust Filling Text' name = 'PyCrust Filling Text'
revision = __version__ revision = __revision__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \ def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxCLIP_CHILDREN): size=wxDefaultSize, style=wxCLIP_CHILDREN):
@@ -265,7 +265,7 @@ class Filling(wxSplitterWindow):
"""PyCrust Filling based on wxSplitterWindow.""" """PyCrust Filling based on wxSplitterWindow."""
name = 'PyCrust Filling' name = 'PyCrust Filling'
revision = __version__ revision = __revision__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \ def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxSP_3D, name='Filling Window', \ size=wxDefaultSize, style=wxSP_3D, name='Filling Window', \
@@ -288,7 +288,7 @@ class FillingFrame(wxFrame):
"""Frame containing the PyCrust filling, or namespace tree component.""" """Frame containing the PyCrust filling, or namespace tree component."""
name = 'PyCrust Filling Frame' name = 'PyCrust Filling Frame'
revision = __version__ revision = __revision__
def __init__(self, parent=None, id=-1, title='PyFilling', \ def __init__(self, parent=None, id=-1, title='PyFilling', \
pos=wxDefaultPosition, size=wxDefaultSize, \ pos=wxDefaultPosition, size=wxDefaultSize, \

View File

@@ -2,7 +2,7 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
import os import os
import sys import sys
@@ -13,7 +13,7 @@ import introspect
class Interpreter(InteractiveInterpreter): class Interpreter(InteractiveInterpreter):
"""PyCrust Interpreter based on code.InteractiveInterpreter.""" """PyCrust Interpreter based on code.InteractiveInterpreter."""
revision = __version__ revision = __revision__
def __init__(self, locals=None, rawin=None, \ def __init__(self, locals=None, rawin=None, \
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr): stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr):

View File

@@ -3,7 +3,7 @@ like call tips and command auto completion."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
import inspect import inspect
import string import string
@@ -14,117 +14,128 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1, \
"""Return list of auto-completion options for command. """Return list of auto-completion options for command.
The list of options will be based on the locals namespace.""" The list of options will be based on the locals namespace."""
attributes = []
# Get the proper chunk of code from the command. # Get the proper chunk of code from the command.
root = getRoot(command, terminator='.') root = getRoot(command, terminator='.')
try: try:
if locals is not None:
object = eval(root, locals) object = eval(root, locals)
else:
object = eval(root)
except:
pass
else:
attributes = getAttributeNames(object, includeMagic, \ attributes = getAttributeNames(object, includeMagic, \
includeSingle, includeDouble) includeSingle, includeDouble)
return attributes return attributes
except:
return []
def getAttributeNames(object, includeMagic=1, includeSingle=1, includeDouble=1): def getAttributeNames(object, includeMagic=1, includeSingle=1, includeDouble=1):
"""Return list of unique attributes, including inherited, for an object.""" """Return list of unique attributes, including inherited, for an object."""
attributes = [] attributes = []
dict = {} 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: if includeMagic:
try: attributes += object._getAttributeNames() try: attributes += object._getAttributeNames()
except: pass except: pass
# Get all attribute names, removing duplicates from the attribute list. # Get all attribute names.
for item in getAllAttributeNames(object): attrdict = getAllAttributeNames(object)
for attrlist in attrdict.values():
attributes += attrlist
# Remove duplicates from the attribute list.
for item in attributes:
dict[item] = None dict[item] = None
attributes += dict.keys() attributes = dict.keys()
attributes.sort(lambda x, y: cmp(x.upper(), y.upper())) attributes.sort(lambda x, y: cmp(x.upper(), y.upper()))
if not includeSingle: 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: if not includeDouble:
attributes = filter(lambda item: item[:2]!='__', attributes) attributes = filter(lambda item: item[:2]!='__', attributes)
# Make sure we haven't picked up any bogus attributes somehow. # 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 return attributes
def hasattrAlwaysReturnsTrue(object):
return hasattr(object, 'bogu5_123_aTTri8ute')
def getAllAttributeNames(object): 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. 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, # !!! Do Not use hasattr() as a test anywhere in this function,
# !!! because it is unreliable with remote objects - xmlrpc, soap, etc. # !!! 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. # Wake up sleepy objects - a hack for ZODB objects in "ghost" state.
wakeupcall = dir(object) wakeupcall = dir(object)
del wakeupcall del wakeupcall
# Get attributes available through the normal convention. # 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: try:
keys = object.__dict__.keys() attributes = object.__dict__.keys()
except: attributes.sort()
except: # Must catch all because object might have __getattr__.
pass pass
else: else:
attributes += keys attrdict[(key, '__dict__', len(attributes))] = attributes
# For a class instance, get the attributes for the class. # For a class instance, get the attributes for the class.
if hasattr(object, '__class__'): try:
# Break a circular reference. This happens with extension classes. klass = object.__class__
if object.__class__ is object: except: # Must catch all because object might have __getattr__.
pass pass
else: else:
attributes += getAllAttributeNames(object.__class__) if klass is object:
# Break a circular reference. This happens with extension classes.
pass
else:
attrdict.update(getAllAttributeNames(klass))
# Also get attributes from any and all parent classes. # Also get attributes from any and all parent classes.
try: try:
bases = object.__bases__ bases = object.__bases__
except: except: # Must catch all because object might have __getattr__.
pass pass
else: else:
if isinstance(bases, type(())): if isinstance(bases, types.TupleType):
for base in bases: for base in bases:
if type(base) is types.TypeType: if type(base) is types.TypeType:
# Break a circular reference. Happens in Python 2.2. # Break a circular reference. Happens in Python 2.2.
pass pass
else: else:
attributes += getAllAttributeNames(base) attrdict.update(getAllAttributeNames(base))
return attributes return attrdict
def getCallTip(command='', locals=None): 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.""" The call tip information will be based on the locals namespace."""
calltip = ('', '', '') # object name, argspec, tip text.
calltip = ('', '', '')
# Get the proper chunk of code from the command. # Get the proper chunk of code from the command.
root = getRoot(command, terminator='(') root = getRoot(command, terminator='(')
try: try:
if locals is not None:
object = eval(root, locals) object = eval(root, locals)
else:
object = eval(root)
except: except:
return calltip return calltip
name = '' name = ''
dropSelf = 1 object, dropSelf = getBaseObject(object)
# 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: try:
object = object.__call__.im_func
except:
dropSelf = 0
else:
dropSelf = 0
if hasattr(object, '__name__'):
name = object.__name__ name = object.__name__
except AttributeError:
pass
tip1 = '' tip1 = ''
argspec = '' argspec = ''
if inspect.isbuiltin(object): if inspect.isbuiltin(object):
@@ -134,8 +145,8 @@ def getCallTip(command='', locals=None):
# tip1 is a string like: "getCallTip(command='', locals=None)" # tip1 is a string like: "getCallTip(command='', locals=None)"
argspec = apply(inspect.formatargspec, inspect.getargspec(object)) argspec = apply(inspect.formatargspec, inspect.getargspec(object))
if dropSelf: if dropSelf:
# The first parameter to a method is a reference to the # The first parameter to a method is a reference to an
# instance, usually coded as "self", and is passed # instance, usually coded as "self", and is usually passed
# automatically by Python and therefore we want to drop it. # automatically by Python and therefore we want to drop it.
temp = argspec.split(',') temp = argspec.split(',')
if len(temp) == 1: # No other arguments. if len(temp) == 1: # No other arguments.
@@ -158,6 +169,89 @@ def getCallTip(command='', locals=None):
calltip = (name, argspec[1:-1], tip.strip()) calltip = (name, argspec[1:-1], tip.strip())
return calltip 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): def getConstructor(object):
"""Return constructor for class object, or None if there isn't one.""" """Return constructor for class object, or None if there isn't one."""
try: try:
@@ -169,40 +263,5 @@ def getConstructor(object):
return constructor return constructor
return None 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

View File

@@ -2,7 +2,7 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
class PseudoKeyword: class PseudoKeyword:
"""A callable class that calls a method passed as a parameter. """A callable class that calls a method passed as a parameter.
@@ -27,8 +27,10 @@ class PseudoKeyword:
def __init__(self, method): def __init__(self, method):
"""Create a callable object that executes method when called.""" """Create a callable object that executes method when called."""
# XXX Should probably check that this is a callable object. if callable(method):
self.method = method self.method = method
else:
raise ValueError, 'method must be callable'
def __call__(self, *args, **kwds): def __call__(self, *args, **kwds):
self.method(*args, **kwds) self.method(*args, **kwds)
@@ -63,7 +65,10 @@ class PseudoFile:
class PseudoFileIn(PseudoFile): class PseudoFileIn(PseudoFile):
def __init__(self, readline): def __init__(self, readline):
if callable(readline):
self.readline = readline self.readline = readline
else:
raise ValueError, 'readline must be callable'
def isatty(self): def isatty(self):
return 1 return 1
@@ -72,7 +77,10 @@ class PseudoFileIn(PseudoFile):
class PseudoFileOut(PseudoFile): class PseudoFileOut(PseudoFile):
def __init__(self, write): def __init__(self, write):
if callable(write):
self.write = write self.write = write
else:
raise ValueError, 'write must be callable'
def isatty(self): def isatty(self):
return 1 return 1
@@ -81,7 +89,10 @@ class PseudoFileOut(PseudoFile):
class PseudoFileErr(PseudoFile): class PseudoFileErr(PseudoFile):
def __init__(self, write): def __init__(self, write):
if callable(write):
self.write = write self.write = write
else:
raise ValueError, 'write must be callable'
def isatty(self): def isatty(self):
return 1 return 1

View File

@@ -6,7 +6,7 @@ Sponsored by Orbtech - Your Source For Python Development Services"""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
from wxPython.wx import * from wxPython.wx import *
from wxPython.stc import * from wxPython.stc import *
@@ -52,7 +52,7 @@ class ShellFacade:
still accessible, even though only some are visible to the user.""" still accessible, even though only some are visible to the user."""
name = 'PyCrust Shell Interface' name = 'PyCrust Shell Interface'
revision = __version__ revision = __revision__
def __init__(self, other): def __init__(self, other):
"""Create a ShellFacade instance.""" """Create a ShellFacade instance."""
@@ -128,7 +128,7 @@ class Shell(wxStyledTextCtrl):
"""PyCrust Shell based on wxStyledTextCtrl.""" """PyCrust Shell based on wxStyledTextCtrl."""
name = 'PyCrust Shell' name = 'PyCrust Shell'
revision = __version__ revision = __revision__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \ def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxCLIP_CHILDREN, introText='', \ size=wxDefaultSize, style=wxCLIP_CHILDREN, introText='', \
@@ -231,18 +231,9 @@ class Shell(wxStyledTextCtrl):
def setBuiltinKeywords(self): def setBuiltinKeywords(self):
"""Create pseudo keywords as part of builtins. """Create pseudo keywords as part of builtins.
This is a rather clever hack that sets "close", "exit" and "quit" This simply sets "close", "exit" and "quit" to a helpful string.
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.
""" """
## 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__ import __builtin__
from pseudo import PseudoKeyword
__builtin__.close = __builtin__.exit = __builtin__.quit = \ __builtin__.close = __builtin__.exit = __builtin__.quit = \
'Click on the close button to leave the application.' 'Click on the close button to leave the application.'
@@ -322,6 +313,7 @@ class Shell(wxStyledTextCtrl):
if self.AutoCompActive(): self.AutoCompCancel() if self.AutoCompActive(): self.AutoCompCancel()
# Get the command between the prompt and the cursor. # Get the command between the prompt and the cursor.
# Add the '(' to the end of the command. # Add the '(' to the end of the command.
self.ReplaceSelection('')
command = self.GetTextRange(stoppos, currpos) + '(' command = self.GetTextRange(stoppos, currpos) + '('
self.write('(') self.write('(')
if self.autoCallTip: self.autoCallTipShow(command) if self.autoCallTip: self.autoCallTipShow(command)
@@ -939,21 +931,17 @@ class ShellMenu:
m = self.autocompMenu = wxMenu() m = self.autocompMenu = wxMenu()
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion', \ m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion', \
'Show auto completion during dot syntax', \ 'Show auto completion during dot syntax', 1)
kind=wxITEM_CHECK)
m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes', \ m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes', \
'Include attributes visible to __getattr__ and __setattr__', \ 'Include attributes visible to __getattr__ and __setattr__', 1)
kind=wxITEM_CHECK)
m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores', \ m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores', \
'Include attibutes prefixed by a single underscore', \ 'Include attibutes prefixed by a single underscore', 1)
kind=wxITEM_CHECK)
m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores', \ m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores', \
'Include attibutes prefixed by a double underscore', \ 'Include attibutes prefixed by a double underscore', 1)
kind=wxITEM_CHECK)
m = self.calltipsMenu = wxMenu() m = self.calltipsMenu = wxMenu()
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips', \ 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 = self.optionsMenu = wxMenu()
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu, \ m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu, \
@@ -1091,7 +1079,7 @@ class ShellFrame(wxFrame, ShellMenu):
"""Frame containing the PyCrust shell component.""" """Frame containing the PyCrust shell component."""
name = 'PyCrust Shell Frame' name = 'PyCrust Shell Frame'
revision = __version__ revision = __revision__
def __init__(self, parent=None, id=-1, title='PyShell', \ def __init__(self, parent=None, id=-1, title='PyShell', \
pos=wxDefaultPosition, size=wxDefaultSize, \ pos=wxDefaultPosition, size=wxDefaultSize, \
@@ -1100,7 +1088,7 @@ class ShellFrame(wxFrame, ShellMenu):
"""Create a PyCrust ShellFrame instance.""" """Create a PyCrust ShellFrame instance."""
wxFrame.__init__(self, parent, id, title, pos, size, style) wxFrame.__init__(self, parent, id, title, pos, size, style)
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION 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.CreateStatusBar()
self.SetStatusText(intro.replace('\n', ', ')) self.SetStatusText(intro.replace('\n', ', '))
if wxPlatform == '__WXMSW__': if wxPlatform == '__WXMSW__':

View File

@@ -4,7 +4,7 @@ interpreter, each have a revision property based on the CVS Revision."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$" __cvsid__ = "$Id$"
__version__ = "$Revision$"[11:-2] __revision__ = "$Revision$"[11:-2]
VERSION = '0.7.1' VERSION = '0.7.2'