Patrick O'Brien's PyCrust package has been renamed to Py and now
includes several new tools. As part of the change the location of the pacakge has changed as well, it is now accessible as "from wxPython import py" (or "from wx import py" using the new namespace.) There are still some transition moudules in the wxPython.lib.PyCrust mackage that will issue a warning and then import what is needed from the new package. These will be removed in a future release. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@20104 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -2,7 +2,7 @@ CHANGES.txt for wxPython
|
|||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
2.4.0.8
|
2.4.1
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Added wxScrolledPanel from Wil Sadkin
|
Added wxScrolledPanel from Wil Sadkin
|
||||||
@@ -24,6 +24,16 @@ people can do imports without "import *" and can use names like
|
|||||||
wx.Frame instead of wx.wxFrame. This is phase 1 of a full transition
|
wx.Frame instead of wx.wxFrame. This is phase 1 of a full transition
|
||||||
to the new namespace.
|
to the new namespace.
|
||||||
|
|
||||||
|
Updated Scintilla to 1.51.
|
||||||
|
|
||||||
|
Patrick O'Brien's PyCrust package has been renamed to Py and now
|
||||||
|
includes several new tools. As part of the change the location of the
|
||||||
|
pacakge has changed as well, it is now accessible as "from wxPython
|
||||||
|
import py" (or "from wx import py" using the new namespace.) There
|
||||||
|
are still some transition moudules in the wxPython.lib.PyCrust mackage
|
||||||
|
that will issue a warning and then import what is needed from the new
|
||||||
|
package. These will be removed in a future release.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -16,13 +16,15 @@ python = sys.executable
|
|||||||
pythonw = 'start ' + os.path.join(os.path.split(python)[0], 'pythonw.exe')
|
pythonw = 'start ' + os.path.join(os.path.split(python)[0], 'pythonw.exe')
|
||||||
scriptdir = os.getcwd()
|
scriptdir = os.getcwd()
|
||||||
|
|
||||||
scripts = [ ("img2png", 0),
|
scripts = [ ("img2png", 0),
|
||||||
("img2py", 0),
|
("img2py", 0),
|
||||||
("img2xpm", 0),
|
("img2xpm", 0),
|
||||||
("xrced", 1),
|
("xrced", 1),
|
||||||
("pyshell", 1),
|
("pyshell", 1),
|
||||||
("pycrust", 1),
|
("pycrust", 1),
|
||||||
("pycwrap", 1),
|
("pywrap", 1),
|
||||||
|
("pyalamode", 1),
|
||||||
|
("pyalacarte", 1),
|
||||||
("helpviewer", 1),
|
("helpviewer", 1),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
4
wxPython/scripts/pyalacarte
Executable file
4
wxPython/scripts/pyalacarte
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from wx.py.PyAlaCarte import main
|
||||||
|
main()
|
4
wxPython/scripts/pyalamode
Executable file
4
wxPython/scripts/pyalamode
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from wx.py.PyAlaMode import main
|
||||||
|
main()
|
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from wxPython.lib.PyCrust.PyCrustApp import main
|
from wx.py.PyCrust import main
|
||||||
main()
|
main()
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
start e:\tools\Python22\pythonw.exe e:\PROJECTS\wx\wxPython\scripts\pycwrap %1 %2 %3 %4 %5 %6 %7 %8 %9
|
|
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from wxPython.lib.PyCrust.PyShellApp import main
|
from wx.py.PyShell import main
|
||||||
main()
|
main()
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from wxPython.lib.PyCrust.wrap import main
|
from wx.py.PyWrap import main
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
sys.path.insert(0, os.curdir)
|
sys.path.insert(0, os.curdir)
|
3
wxPython/wx/py/PyAlaCarte.py
Normal file
3
wxPython/wx/py/PyAlaCarte.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Py is really located in the old namespace, but it doesn't need any
|
||||||
|
# renaming done.
|
||||||
|
from wxPython.py.PyAlaCarte import *
|
3
wxPython/wx/py/PyAlaMode.py
Normal file
3
wxPython/wx/py/PyAlaMode.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Py is really located in the old namespace, but it doesn't need any
|
||||||
|
# renaming done.
|
||||||
|
from wxPython.py.PyAlaMode import *
|
3
wxPython/wx/py/PyCrust.py
Normal file
3
wxPython/wx/py/PyCrust.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Py is really located in the old namespace, but it doesn't need any
|
||||||
|
# renaming done.
|
||||||
|
from wxPython.py.PyCrust import *
|
3
wxPython/wx/py/PyFilling.py
Normal file
3
wxPython/wx/py/PyFilling.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Py is really located in the old namespace, but it doesn't need any
|
||||||
|
# renaming done.
|
||||||
|
from wxPython.py.PyFilling import *
|
3
wxPython/wx/py/PyShell.py
Normal file
3
wxPython/wx/py/PyShell.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Py is really located in the old namespace, but it doesn't need any
|
||||||
|
# renaming done.
|
||||||
|
from wxPython.py.PyShell import *
|
3
wxPython/wx/py/PyWrap.py
Normal file
3
wxPython/wx/py/PyWrap.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Py is really located in the old namespace, but it doesn't need any
|
||||||
|
# renaming done.
|
||||||
|
from wxPython.py.PyWrap import *
|
3
wxPython/wx/py/__init__.py
Normal file
3
wxPython/wx/py/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Py is really located in the old namespace, but it doesn't need any
|
||||||
|
# renaming done.
|
||||||
|
from wxPython.py import *
|
@@ -1,3 +0,0 @@
|
|||||||
*.pyc
|
|
||||||
*.BAK
|
|
||||||
*.$$$
|
|
@@ -1,70 +1,6 @@
|
|||||||
|
|
||||||
"""PyCrustApp is a python shell and namespace browser application."""
|
from wxPython.py.PyCrust import *
|
||||||
|
|
||||||
# The next two lines, and the other code below that makes use of
|
|
||||||
# ``__main__`` and ``original``, serve the purpose of cleaning up the
|
|
||||||
# main namespace to look as much as possible like the regular Python
|
|
||||||
# shell environment.
|
|
||||||
import __main__
|
|
||||||
original = __main__.__dict__.keys()
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
from wxPython import wx
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
|
|
||||||
class App(wx.wxApp):
|
|
||||||
"""PyCrust standalone application."""
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
from wxPython import wx
|
|
||||||
wx.wxInitAllImageHandlers()
|
|
||||||
locals = __main__.__dict__
|
|
||||||
from crust import CrustFrame
|
|
||||||
self.frame = CrustFrame(locals=locals)
|
|
||||||
self.frame.SetSize((800, 600))
|
|
||||||
self.frame.Show()
|
|
||||||
self.SetTopWindow(self.frame)
|
|
||||||
# Add the application object to the sys module's namespace.
|
|
||||||
# This allows a shell user to do:
|
|
||||||
# >>> import sys
|
|
||||||
# >>> sys.app.whatever
|
|
||||||
import sys
|
|
||||||
sys.app = self
|
|
||||||
return 1
|
|
||||||
|
|
||||||
'''
|
|
||||||
The main() function needs to handle being imported, such as with the
|
|
||||||
pycrust script that wxPython installs:
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from wxPython.lib.PyCrust.PyCrustApp import main
|
|
||||||
main()
|
|
||||||
'''
|
|
||||||
|
|
||||||
def main():
|
|
||||||
import __main__
|
|
||||||
md = __main__.__dict__
|
|
||||||
keepers = original
|
|
||||||
keepers.append('App')
|
|
||||||
for key in md.keys():
|
|
||||||
if key not in keepers:
|
|
||||||
del md[key]
|
|
||||||
app = App(0)
|
|
||||||
if md.has_key('App') and md['App'] is App:
|
|
||||||
del md['App']
|
|
||||||
if md.has_key('__main__') and md['__main__'] is __main__:
|
|
||||||
del md['__main__']
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
@@ -1,44 +1,5 @@
|
|||||||
|
|
||||||
"""PyFillingApp is a python namespace inspection application."""
|
from wxPython.py.PyFilling import *
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
# We use this object to get more introspection when run standalone.
|
|
||||||
app = None
|
|
||||||
|
|
||||||
import filling
|
|
||||||
|
|
||||||
# These are imported just to have something interesting to inspect.
|
|
||||||
import crust
|
|
||||||
import interpreter
|
|
||||||
import introspect
|
|
||||||
import pseudo
|
|
||||||
import shell
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from wxPython import wx
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
|
|
||||||
class App(filling.App):
|
|
||||||
def OnInit(self):
|
|
||||||
filling.App.OnInit(self)
|
|
||||||
self.root = self.fillingFrame.filling.tree.root
|
|
||||||
return True
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Create and run the application."""
|
|
||||||
global app
|
|
||||||
app = App(0)
|
|
||||||
app.fillingFrame.filling.tree.Expand(app.root)
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@@ -1,71 +1,6 @@
|
|||||||
|
|
||||||
"""PyShellApp is a python shell application."""
|
from wxPython.py.PyShell import *
|
||||||
|
|
||||||
# The next two lines, and the other code below that makes use of
|
|
||||||
# ``__main__`` and ``original``, serve the purpose of cleaning up the
|
|
||||||
# main namespace to look as much as possible like the regular Python
|
|
||||||
# shell environment.
|
|
||||||
import __main__
|
|
||||||
original = __main__.__dict__.keys()
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
from wxPython import wx
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
|
|
||||||
class App(wx.wxApp):
|
|
||||||
"""PyShell standalone application."""
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
from wxPython import wx
|
|
||||||
wx.wxInitAllImageHandlers()
|
|
||||||
locals = __main__.__dict__
|
|
||||||
from shell import ShellFrame
|
|
||||||
self.frame = ShellFrame(locals=locals)
|
|
||||||
self.frame.SetSize((750, 525))
|
|
||||||
self.frame.Show()
|
|
||||||
self.SetTopWindow(self.frame)
|
|
||||||
self.frame.shell.SetFocus()
|
|
||||||
# Add the application object to the sys module's namespace.
|
|
||||||
# This allows a shell user to do:
|
|
||||||
# >>> import sys
|
|
||||||
# >>> sys.app.whatever
|
|
||||||
import sys
|
|
||||||
sys.app = self
|
|
||||||
return 1
|
|
||||||
|
|
||||||
'''
|
|
||||||
The main() function needs to handle being imported, such as with the
|
|
||||||
pycrust script that wxPython installs:
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from wxPython.lib.PyCrust.PyCrustApp import main
|
|
||||||
main()
|
|
||||||
'''
|
|
||||||
|
|
||||||
def main():
|
|
||||||
import __main__
|
|
||||||
md = __main__.__dict__
|
|
||||||
keepers = original
|
|
||||||
keepers.append('App')
|
|
||||||
for key in md.keys():
|
|
||||||
if key not in keepers:
|
|
||||||
del md[key]
|
|
||||||
app = App(0)
|
|
||||||
if md.has_key('App') and md['App'] is App:
|
|
||||||
del md['App']
|
|
||||||
if md.has_key('__main__') and md['__main__'] is __main__:
|
|
||||||
del md['__main__']
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
@@ -1 +1,5 @@
|
|||||||
# Orbtech python package.
|
|
||||||
|
# Change this to an ImportError after the next release
|
||||||
|
import warnings
|
||||||
|
warnings.warn("PyCrust has been renamed to Py. Use 'from wx import py'", stacklevel=2)
|
||||||
|
|
||||||
|
@@ -1,169 +1,2 @@
|
|||||||
"""PyCrust Crust combines the shell and filling into one control."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
from wxPython import wx
|
|
||||||
from filling import Filling
|
|
||||||
import os
|
|
||||||
from shell import Shell
|
|
||||||
from shellmenu import ShellMenu
|
|
||||||
from version import VERSION
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
|
|
||||||
class Crust(wx.wxSplitterWindow):
|
|
||||||
"""PyCrust Crust based on wxSplitterWindow."""
|
|
||||||
|
|
||||||
name = 'PyCrust Crust'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
|
||||||
size=wx.wxDefaultSize, style=wx.wxSP_3D,
|
|
||||||
name='Crust Window', rootObject=None, rootLabel=None,
|
|
||||||
rootIsNamespace=True, intro='', locals=None,
|
|
||||||
InterpClass=None, *args, **kwds):
|
|
||||||
"""Create a PyCrust Crust instance."""
|
|
||||||
wx.wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
|
||||||
self.shell = Shell(parent=self, introText=intro,
|
|
||||||
locals=locals, InterpClass=InterpClass,
|
|
||||||
*args, **kwds)
|
|
||||||
if rootObject is None:
|
|
||||||
rootObject = self.shell.interp.locals
|
|
||||||
self.notebook = wx.wxNotebook(parent=self, id=-1)
|
|
||||||
self.shell.interp.locals['notebook'] = self.notebook
|
|
||||||
self.filling = Filling(parent=self.notebook,
|
|
||||||
rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace)
|
|
||||||
# Add 'filling' to the interpreter's locals.
|
|
||||||
self.shell.interp.locals['filling'] = self.filling
|
|
||||||
self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
|
|
||||||
self.calltip = Calltip(parent=self.notebook)
|
|
||||||
self.notebook.AddPage(page=self.calltip, text='Calltip')
|
|
||||||
self.sessionlisting = SessionListing(parent=self.notebook)
|
|
||||||
self.notebook.AddPage(page=self.sessionlisting, text='Session')
|
|
||||||
self.dispatcherlisting = DispatcherListing(parent=self.notebook)
|
|
||||||
self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
|
|
||||||
from wxd import wx_
|
|
||||||
self.wxdocs = Filling(parent=self.notebook,
|
|
||||||
rootObject=wx_,
|
|
||||||
rootLabel='wx',
|
|
||||||
rootIsNamespace=False,
|
|
||||||
static=True)
|
|
||||||
self.notebook.AddPage(page=self.wxdocs, text='wxPython Docs')
|
|
||||||
from wxd import stc_
|
|
||||||
self.stcdocs = Filling(parent=self.notebook,
|
|
||||||
rootObject=stc_.StyledTextCtrl,
|
|
||||||
rootLabel='StyledTextCtrl',
|
|
||||||
rootIsNamespace=False,
|
|
||||||
static=True)
|
|
||||||
self.notebook.AddPage(page=self.stcdocs, text='StyledTextCtrl Docs')
|
|
||||||
self.SplitHorizontally(self.shell, self.notebook, 300)
|
|
||||||
self.SetMinimumPaneSize(1)
|
|
||||||
|
|
||||||
|
|
||||||
class Calltip(wx.wxTextCtrl):
|
|
||||||
"""Text control containing the most recent shell calltip."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1):
|
|
||||||
import dispatcher
|
|
||||||
style = wx.wxTE_MULTILINE | wx.wxTE_READONLY | wx.wxTE_RICH2
|
|
||||||
wx.wxTextCtrl.__init__(self, parent=parent, id=id, style=style)
|
|
||||||
self.SetBackgroundColour(wx.wxColour(255, 255, 232))
|
|
||||||
dispatcher.connect(receiver=self.display, signal='Shell.calltip')
|
|
||||||
|
|
||||||
def display(self, calltip):
|
|
||||||
"""Receiver for Shell.calltip signal."""
|
|
||||||
self.SetValue(calltip)
|
|
||||||
|
|
||||||
|
|
||||||
class SessionListing(wx.wxTextCtrl):
|
|
||||||
"""Text control containing all commands for session."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1):
|
|
||||||
import dispatcher
|
|
||||||
style = wx.wxTE_MULTILINE | wx.wxTE_READONLY | \
|
|
||||||
wx.wxTE_RICH2 | wx.wxTE_DONTWRAP
|
|
||||||
wx.wxTextCtrl.__init__(self, parent=parent, id=id, style=style)
|
|
||||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
|
||||||
|
|
||||||
def push(self, command, more):
|
|
||||||
"""Receiver for Interpreter.push signal."""
|
|
||||||
if command and not more:
|
|
||||||
self.SetInsertionPointEnd()
|
|
||||||
start, end = self.GetSelection()
|
|
||||||
if start != end:
|
|
||||||
self.SetSelection(0, 0)
|
|
||||||
self.AppendText(command + '\n')
|
|
||||||
|
|
||||||
|
|
||||||
class DispatcherListing(wx.wxTextCtrl):
|
|
||||||
"""Text control containing all dispatches for session."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1):
|
|
||||||
import dispatcher
|
|
||||||
style = wx.wxTE_MULTILINE | wx.wxTE_READONLY | \
|
|
||||||
wx.wxTE_RICH2 | wx.wxTE_DONTWRAP
|
|
||||||
wx.wxTextCtrl.__init__(self, parent=parent, id=id, style=style)
|
|
||||||
dispatcher.connect(receiver=self.spy)
|
|
||||||
|
|
||||||
def spy(self, signal, sender):
|
|
||||||
"""Receiver for Any signal from Any sender."""
|
|
||||||
text = '%r from %s' % (signal, sender)
|
|
||||||
self.SetInsertionPointEnd()
|
|
||||||
start, end = self.GetSelection()
|
|
||||||
if start != end:
|
|
||||||
self.SetSelection(0, 0)
|
|
||||||
self.AppendText(text + '\n')
|
|
||||||
|
|
||||||
|
|
||||||
class CrustFrame(wx.wxFrame, ShellMenu):
|
|
||||||
"""Frame containing all the PyCrust components."""
|
|
||||||
|
|
||||||
name = 'PyCrust Frame'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyCrust',
|
|
||||||
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize,
|
|
||||||
style=wx.wxDEFAULT_FRAME_STYLE,
|
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=True,
|
|
||||||
locals=None, InterpClass=None, *args, **kwds):
|
|
||||||
"""Create a PyCrust CrustFrame instance."""
|
|
||||||
wx.wxFrame.__init__(self, parent, id, title, pos, size, style)
|
|
||||||
intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION
|
|
||||||
intro += '\nSponsored by Orbtech - '
|
|
||||||
intro += 'Your source for Python programming expertise.'
|
|
||||||
self.CreateStatusBar()
|
|
||||||
self.SetStatusText(intro.replace('\n', ', '))
|
|
||||||
import images
|
|
||||||
self.SetIcon(images.getPyCrustIcon())
|
|
||||||
self.crust = Crust(parent=self, intro=intro,
|
|
||||||
rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace,
|
|
||||||
locals=locals,
|
|
||||||
InterpClass=InterpClass, *args, **kwds)
|
|
||||||
# Override the filling so that status messages go to the status bar.
|
|
||||||
self.crust.filling.tree.setStatusText = self.SetStatusText
|
|
||||||
# Override the shell so that status messages go to the status bar.
|
|
||||||
self.crust.shell.setStatusText = self.SetStatusText
|
|
||||||
# Fix a problem with the sash shrinking to nothing.
|
|
||||||
self.crust.filling.SetSashPosition(200)
|
|
||||||
self.shell = self.crust.shell
|
|
||||||
self.createMenus()
|
|
||||||
wx.EVT_CLOSE(self, self.OnCloseWindow)
|
|
||||||
# Set focus to the shell editor.
|
|
||||||
self.crust.shell.SetFocus()
|
|
||||||
|
|
||||||
def OnCloseWindow(self, event):
|
|
||||||
self.crust.shell.destroy()
|
|
||||||
self.Destroy()
|
|
||||||
|
|
||||||
|
|
||||||
|
from wxPython.py.crust import *
|
||||||
|
@@ -1,436 +1,3 @@
|
|||||||
"""PyCrust Filling is the gui tree control through which a user can
|
|
||||||
navigate the local namespace or any object."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
from wxPython.py.filling import *
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
from wxPython import wx
|
|
||||||
from wxPython import stc
|
|
||||||
from version import VERSION
|
|
||||||
import dispatcher
|
|
||||||
import inspect
|
|
||||||
import introspect
|
|
||||||
import keyword
|
|
||||||
import sys
|
|
||||||
import types
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
COMMONTYPES = [getattr(types, t) for t in dir(types) \
|
|
||||||
if not t.startswith('_') \
|
|
||||||
and t not in ('ClassType', 'InstanceType', 'ModuleType')]
|
|
||||||
|
|
||||||
DOCTYPES = ('BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
|
|
||||||
'FunctionType', 'GeneratorType', 'InstanceType',
|
|
||||||
'LambdaType', 'MethodType', 'ModuleType',
|
|
||||||
'UnboundMethodType', 'method-wrapper')
|
|
||||||
|
|
||||||
SIMPLETYPES = [getattr(types, t) for t in dir(types) \
|
|
||||||
if not t.startswith('_') and t not in DOCTYPES]
|
|
||||||
|
|
||||||
try:
|
|
||||||
COMMONTYPES.append(type(''.__repr__)) # Method-wrapper in version 2.2.x.
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FillingTree(wx.wxTreeCtrl):
|
|
||||||
"""PyCrust FillingTree based on wxTreeCtrl."""
|
|
||||||
|
|
||||||
name = 'PyCrust Filling Tree'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
|
||||||
size=wx.wxDefaultSize, style=wx.wxTR_DEFAULT_STYLE,
|
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=0,
|
|
||||||
static=False):
|
|
||||||
"""Create a PyCrust FillingTree instance."""
|
|
||||||
wx.wxTreeCtrl.__init__(self, parent, id, pos, size, style)
|
|
||||||
self.rootIsNamespace = rootIsNamespace
|
|
||||||
import __main__
|
|
||||||
if rootObject is None:
|
|
||||||
rootObject = __main__.__dict__
|
|
||||||
self.rootIsNamespace = 1
|
|
||||||
if rootObject is __main__.__dict__ and rootLabel is None:
|
|
||||||
rootLabel = 'locals()'
|
|
||||||
if not rootLabel:
|
|
||||||
rootLabel = 'Ingredients'
|
|
||||||
rootData = wx.wxTreeItemData(rootObject)
|
|
||||||
self.item = self.root = self.AddRoot(rootLabel, -1, -1, rootData)
|
|
||||||
self.SetItemHasChildren(self.root, self.hasChildren(rootObject))
|
|
||||||
wx.EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
|
|
||||||
wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
|
|
||||||
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
|
||||||
wx.EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
|
|
||||||
if not static:
|
|
||||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
|
||||||
|
|
||||||
def push(self, command, more):
|
|
||||||
"""Receiver for Interpreter.push signal."""
|
|
||||||
self.display()
|
|
||||||
|
|
||||||
def OnItemExpanding(self, event):
|
|
||||||
"""Add children to the item."""
|
|
||||||
busy = wx.wxBusyCursor()
|
|
||||||
item = event.GetItem()
|
|
||||||
if self.IsExpanded(item):
|
|
||||||
return
|
|
||||||
self.addChildren(item)
|
|
||||||
# self.SelectItem(item)
|
|
||||||
|
|
||||||
def OnItemCollapsed(self, event):
|
|
||||||
"""Remove all children from the item."""
|
|
||||||
busy = wx.wxBusyCursor()
|
|
||||||
item = event.GetItem()
|
|
||||||
# self.CollapseAndReset(item)
|
|
||||||
# self.DeleteChildren(item)
|
|
||||||
# self.SelectItem(item)
|
|
||||||
|
|
||||||
def OnSelChanged(self, event):
|
|
||||||
"""Display information about the item."""
|
|
||||||
busy = wx.wxBusyCursor()
|
|
||||||
self.item = event.GetItem()
|
|
||||||
self.display()
|
|
||||||
|
|
||||||
def OnItemActivated(self, event):
|
|
||||||
"""Launch a DirFrame."""
|
|
||||||
item = event.GetItem()
|
|
||||||
text = self.getFullName(item)
|
|
||||||
obj = self.GetPyData(item)
|
|
||||||
frame = FillingFrame(parent=self, size=(600, 100), rootObject=obj,
|
|
||||||
rootLabel=text, rootIsNamespace=False)
|
|
||||||
frame.Show()
|
|
||||||
|
|
||||||
def hasChildren(self, obj):
|
|
||||||
"""Return true if object has children."""
|
|
||||||
if self.getChildren(obj):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def getChildren(self, obj):
|
|
||||||
"""Return dictionary with attributes or contents of object."""
|
|
||||||
busy = wx.wxBusyCursor()
|
|
||||||
otype = type(obj)
|
|
||||||
if otype is types.DictType \
|
|
||||||
or str(otype)[17:23] == 'BTrees' and hasattr(obj, 'keys'):
|
|
||||||
return obj
|
|
||||||
d = {}
|
|
||||||
if otype is types.ListType or otype is types.TupleType:
|
|
||||||
for n in range(len(obj)):
|
|
||||||
key = '[' + str(n) + ']'
|
|
||||||
d[key] = obj[n]
|
|
||||||
if otype not in COMMONTYPES:
|
|
||||||
for key in introspect.getAttributeNames(obj):
|
|
||||||
# Believe it or not, some attributes can disappear,
|
|
||||||
# such as the exc_traceback attribute of the sys
|
|
||||||
# module. So this is nested in a try block.
|
|
||||||
try:
|
|
||||||
d[key] = getattr(obj, key)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return d
|
|
||||||
|
|
||||||
def addChildren(self, item):
|
|
||||||
self.DeleteChildren(item)
|
|
||||||
obj = self.GetPyData(item)
|
|
||||||
children = self.getChildren(obj)
|
|
||||||
if not children:
|
|
||||||
return
|
|
||||||
keys = children.keys()
|
|
||||||
keys.sort(lambda x, y: cmp(x.lower(), y.lower()))
|
|
||||||
for key in keys:
|
|
||||||
itemtext = str(key)
|
|
||||||
# Show string dictionary items with single quotes, except
|
|
||||||
# for the first level of items, if they represent a
|
|
||||||
# namespace.
|
|
||||||
if type(obj) is types.DictType \
|
|
||||||
and type(key) is types.StringType \
|
|
||||||
and (item != self.root \
|
|
||||||
or (item == self.root and not self.rootIsNamespace)):
|
|
||||||
itemtext = repr(key)
|
|
||||||
child = children[key]
|
|
||||||
data = wx.wxTreeItemData(child)
|
|
||||||
branch = self.AppendItem(parent=item, text=itemtext, data=data)
|
|
||||||
self.SetItemHasChildren(branch, self.hasChildren(child))
|
|
||||||
|
|
||||||
def display(self):
|
|
||||||
item = self.item
|
|
||||||
if self.IsExpanded(item):
|
|
||||||
self.addChildren(item)
|
|
||||||
self.setText('')
|
|
||||||
obj = self.GetPyData(item)
|
|
||||||
if obj is None: # Windows bug fix.
|
|
||||||
return
|
|
||||||
self.SetItemHasChildren(item, self.hasChildren(obj))
|
|
||||||
otype = type(obj)
|
|
||||||
text = ''
|
|
||||||
text += self.getFullName(item)
|
|
||||||
text += '\n\nType: ' + str(otype)
|
|
||||||
try:
|
|
||||||
value = str(obj)
|
|
||||||
except:
|
|
||||||
value = ''
|
|
||||||
if otype is types.StringType or otype is types.UnicodeType:
|
|
||||||
value = repr(obj)
|
|
||||||
text += '\n\nValue: ' + value
|
|
||||||
if otype not in SIMPLETYPES:
|
|
||||||
try:
|
|
||||||
text += '\n\nDocstring:\n\n"""' + \
|
|
||||||
inspect.getdoc(obj).strip() + '"""'
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if otype is types.InstanceType:
|
|
||||||
try:
|
|
||||||
text += '\n\nClass Definition:\n\n' + \
|
|
||||||
inspect.getsource(obj.__class__)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
text += '\n\nSource Code:\n\n' + \
|
|
||||||
inspect.getsource(obj)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.setText(text)
|
|
||||||
|
|
||||||
def getFullName(self, item, partial=''):
|
|
||||||
"""Return a syntactically proper name for item."""
|
|
||||||
name = self.GetItemText(item)
|
|
||||||
parent = None
|
|
||||||
obj = None
|
|
||||||
if item != self.root:
|
|
||||||
parent = self.GetItemParent(item)
|
|
||||||
obj = self.GetPyData(parent)
|
|
||||||
# Apply dictionary syntax to dictionary items, except the root
|
|
||||||
# and first level children of a namepace.
|
|
||||||
if (type(obj) is types.DictType \
|
|
||||||
or str(type(obj))[17:23] == 'BTrees' \
|
|
||||||
and hasattr(obj, 'keys')) \
|
|
||||||
and ((item != self.root and parent != self.root) \
|
|
||||||
or (parent == self.root and not self.rootIsNamespace)):
|
|
||||||
name = '[' + name + ']'
|
|
||||||
# Apply dot syntax to multipart names.
|
|
||||||
if partial:
|
|
||||||
if partial[0] == '[':
|
|
||||||
name += partial
|
|
||||||
else:
|
|
||||||
name += '.' + partial
|
|
||||||
# Repeat for everything but the root item
|
|
||||||
# and first level children of a namespace.
|
|
||||||
if (item != self.root and parent != self.root) \
|
|
||||||
or (parent == self.root and not self.rootIsNamespace):
|
|
||||||
name = self.getFullName(parent, partial=name)
|
|
||||||
return name
|
|
||||||
|
|
||||||
def setText(self, text):
|
|
||||||
"""Display information about the current selection."""
|
|
||||||
|
|
||||||
# This method will likely be replaced by the enclosing app to
|
|
||||||
# do something more interesting, like write to a text control.
|
|
||||||
print text
|
|
||||||
|
|
||||||
def setStatusText(self, text):
|
|
||||||
"""Display status information."""
|
|
||||||
|
|
||||||
# This method will likely be replaced by the enclosing app to
|
|
||||||
# do something more interesting, like write to a status bar.
|
|
||||||
print text
|
|
||||||
|
|
||||||
|
|
||||||
if wx.wxPlatform == '__WXMSW__':
|
|
||||||
faces = { 'times' : 'Times New Roman',
|
|
||||||
'mono' : 'Courier New',
|
|
||||||
'helv' : 'Lucida Console',
|
|
||||||
'lucida' : 'Lucida Console',
|
|
||||||
'other' : 'Comic Sans MS',
|
|
||||||
'size' : 10,
|
|
||||||
'lnsize' : 9,
|
|
||||||
'backcol': '#FFFFFF',
|
|
||||||
}
|
|
||||||
else: # GTK
|
|
||||||
faces = { 'times' : 'Times',
|
|
||||||
'mono' : 'Courier',
|
|
||||||
'helv' : 'Helvetica',
|
|
||||||
'other' : 'new century schoolbook',
|
|
||||||
'size' : 12,
|
|
||||||
'lnsize' : 10,
|
|
||||||
'backcol': '#FFFFFF',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FillingText(stc.wxStyledTextCtrl):
|
|
||||||
"""PyCrust FillingText based on wxStyledTextCtrl."""
|
|
||||||
|
|
||||||
name = 'PyCrust Filling Text'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
|
||||||
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN,
|
|
||||||
static=False):
|
|
||||||
"""Create a PyCrust FillingText instance."""
|
|
||||||
stc.wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
|
||||||
# Configure various defaults and user preferences.
|
|
||||||
self.config()
|
|
||||||
dispatcher.connect(receiver=self.fontsizer, signal='FontIncrease')
|
|
||||||
dispatcher.connect(receiver=self.fontsizer, signal='FontDecrease')
|
|
||||||
dispatcher.connect(receiver=self.fontsizer, signal='FontDefault')
|
|
||||||
if not static:
|
|
||||||
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
|
||||||
|
|
||||||
def push(self, command, more):
|
|
||||||
"""Receiver for Interpreter.push signal."""
|
|
||||||
self.Refresh()
|
|
||||||
|
|
||||||
def fontsizer(self, signal):
|
|
||||||
"""Receiver for Font* signals."""
|
|
||||||
size = self.GetZoom()
|
|
||||||
if signal == 'FontIncrease':
|
|
||||||
size += 1
|
|
||||||
elif signal == 'FontDecrease':
|
|
||||||
size -= 1
|
|
||||||
elif signal == 'FontDefault':
|
|
||||||
size = 0
|
|
||||||
self.SetZoom(size)
|
|
||||||
|
|
||||||
def config(self):
|
|
||||||
"""Configure shell based on user preferences."""
|
|
||||||
self.SetMarginWidth(1, 0)
|
|
||||||
|
|
||||||
self.SetLexer(stc.wxSTC_LEX_PYTHON)
|
|
||||||
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
|
||||||
|
|
||||||
self.setStyles(faces)
|
|
||||||
self.SetViewWhiteSpace(0)
|
|
||||||
self.SetTabWidth(4)
|
|
||||||
self.SetUseTabs(0)
|
|
||||||
self.SetReadOnly(1)
|
|
||||||
try:
|
|
||||||
self.SetWrapMode(1)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def setStyles(self, faces):
|
|
||||||
"""Configure font size, typeface and color for lexer."""
|
|
||||||
|
|
||||||
# Default style
|
|
||||||
self.StyleSetSpec(stc.wxSTC_STYLE_DEFAULT,
|
|
||||||
"face:%(mono)s,size:%(size)d" % faces)
|
|
||||||
|
|
||||||
self.StyleClearAll()
|
|
||||||
|
|
||||||
# Built in styles
|
|
||||||
self.StyleSetSpec(stc.wxSTC_STYLE_LINENUMBER,
|
|
||||||
"back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
|
||||||
self.StyleSetSpec(stc.wxSTC_STYLE_CONTROLCHAR,
|
|
||||||
"face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.wxSTC_STYLE_BRACELIGHT,
|
|
||||||
"fore:#0000FF,back:#FFFF88")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_STYLE_BRACEBAD,
|
|
||||||
"fore:#FF0000,back:#FFFF88")
|
|
||||||
|
|
||||||
# Python styles
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_DEFAULT,
|
|
||||||
"face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_COMMENTLINE,
|
|
||||||
"fore:#007F00,face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_NUMBER,
|
|
||||||
"")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_STRING,
|
|
||||||
"fore:#7F007F,face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_CHARACTER,
|
|
||||||
"fore:#7F007F,face:%(mono)s" % faces)
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_WORD,
|
|
||||||
"fore:#00007F,bold")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_TRIPLE,
|
|
||||||
"fore:#7F0000")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_TRIPLEDOUBLE,
|
|
||||||
"fore:#000033,back:#FFFFE8")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_CLASSNAME,
|
|
||||||
"fore:#0000FF,bold")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_DEFNAME,
|
|
||||||
"fore:#007F7F,bold")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_OPERATOR,
|
|
||||||
"")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_IDENTIFIER,
|
|
||||||
"")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_COMMENTBLOCK,
|
|
||||||
"fore:#7F7F7F")
|
|
||||||
self.StyleSetSpec(stc.wxSTC_P_STRINGEOL,
|
|
||||||
"fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
|
||||||
|
|
||||||
def SetText(self, *args, **kwds):
|
|
||||||
self.SetReadOnly(0)
|
|
||||||
stc.wxStyledTextCtrl.SetText(self, *args, **kwds)
|
|
||||||
self.SetReadOnly(1)
|
|
||||||
|
|
||||||
|
|
||||||
class Filling(wx.wxSplitterWindow):
|
|
||||||
"""PyCrust Filling based on wxSplitterWindow."""
|
|
||||||
|
|
||||||
name = 'PyCrust Filling'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
|
||||||
size=wx.wxDefaultSize, style=wx.wxSP_3D,
|
|
||||||
name='Filling Window', rootObject=None,
|
|
||||||
rootLabel=None, rootIsNamespace=0, static=False):
|
|
||||||
"""Create a PyCrust Filling instance."""
|
|
||||||
wx.wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
|
||||||
self.tree = FillingTree(parent=self, rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace,
|
|
||||||
static=static)
|
|
||||||
self.text = FillingText(parent=self, static=static)
|
|
||||||
self.SplitVertically(self.tree, self.text, 200)
|
|
||||||
self.SetMinimumPaneSize(1)
|
|
||||||
# Override the filling so that descriptions go to FillingText.
|
|
||||||
self.tree.setText = self.text.SetText
|
|
||||||
# Display the root item.
|
|
||||||
## self.tree.SelectItem(self.tree.root)
|
|
||||||
self.tree.display()
|
|
||||||
|
|
||||||
|
|
||||||
class FillingFrame(wx.wxFrame):
|
|
||||||
"""Frame containing the PyCrust filling, or namespace tree component."""
|
|
||||||
|
|
||||||
name = 'PyCrust Filling Frame'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyFilling',
|
|
||||||
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize,
|
|
||||||
style=wx.wxDEFAULT_FRAME_STYLE, rootObject=None,
|
|
||||||
rootLabel=None, rootIsNamespace=0, static=False):
|
|
||||||
"""Create a PyCrust FillingFrame instance."""
|
|
||||||
wx.wxFrame.__init__(self, parent, id, title, pos, size, style)
|
|
||||||
intro = 'PyFilling - The Tastiest Namespace Inspector'
|
|
||||||
self.CreateStatusBar()
|
|
||||||
self.SetStatusText(intro)
|
|
||||||
import images
|
|
||||||
self.SetIcon(images.getPyCrustIcon())
|
|
||||||
self.filling = Filling(parent=self, rootObject=rootObject,
|
|
||||||
rootLabel=rootLabel,
|
|
||||||
rootIsNamespace=rootIsNamespace,
|
|
||||||
static=static)
|
|
||||||
# Override so that status messages go to the status bar.
|
|
||||||
self.filling.tree.setStatusText = self.SetStatusText
|
|
||||||
|
|
||||||
|
|
||||||
class App(wx.wxApp):
|
|
||||||
"""PyFilling standalone application."""
|
|
||||||
|
|
||||||
def OnInit(self):
|
|
||||||
wx.wxInitAllImageHandlers()
|
|
||||||
self.fillingFrame = FillingFrame()
|
|
||||||
self.fillingFrame.Show(True)
|
|
||||||
self.SetTopWindow(self.fillingFrame)
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,226 +0,0 @@
|
|||||||
"""Shell menu mixin shared by shell and crust."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
from wxPython import wx
|
|
||||||
import sys
|
|
||||||
from version import VERSION
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
ID_AUTOCOMP = wx.wxNewId()
|
|
||||||
ID_AUTOCOMP_SHOW = wx.wxNewId()
|
|
||||||
ID_AUTOCOMP_INCLUDE_MAGIC = wx.wxNewId()
|
|
||||||
ID_AUTOCOMP_INCLUDE_SINGLE = wx.wxNewId()
|
|
||||||
ID_AUTOCOMP_INCLUDE_DOUBLE = wx.wxNewId()
|
|
||||||
ID_CALLTIPS = wx.wxNewId()
|
|
||||||
ID_CALLTIPS_SHOW = wx.wxNewId()
|
|
||||||
ID_COPY_PLUS = wx.wxNewId()
|
|
||||||
ID_PASTE_PLUS = wx.wxNewId()
|
|
||||||
ID_WRAP = wx.wxNewId()
|
|
||||||
|
|
||||||
|
|
||||||
class ShellMenu:
|
|
||||||
"""Mixin class to add standard menu items."""
|
|
||||||
|
|
||||||
def createMenus(self):
|
|
||||||
m = self.fileMenu = wx.wxMenu()
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wx.wxID_EXIT, 'E&xit', 'Exit PyCrust')
|
|
||||||
|
|
||||||
m = self.editMenu = wx.wxMenu()
|
|
||||||
m.Append(wx.wxID_UNDO, '&Undo \tCtrl+Z',
|
|
||||||
'Undo the last action')
|
|
||||||
m.Append(wx.wxID_REDO, '&Redo \tCtrl+Y',
|
|
||||||
'Redo the last undone action')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wx.wxID_CUT, 'Cu&t \tCtrl+X',
|
|
||||||
'Cut the selection')
|
|
||||||
m.Append(wx.wxID_COPY, '&Copy \tCtrl+C',
|
|
||||||
'Copy the selection - removing prompts')
|
|
||||||
m.Append(ID_COPY_PLUS, 'Cop&y Plus \tCtrl+Shift+C',
|
|
||||||
'Copy the selection - retaining prompts')
|
|
||||||
m.Append(wx.wxID_PASTE, '&Paste \tCtrl+V', 'Paste')
|
|
||||||
m.Append(ID_PASTE_PLUS, 'Past&e Plus \tCtrl+Shift+V',
|
|
||||||
'Paste and run commands')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wx.wxID_CLEAR, 'Cle&ar',
|
|
||||||
'Delete the selection')
|
|
||||||
m.Append(wx.wxID_SELECTALL, 'Select A&ll \tCtrl+A',
|
|
||||||
'Select all text')
|
|
||||||
|
|
||||||
m = self.autocompMenu = wx.wxMenu()
|
|
||||||
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion',
|
|
||||||
'Show auto completion during dot syntax', 1)
|
|
||||||
m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes',
|
|
||||||
'Include attributes visible to __getattr__ and __setattr__',
|
|
||||||
1)
|
|
||||||
m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores',
|
|
||||||
'Include attibutes prefixed by a single underscore', 1)
|
|
||||||
m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores',
|
|
||||||
'Include attibutes prefixed by a double underscore', 1)
|
|
||||||
|
|
||||||
m = self.calltipsMenu = wx.wxMenu()
|
|
||||||
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips',
|
|
||||||
'Show call tips with argument specifications', 1)
|
|
||||||
|
|
||||||
m = self.optionsMenu = wx.wxMenu()
|
|
||||||
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu,
|
|
||||||
'Auto Completion Options')
|
|
||||||
m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu,
|
|
||||||
'Call Tip Options')
|
|
||||||
m.Append(ID_WRAP, '&Wrap Lines',
|
|
||||||
'Wrap lines at right edge', 1)
|
|
||||||
|
|
||||||
m = self.helpMenu = wx.wxMenu()
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wx.wxID_ABOUT, '&About...', 'About PyCrust')
|
|
||||||
|
|
||||||
b = self.menuBar = wx.wxMenuBar()
|
|
||||||
b.Append(self.fileMenu, '&File')
|
|
||||||
b.Append(self.editMenu, '&Edit')
|
|
||||||
b.Append(self.optionsMenu, '&Options')
|
|
||||||
b.Append(self.helpMenu, '&Help')
|
|
||||||
self.SetMenuBar(b)
|
|
||||||
|
|
||||||
wx.EVT_MENU(self, wx.wxID_EXIT, self.OnExit)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_UNDO, self.OnUndo)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_REDO, self.OnRedo)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_CUT, self.OnCut)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_COPY, self.OnCopy)
|
|
||||||
wx.EVT_MENU(self, ID_COPY_PLUS, self.OnCopyPlus)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_PASTE, self.OnPaste)
|
|
||||||
wx.EVT_MENU(self, ID_PASTE_PLUS, self.OnPastePlus)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_CLEAR, self.OnClear)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_SELECTALL, self.OnSelectAll)
|
|
||||||
wx.EVT_MENU(self, wx.wxID_ABOUT, self.OnAbout)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_SHOW,
|
|
||||||
self.OnAutoCompleteShow)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_INCLUDE_MAGIC,
|
|
||||||
self.OnAutoCompleteIncludeMagic)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_INCLUDE_SINGLE,
|
|
||||||
self.OnAutoCompleteIncludeSingle)
|
|
||||||
wx.EVT_MENU(self, ID_AUTOCOMP_INCLUDE_DOUBLE,
|
|
||||||
self.OnAutoCompleteIncludeDouble)
|
|
||||||
wx.EVT_MENU(self, ID_CALLTIPS_SHOW,
|
|
||||||
self.OnCallTipsShow)
|
|
||||||
wx.EVT_MENU(self, ID_WRAP, self.OnWrap)
|
|
||||||
|
|
||||||
wx.EVT_UPDATE_UI(self, wx.wxID_UNDO, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, wx.wxID_REDO, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, wx.wxID_CUT, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, wx.wxID_COPY, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_COPY_PLUS, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, wx.wxID_PASTE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_PASTE_PLUS, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, wx.wxID_CLEAR, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SHOW, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_MAGIC, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_SINGLE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_DOUBLE, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_CALLTIPS_SHOW, self.OnUpdateMenu)
|
|
||||||
wx.EVT_UPDATE_UI(self, ID_WRAP, self.OnUpdateMenu)
|
|
||||||
|
|
||||||
def OnExit(self, event):
|
|
||||||
self.Close(True)
|
|
||||||
|
|
||||||
def OnUndo(self, event):
|
|
||||||
self.shell.Undo()
|
|
||||||
|
|
||||||
def OnRedo(self, event):
|
|
||||||
self.shell.Redo()
|
|
||||||
|
|
||||||
def OnCut(self, event):
|
|
||||||
self.shell.Cut()
|
|
||||||
|
|
||||||
def OnCopy(self, event):
|
|
||||||
self.shell.Copy()
|
|
||||||
|
|
||||||
def OnCopyPlus(self, event):
|
|
||||||
self.shell.CopyWithPrompts()
|
|
||||||
|
|
||||||
def OnPaste(self, event):
|
|
||||||
self.shell.Paste()
|
|
||||||
|
|
||||||
def OnPastePlus(self, event):
|
|
||||||
self.shell.PasteAndRun()
|
|
||||||
|
|
||||||
def OnClear(self, event):
|
|
||||||
self.shell.Clear()
|
|
||||||
|
|
||||||
def OnSelectAll(self, event):
|
|
||||||
self.shell.SelectAll()
|
|
||||||
|
|
||||||
def OnAbout(self, event):
|
|
||||||
"""Display an About PyCrust window."""
|
|
||||||
title = 'About PyCrust'
|
|
||||||
text = 'PyCrust %s\n\n' % VERSION + \
|
|
||||||
'Yet another Python shell, only flakier.\n\n' + \
|
|
||||||
'Half-baked by Patrick K. O\'Brien,\n' + \
|
|
||||||
'the other half is still in the oven.\n\n' + \
|
|
||||||
'Shell Revision: %s\n' % self.shell.revision + \
|
|
||||||
'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
|
|
||||||
'Python Version: %s\n' % sys.version.split()[0] + \
|
|
||||||
'wxPython Version: %s\n' % wx.__version__ + \
|
|
||||||
'Platform: %s\n' % sys.platform
|
|
||||||
dialog = wx.wxMessageDialog(self, text, title,
|
|
||||||
wx.wxOK | wx.wxICON_INFORMATION)
|
|
||||||
dialog.ShowModal()
|
|
||||||
dialog.Destroy()
|
|
||||||
|
|
||||||
def OnAutoCompleteShow(self, event):
|
|
||||||
self.shell.autoComplete = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteIncludeMagic(self, event):
|
|
||||||
self.shell.autoCompleteIncludeMagic = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteIncludeSingle(self, event):
|
|
||||||
self.shell.autoCompleteIncludeSingle = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteIncludeDouble(self, event):
|
|
||||||
self.shell.autoCompleteIncludeDouble = event.IsChecked()
|
|
||||||
|
|
||||||
def OnCallTipsShow(self, event):
|
|
||||||
self.shell.autoCallTip = event.IsChecked()
|
|
||||||
|
|
||||||
def OnWrap(self, event):
|
|
||||||
self.shell.SetWrapMode(event.IsChecked())
|
|
||||||
|
|
||||||
def OnUpdateMenu(self, event):
|
|
||||||
"""Update menu items based on current status."""
|
|
||||||
id = event.GetId()
|
|
||||||
if id == wx.wxID_UNDO:
|
|
||||||
event.Enable(self.shell.CanUndo())
|
|
||||||
elif id == wx.wxID_REDO:
|
|
||||||
event.Enable(self.shell.CanRedo())
|
|
||||||
elif id == wx.wxID_CUT:
|
|
||||||
event.Enable(self.shell.CanCut())
|
|
||||||
elif id == wx.wxID_COPY:
|
|
||||||
event.Enable(self.shell.CanCopy())
|
|
||||||
elif id == ID_COPY_PLUS:
|
|
||||||
event.Enable(self.shell.CanCopy())
|
|
||||||
elif id == wx.wxID_PASTE:
|
|
||||||
event.Enable(self.shell.CanPaste())
|
|
||||||
elif id == ID_PASTE_PLUS:
|
|
||||||
event.Enable(self.shell.CanPaste())
|
|
||||||
elif id == wx.wxID_CLEAR:
|
|
||||||
event.Enable(self.shell.CanCut())
|
|
||||||
elif id == ID_AUTOCOMP_SHOW:
|
|
||||||
event.Check(self.shell.autoComplete)
|
|
||||||
elif id == ID_AUTOCOMP_INCLUDE_MAGIC:
|
|
||||||
event.Check(self.shell.autoCompleteIncludeMagic)
|
|
||||||
elif id == ID_AUTOCOMP_INCLUDE_SINGLE:
|
|
||||||
event.Check(self.shell.autoCompleteIncludeSingle)
|
|
||||||
elif id == ID_AUTOCOMP_INCLUDE_DOUBLE:
|
|
||||||
event.Check(self.shell.autoCompleteIncludeDouble)
|
|
||||||
elif id == ID_CALLTIPS_SHOW:
|
|
||||||
event.Check(self.shell.autoCallTip)
|
|
||||||
elif id == ID_WRAP:
|
|
||||||
event.Check(self.shell.GetWrapMode())
|
|
||||||
|
|
@@ -1,54 +1,5 @@
|
|||||||
|
|
||||||
"""Wrap is a command line utility that runs a wxPython program with
|
from wxPython.py.PyWrap import *
|
||||||
additional runtime-tools, such as PyCrust."""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from wxPython import wx
|
|
||||||
from crust import CrustFrame as Frame
|
|
||||||
|
|
||||||
try:
|
|
||||||
True
|
|
||||||
except NameError:
|
|
||||||
True = 1==1
|
|
||||||
False = 1==0
|
|
||||||
|
|
||||||
|
|
||||||
def wrap(app):
|
|
||||||
wx.wxInitAllImageHandlers()
|
|
||||||
frame = Frame()
|
|
||||||
frame.SetSize((750, 525))
|
|
||||||
frame.Show(True)
|
|
||||||
frame.shell.interp.locals['app'] = app
|
|
||||||
app.MainLoop()
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
|
||||||
if len(argv) < 2:
|
|
||||||
print "Please specify a module name."
|
|
||||||
raise SystemExit
|
|
||||||
name = argv[1]
|
|
||||||
if name[-3:] == '.py':
|
|
||||||
name = name[:-3]
|
|
||||||
module = __import__(name)
|
|
||||||
# Find the App class.
|
|
||||||
App = None
|
|
||||||
d = module.__dict__
|
|
||||||
for item in d.keys():
|
|
||||||
try:
|
|
||||||
if issubclass(d[item], wx.wxApp):
|
|
||||||
App = d[item]
|
|
||||||
except (NameError, TypeError):
|
|
||||||
pass
|
|
||||||
if App is None:
|
|
||||||
print "No App class found."
|
|
||||||
raise SystemExit
|
|
||||||
app = App()
|
|
||||||
wrap(app)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@@ -1,488 +0,0 @@
|
|||||||
"""Decorator classes for documentation and shell scripting.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|
||||||
__cvsid__ = "$Id$"
|
|
||||||
__revision__ = "$Revision$"[11:-2]
|
|
||||||
|
|
||||||
|
|
||||||
# These are not the real wxPython classes. These are Python versions
|
|
||||||
# for documentation purposes. They are also used to apply docstrings
|
|
||||||
# to the real wxPython classes, which are SWIG-generated wrappers for
|
|
||||||
# C-language classes.
|
|
||||||
|
|
||||||
|
|
||||||
from Base import Object
|
|
||||||
import Parameters as wx
|
|
||||||
|
|
||||||
|
|
||||||
class Sizer(Object):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def Add(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def AddMany(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def AddSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def AddSpacer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def AddWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Clear(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def DeleteWindows(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Destroy(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Fit(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def FitInside(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetChildren(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetMinSize(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetMinSizeTuple(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetPosition(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetPositionTuple(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetSize(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetSizeTuple(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Hide(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def HideSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def HideWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Insert(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def InsertSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def InsertSpacer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def InsertWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def IsShown(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def IsShownSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def IsShownWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Layout(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Prepend(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def PrependSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def PrependSpacer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def PrependWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Remove(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RemovePos(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RemoveSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RemoveWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetDimension(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetItemMinSize(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetItemMinSizePos(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetItemMinSizeSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetItemMinSizeWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetMinSize(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetSizeHints(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetVirtualSizeHints(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Show(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def ShowItems(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def ShowSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def ShowWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _setOORInfo(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class SizerItem(Object):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def CalcMin(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def DeleteWindows(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetBorder(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetFlag(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetOption(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetPosition(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetRatio(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetSize(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetUserData(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def IsShown(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def IsSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def IsSpacer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def IsWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetBorder(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetDimension(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetFlag(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetInitSize(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetOption(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetRatio(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetRatioSize(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetRatioWH(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetSizer(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetWindow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def Show(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BoxSizer(Sizer):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def CalcMin(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetOrientation(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RecalcSizes(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetOrientation(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class GridSizer(Sizer):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def CalcMin(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetCols(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetHGap(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetRows(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetVGap(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RecalcSizes(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetCols(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetHGap(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetRows(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def SetVGap(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FlexGridSizer(GridSizer):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def AddGrowableCol(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def AddGrowableRow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def CalcMin(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RecalcSizes(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RemoveGrowableCol(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RemoveGrowableRow(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class NotebookSizer(Sizer):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def CalcMin(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetNotebook(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RecalcSizes(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PySizer(Sizer):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _setCallbackInfo(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class StaticBoxSizer(BoxSizer):
|
|
||||||
""""""
|
|
||||||
|
|
||||||
def CalcMin(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def GetStaticBox(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def RecalcSizes(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
@@ -7,6 +7,35 @@
|
|||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
0.9.1 (3/21/2003 to //2003)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Fixed bug in introspect.py on introspecting objects occurring
|
||||||
|
immediately after a secondary prompt, like this:
|
||||||
|
|
||||||
|
>>> l = [1, 2, 3]
|
||||||
|
>>> for n in range(3):
|
||||||
|
... l. <-- failed to popup autocomplete list
|
||||||
|
|
||||||
|
Added documentation files:
|
||||||
|
|
||||||
|
* MANUAL.txt (in PyCrust)
|
||||||
|
* wxPython.txt (in PyCrust/wxd)
|
||||||
|
* wx.txt (in wx)
|
||||||
|
* examples.txt (in wx/examples)
|
||||||
|
|
||||||
|
Added PyAlaMode.py and PyAlaCarte code editors.
|
||||||
|
|
||||||
|
Major refactoring to support editor and shell from the same base.
|
||||||
|
|
||||||
|
Renamed program files:
|
||||||
|
|
||||||
|
* PyCrustApp.py to PyCrust.py
|
||||||
|
* PyFillingApp.py to PyFilling.py
|
||||||
|
* PyShellApp.py to PyShell.py
|
||||||
|
* wrap.py to PyWrap.py
|
||||||
|
|
||||||
|
|
||||||
0.9 (2/27/2003 to 3/20/2003)
|
0.9 (2/27/2003 to 3/20/2003)
|
||||||
============================
|
============================
|
||||||
|
|
76
wxPython/wxPython/py/MANUAL.txt
Normal file
76
wxPython/wxPython/py/MANUAL.txt
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
===============
|
||||||
|
The Py Manual
|
||||||
|
===============
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
Py - Served Fresh Daily
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
:Author: Patrick K. O'Brien
|
||||||
|
:Contact: pobrien@orbtech.com
|
||||||
|
:Date: $Date$
|
||||||
|
:Revision: $Revision$
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
This document will show you how to make use of the Py programs and
|
||||||
|
library of modules.
|
||||||
|
|
||||||
|
|
||||||
|
What is Py?
|
||||||
|
===========
|
||||||
|
|
||||||
|
Py is really several things. Py is a set of standalone programs as
|
||||||
|
well as a library of modules that you can use in your own programs.
|
||||||
|
|
||||||
|
First, Py contains standalone programs that provide code editors and
|
||||||
|
graphical, Python shell interfaces. Second, Py contains a collections
|
||||||
|
of modules that you can use in your own wxPython applications to
|
||||||
|
provide similar services, either for your own use during development,
|
||||||
|
or as an interface for users of your program. Third, Py containss a
|
||||||
|
wrapper utility, providing you with runtime introspection capabilities
|
||||||
|
for your wxPython programs without having to include PyCrust or
|
||||||
|
PyShell in your program, or alter one line of your code.
|
||||||
|
|
||||||
|
|
||||||
|
Py standalone programs
|
||||||
|
======================
|
||||||
|
|
||||||
|
There are several standalone applications in the Py package:
|
||||||
|
|
||||||
|
* PyAlaCarte
|
||||||
|
* PyAlaMode
|
||||||
|
* PyCrust
|
||||||
|
* PyFilling
|
||||||
|
* PyShell
|
||||||
|
* PyWrap
|
||||||
|
|
||||||
|
|
||||||
|
Py modules
|
||||||
|
==========
|
||||||
|
|
||||||
|
Py was designed to be modular. That means graphical code is kept
|
||||||
|
separate from non-graphical code, and many of the Py modules can be
|
||||||
|
used by other programs. Likewise, other programs can supply some of
|
||||||
|
the modules needed by Py. For example, you could supply a customized
|
||||||
|
interpreter module and plug it in to the PyCrust standalone
|
||||||
|
application. As long as it supports the minimum functionality
|
||||||
|
required, PyCrust will work just as well with your interpreter as with
|
||||||
|
its default interpreter.
|
||||||
|
|
||||||
|
|
||||||
|
Py runtime wrapper
|
||||||
|
==================
|
||||||
|
|
||||||
|
The Py wrapper utility (``PyWrap.py``) lets you run an existing
|
||||||
|
wxPython program with a PyCrust frame at the same time. Inside the
|
||||||
|
PyCrust shell, the local variable ``app`` is assigned to your
|
||||||
|
application instance. In this way you can introspect your entire
|
||||||
|
application within the PyCrust shell and the PyFilling namespace
|
||||||
|
viewer. And through the use of the Py decorator classes, PyCrust can
|
||||||
|
display wxPython function and method signatures as well as docstrings
|
||||||
|
for the entire wxPython library.
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
44
wxPython/wxPython/py/PyAlaCarte.py
Executable file
44
wxPython/wxPython/py/PyAlaCarte.py
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""PyAlaCarte is a simple programmer's editor."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import editor
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
class App(wx.wxApp):
|
||||||
|
"""PyAlaCarte standalone application."""
|
||||||
|
|
||||||
|
def __init__(self, filename=None):
|
||||||
|
self.filename = filename
|
||||||
|
wx.wxApp.__init__(self, redirect=False)
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
wx.wxInitAllImageHandlers()
|
||||||
|
self.frame = editor.EditorFrame(filename=self.filename)
|
||||||
|
self.frame.Show()
|
||||||
|
self.SetTopWindow(self.frame)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main(filename=None):
|
||||||
|
app = App(filename)
|
||||||
|
app.MainLoop()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
filename = None
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
filename = os.path.realpath(sys.argv[1])
|
||||||
|
main(filename)
|
44
wxPython/wxPython/py/PyAlaMode.py
Executable file
44
wxPython/wxPython/py/PyAlaMode.py
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""PyAlaMode is a programmer's editor."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import editor
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
class App(wx.wxApp):
|
||||||
|
"""PyAlaMode standalone application."""
|
||||||
|
|
||||||
|
def __init__(self, filename=None):
|
||||||
|
self.filename = filename
|
||||||
|
wx.wxApp.__init__(self, redirect=False)
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
wx.wxInitAllImageHandlers()
|
||||||
|
self.frame = editor.EditorNotebookFrame(filename=self.filename)
|
||||||
|
self.frame.Show()
|
||||||
|
self.SetTopWindow(self.frame)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main(filename=None):
|
||||||
|
app = App(filename)
|
||||||
|
app.MainLoop()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
filename = None
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
filename = os.path.realpath(sys.argv[1])
|
||||||
|
main(filename)
|
71
wxPython/wxPython/py/PyCrust.py
Executable file
71
wxPython/wxPython/py/PyCrust.py
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""PyCrust is a python shell and namespace browser application."""
|
||||||
|
|
||||||
|
# The next two lines, and the other code below that makes use of
|
||||||
|
# ``__main__`` and ``original``, serve the purpose of cleaning up the
|
||||||
|
# main namespace to look as much as possible like the regular Python
|
||||||
|
# shell environment.
|
||||||
|
import __main__
|
||||||
|
original = __main__.__dict__.keys()
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class App(wx.wxApp):
|
||||||
|
"""PyCrust standalone application."""
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
from wxPython import wx
|
||||||
|
wx.wxInitAllImageHandlers()
|
||||||
|
locals = __main__.__dict__
|
||||||
|
from crust import CrustFrame
|
||||||
|
self.frame = CrustFrame(locals=locals)
|
||||||
|
self.frame.SetSize((800, 600))
|
||||||
|
self.frame.Show()
|
||||||
|
self.SetTopWindow(self.frame)
|
||||||
|
# Add the application object to the sys module's namespace.
|
||||||
|
# This allows a shell user to do:
|
||||||
|
# >>> import sys
|
||||||
|
# >>> sys.app.whatever
|
||||||
|
import sys
|
||||||
|
sys.app = self
|
||||||
|
return True
|
||||||
|
|
||||||
|
'''
|
||||||
|
The main() function needs to handle being imported, such as with the
|
||||||
|
pycrust script that wxPython installs:
|
||||||
|
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from wxPython.lib.PyCrust.PyCrustApp import main
|
||||||
|
main()
|
||||||
|
'''
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import __main__
|
||||||
|
md = __main__.__dict__
|
||||||
|
keepers = original
|
||||||
|
keepers.append('App')
|
||||||
|
for key in md.keys():
|
||||||
|
if key not in keepers:
|
||||||
|
del md[key]
|
||||||
|
app = App(0)
|
||||||
|
if md.has_key('App') and md['App'] is App:
|
||||||
|
del md['App']
|
||||||
|
if md.has_key('__main__') and md['__main__'] is __main__:
|
||||||
|
del md['__main__']
|
||||||
|
app.MainLoop()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
46
wxPython/wxPython/py/PyFilling.py
Executable file
46
wxPython/wxPython/py/PyFilling.py
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""PyFilling is a python namespace inspection application."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
# We use this object to get more introspection when run standalone.
|
||||||
|
app = None
|
||||||
|
|
||||||
|
import filling
|
||||||
|
|
||||||
|
# These are imported just to have something interesting to inspect.
|
||||||
|
import crust
|
||||||
|
import interpreter
|
||||||
|
import introspect
|
||||||
|
import pseudo
|
||||||
|
import shell
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class App(filling.App):
|
||||||
|
def OnInit(self):
|
||||||
|
filling.App.OnInit(self)
|
||||||
|
self.root = self.fillingFrame.filling.tree.root
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Create and run the application."""
|
||||||
|
global app
|
||||||
|
app = App(0)
|
||||||
|
app.fillingFrame.filling.tree.Expand(app.root)
|
||||||
|
app.MainLoop()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
72
wxPython/wxPython/py/PyShell.py
Executable file
72
wxPython/wxPython/py/PyShell.py
Executable file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""PyShell is a python shell application."""
|
||||||
|
|
||||||
|
# The next two lines, and the other code below that makes use of
|
||||||
|
# ``__main__`` and ``original``, serve the purpose of cleaning up the
|
||||||
|
# main namespace to look as much as possible like the regular Python
|
||||||
|
# shell environment.
|
||||||
|
import __main__
|
||||||
|
original = __main__.__dict__.keys()
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class App(wx.wxApp):
|
||||||
|
"""PyShell standalone application."""
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
from wxPython import wx
|
||||||
|
wx.wxInitAllImageHandlers()
|
||||||
|
locals = __main__.__dict__
|
||||||
|
from shell import ShellFrame
|
||||||
|
self.frame = ShellFrame(locals=locals)
|
||||||
|
self.frame.SetSize((750, 525))
|
||||||
|
self.frame.Show()
|
||||||
|
self.SetTopWindow(self.frame)
|
||||||
|
self.frame.shell.SetFocus()
|
||||||
|
# Add the application object to the sys module's namespace.
|
||||||
|
# This allows a shell user to do:
|
||||||
|
# >>> import sys
|
||||||
|
# >>> sys.app.whatever
|
||||||
|
import sys
|
||||||
|
sys.app = self
|
||||||
|
return 1
|
||||||
|
|
||||||
|
'''
|
||||||
|
The main() function needs to handle being imported, such as with the
|
||||||
|
pycrust script that wxPython installs:
|
||||||
|
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from wxPython.lib.PyCrust.PyCrustApp import main
|
||||||
|
main()
|
||||||
|
'''
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import __main__
|
||||||
|
md = __main__.__dict__
|
||||||
|
keepers = original
|
||||||
|
keepers.append('App')
|
||||||
|
for key in md.keys():
|
||||||
|
if key not in keepers:
|
||||||
|
del md[key]
|
||||||
|
app = App(0)
|
||||||
|
if md.has_key('App') and md['App'] is App:
|
||||||
|
del md['App']
|
||||||
|
if md.has_key('__main__') and md['__main__'] is __main__:
|
||||||
|
del md['__main__']
|
||||||
|
app.MainLoop()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
57
wxPython/wxPython/py/PyWrap.py
Executable file
57
wxPython/wxPython/py/PyWrap.py
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""PyWrap is a command line utility that runs a wxPython program with
|
||||||
|
additional runtime-tools, such as PyCrust."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from wxPython import wx
|
||||||
|
from crust import CrustFrame as Frame
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
def wrap(app):
|
||||||
|
wx.wxInitAllImageHandlers()
|
||||||
|
frame = Frame()
|
||||||
|
frame.SetSize((750, 525))
|
||||||
|
frame.Show(True)
|
||||||
|
frame.shell.interp.locals['app'] = app
|
||||||
|
app.MainLoop()
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
if len(argv) < 2:
|
||||||
|
print "Please specify a module name."
|
||||||
|
raise SystemExit
|
||||||
|
name = argv[1]
|
||||||
|
if name[-3:] == '.py':
|
||||||
|
name = name[:-3]
|
||||||
|
module = __import__(name)
|
||||||
|
# Find the App class.
|
||||||
|
App = None
|
||||||
|
d = module.__dict__
|
||||||
|
for item in d.keys():
|
||||||
|
try:
|
||||||
|
if issubclass(d[item], wx.wxApp):
|
||||||
|
App = d[item]
|
||||||
|
except (NameError, TypeError):
|
||||||
|
pass
|
||||||
|
if App is None:
|
||||||
|
print "No App class found."
|
||||||
|
raise SystemExit
|
||||||
|
app = App()
|
||||||
|
wrap(app)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.path.insert(0, os.curdir)
|
||||||
|
main(sys.argv)
|
20
wxPython/wxPython/py/__init__.py
Normal file
20
wxPython/wxPython/py/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
"""Python package."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
import base
|
||||||
|
import buffer
|
||||||
|
import crust
|
||||||
|
import dispatcher
|
||||||
|
import document
|
||||||
|
import editor
|
||||||
|
import filling
|
||||||
|
import frame
|
||||||
|
import images
|
||||||
|
import interpreter
|
||||||
|
import introspect
|
||||||
|
import pseudo
|
||||||
|
import shell
|
||||||
|
import version
|
195
wxPython/wxPython/py/base.py
Normal file
195
wxPython/wxPython/py/base.py
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
"""Base editor."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
from wxPython import stc
|
||||||
|
|
||||||
|
import keyword
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
import dispatcher
|
||||||
|
from version import VERSION
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
if wx.wxPlatform == '__WXMSW__':
|
||||||
|
FACES = { 'times' : 'Times New Roman',
|
||||||
|
'mono' : 'Courier New',
|
||||||
|
'helv' : 'Lucida Console',
|
||||||
|
'lucida' : 'Lucida Console',
|
||||||
|
'other' : 'Comic Sans MS',
|
||||||
|
'size' : 10,
|
||||||
|
'lnsize' : 9,
|
||||||
|
'backcol': '#FFFFFF',
|
||||||
|
}
|
||||||
|
else: # GTK
|
||||||
|
FACES = { 'times' : 'Times',
|
||||||
|
'mono' : 'Courier',
|
||||||
|
'helv' : 'Helvetica',
|
||||||
|
'other' : 'new century schoolbook',
|
||||||
|
'size' : 12,
|
||||||
|
'lnsize' : 10,
|
||||||
|
'backcol': '#FFFFFF',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Editor(stc.wxStyledTextCtrl):
|
||||||
|
"""Editor based on StyledTextCtrl."""
|
||||||
|
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
|
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER):
|
||||||
|
"""Create an Editor instance."""
|
||||||
|
stc.wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
||||||
|
self.__config()
|
||||||
|
stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
|
||||||
|
dispatcher.connect(receiver=self._fontsizer, signal='FontIncrease')
|
||||||
|
dispatcher.connect(receiver=self._fontsizer, signal='FontDecrease')
|
||||||
|
dispatcher.connect(receiver=self._fontsizer, signal='FontDefault')
|
||||||
|
|
||||||
|
def _fontsizer(self, signal):
|
||||||
|
"""Receiver for Font* signals."""
|
||||||
|
size = self.GetZoom()
|
||||||
|
if signal == 'FontIncrease':
|
||||||
|
size += 1
|
||||||
|
elif signal == 'FontDecrease':
|
||||||
|
size -= 1
|
||||||
|
elif signal == 'FontDefault':
|
||||||
|
size = 0
|
||||||
|
self.SetZoom(size)
|
||||||
|
|
||||||
|
def __config(self):
|
||||||
|
"""Configure shell based on user preferences."""
|
||||||
|
self.SetMarginType(1, stc.wxSTC_MARGIN_NUMBER)
|
||||||
|
self.SetMarginWidth(1, 40)
|
||||||
|
|
||||||
|
self.SetLexer(stc.wxSTC_LEX_PYTHON)
|
||||||
|
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
||||||
|
|
||||||
|
self.setStyles(FACES)
|
||||||
|
self.SetViewWhiteSpace(False)
|
||||||
|
self.SetTabWidth(4)
|
||||||
|
self.SetUseTabs(False)
|
||||||
|
# Do we want to automatically pop up command completion options?
|
||||||
|
self.autoComplete = True
|
||||||
|
self.autoCompleteIncludeMagic = True
|
||||||
|
self.autoCompleteIncludeSingle = True
|
||||||
|
self.autoCompleteIncludeDouble = True
|
||||||
|
self.autoCompleteCaseInsensitive = True
|
||||||
|
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
|
||||||
|
self.AutoCompSetAutoHide(False)
|
||||||
|
self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`')
|
||||||
|
# Do we want to automatically pop up command argument help?
|
||||||
|
self.autoCallTip = True
|
||||||
|
self.CallTipSetBackground(wx.wxColour(255, 255, 232))
|
||||||
|
self.SetWrapMode(False)
|
||||||
|
try:
|
||||||
|
self.SetEndAtLastLine(False)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setStyles(self, faces):
|
||||||
|
"""Configure font size, typeface and color for lexer."""
|
||||||
|
|
||||||
|
# Default style
|
||||||
|
self.StyleSetSpec(stc.wxSTC_STYLE_DEFAULT,
|
||||||
|
"face:%(mono)s,size:%(size)d,back:%(backcol)s" % \
|
||||||
|
faces)
|
||||||
|
|
||||||
|
self.StyleClearAll()
|
||||||
|
|
||||||
|
# Built in styles
|
||||||
|
self.StyleSetSpec(stc.wxSTC_STYLE_LINENUMBER,
|
||||||
|
"back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
||||||
|
self.StyleSetSpec(stc.wxSTC_STYLE_CONTROLCHAR,
|
||||||
|
"face:%(mono)s" % faces)
|
||||||
|
self.StyleSetSpec(stc.wxSTC_STYLE_BRACELIGHT,
|
||||||
|
"fore:#0000FF,back:#FFFF88")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_STYLE_BRACEBAD,
|
||||||
|
"fore:#FF0000,back:#FFFF88")
|
||||||
|
|
||||||
|
# Python styles
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_DEFAULT,
|
||||||
|
"face:%(mono)s" % faces)
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_COMMENTLINE,
|
||||||
|
"fore:#007F00,face:%(mono)s" % faces)
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_NUMBER,
|
||||||
|
"")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_STRING,
|
||||||
|
"fore:#7F007F,face:%(mono)s" % faces)
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_CHARACTER,
|
||||||
|
"fore:#7F007F,face:%(mono)s" % faces)
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_WORD,
|
||||||
|
"fore:#00007F,bold")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_TRIPLE,
|
||||||
|
"fore:#7F0000")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_TRIPLEDOUBLE,
|
||||||
|
"fore:#000033,back:#FFFFE8")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_CLASSNAME,
|
||||||
|
"fore:#0000FF,bold")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_DEFNAME,
|
||||||
|
"fore:#007F7F,bold")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_OPERATOR,
|
||||||
|
"")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_IDENTIFIER,
|
||||||
|
"")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_COMMENTBLOCK,
|
||||||
|
"fore:#7F7F7F")
|
||||||
|
self.StyleSetSpec(stc.wxSTC_P_STRINGEOL,
|
||||||
|
"fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
||||||
|
|
||||||
|
def OnUpdateUI(self, event):
|
||||||
|
"""Check for matching braces."""
|
||||||
|
# If the auto-complete window is up let it do its thing.
|
||||||
|
if self.AutoCompActive() or self.CallTipActive():
|
||||||
|
return
|
||||||
|
braceAtCaret = -1
|
||||||
|
braceOpposite = -1
|
||||||
|
charBefore = None
|
||||||
|
caretPos = self.GetCurrentPos()
|
||||||
|
if caretPos > 0:
|
||||||
|
charBefore = self.GetCharAt(caretPos - 1)
|
||||||
|
styleBefore = self.GetStyleAt(caretPos - 1)
|
||||||
|
|
||||||
|
# Check before.
|
||||||
|
if charBefore and chr(charBefore) in '[]{}()' \
|
||||||
|
and styleBefore == stc.wxSTC_P_OPERATOR:
|
||||||
|
braceAtCaret = caretPos - 1
|
||||||
|
|
||||||
|
# Check after.
|
||||||
|
if braceAtCaret < 0:
|
||||||
|
charAfter = self.GetCharAt(caretPos)
|
||||||
|
styleAfter = self.GetStyleAt(caretPos)
|
||||||
|
if charAfter and chr(charAfter) in '[]{}()' \
|
||||||
|
and styleAfter == stc.wxSTC_P_OPERATOR:
|
||||||
|
braceAtCaret = caretPos
|
||||||
|
|
||||||
|
if braceAtCaret >= 0:
|
||||||
|
braceOpposite = self.BraceMatch(braceAtCaret)
|
||||||
|
|
||||||
|
if braceAtCaret != -1 and braceOpposite == -1:
|
||||||
|
self.BraceBadLight(braceAtCaret)
|
||||||
|
else:
|
||||||
|
self.BraceHighlight(braceAtCaret, braceOpposite)
|
||||||
|
|
||||||
|
def CanCut(self):
|
||||||
|
"""Return true if text is selected and can be cut."""
|
||||||
|
return self.CanCopy()
|
||||||
|
|
||||||
|
def CanCopy(self):
|
||||||
|
"""Return true if text is selected and can be copied."""
|
||||||
|
return self.GetSelectionStart() != self.GetSelectionEnd()
|
||||||
|
|
||||||
|
def CanEdit(self):
|
||||||
|
"""Return true if editing should succeed."""
|
||||||
|
return True
|
140
wxPython/wxPython/py/buffer.py
Normal file
140
wxPython/wxPython/py/buffer.py
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
"""Buffer class."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
import imp
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import document
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class Buffer:
|
||||||
|
"""Buffer class."""
|
||||||
|
|
||||||
|
id = 0
|
||||||
|
|
||||||
|
def __init__(self, editor, interp, filename=None):
|
||||||
|
"""Create a Buffer instance."""
|
||||||
|
Buffer.id += 1
|
||||||
|
self.id = Buffer.id
|
||||||
|
self.name = ''
|
||||||
|
self.editor = editor
|
||||||
|
self.interp = interp
|
||||||
|
self.modules = sys.modules.keys()
|
||||||
|
self.syspath = sys.path[:]
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
self.syspath.remove('')
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
self.syspath.remove('.')
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
self.open(filename)
|
||||||
|
|
||||||
|
def getStatus(self):
|
||||||
|
"""Return (filepath, line, column) status tuple."""
|
||||||
|
editor = self.editor
|
||||||
|
pos = editor.GetCurrentPos()
|
||||||
|
line = editor.LineFromPosition(pos) + 1
|
||||||
|
col = editor.GetColumn(pos) + 1
|
||||||
|
status = (self.doc.filepath or self.name, line, col)
|
||||||
|
return status
|
||||||
|
|
||||||
|
def hasChanged(self):
|
||||||
|
"""Return True if text in editor has changed since last save."""
|
||||||
|
return self.editor.GetModify()
|
||||||
|
|
||||||
|
def new(self, filepath):
|
||||||
|
"""New empty buffer."""
|
||||||
|
if not filepath:
|
||||||
|
return
|
||||||
|
if os.path.exists(filepath):
|
||||||
|
self.confirmed = self.overwriteConfirm(filepath)
|
||||||
|
else:
|
||||||
|
self.confirmed = True
|
||||||
|
|
||||||
|
def open(self, filename):
|
||||||
|
"""Open file into buffer."""
|
||||||
|
self.doc = document.Document(filename)
|
||||||
|
self.name = self.doc.filename or ('Untitled:' + str(self.id))
|
||||||
|
self.modulename = self.doc.filebase
|
||||||
|
if self.doc.filepath and os.path.exists(self.doc.filepath):
|
||||||
|
self.editor.ClearAll()
|
||||||
|
self.editor.SetText(self.doc.read())
|
||||||
|
self.editor.EmptyUndoBuffer()
|
||||||
|
self.editor.SetSavePoint()
|
||||||
|
self.confirmed = True
|
||||||
|
if self.doc.filedir and self.doc.filedir not in self.syspath:
|
||||||
|
self.syspath.insert(0, self.doc.filedir)
|
||||||
|
|
||||||
|
def overwriteConfirm(filepath):
|
||||||
|
"""Confirm overwriting an existing file."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
"""Save buffer."""
|
||||||
|
filepath = self.doc.filepath
|
||||||
|
if not filepath:
|
||||||
|
return # XXX Get filename
|
||||||
|
if not os.path.exists(filepath):
|
||||||
|
self.confirmed = True
|
||||||
|
if not self.confirmed:
|
||||||
|
self.confirmed = self.overwriteConfirm(filepath)
|
||||||
|
if self.confirmed:
|
||||||
|
self.doc.write(self.editor.GetText())
|
||||||
|
self.editor.SetSavePoint()
|
||||||
|
|
||||||
|
def saveAs(self, filename):
|
||||||
|
"""Save buffer."""
|
||||||
|
self.doc = document.Document(filename)
|
||||||
|
self.name = self.doc.filename
|
||||||
|
self.modulename = self.doc.filebase
|
||||||
|
filepath = self.doc.filepath
|
||||||
|
if not filepath:
|
||||||
|
return # XXX Get filename
|
||||||
|
## if not os.path.exists(filepath):
|
||||||
|
self.confirmed = True
|
||||||
|
if not self.confirmed:
|
||||||
|
self.confirmed = self.overwriteConfirm(filepath)
|
||||||
|
if self.confirmed:
|
||||||
|
self.doc.write(self.editor.GetText())
|
||||||
|
self.editor.SetSavePoint()
|
||||||
|
|
||||||
|
def updateNamespace(self):
|
||||||
|
"""Update the namespace for autocompletion and calltips.
|
||||||
|
|
||||||
|
Return True if updated, False if there was an error."""
|
||||||
|
backup = self.interp.locals
|
||||||
|
syspath = sys.path
|
||||||
|
sys.path = self.syspath
|
||||||
|
code = self.editor.GetText()
|
||||||
|
module = imp.new_module(str(self.modulename))
|
||||||
|
namespace = module.__dict__.copy()
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
exec code in namespace
|
||||||
|
except:
|
||||||
|
self.interp.locals = backup
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
self.interp.locals = namespace
|
||||||
|
return True
|
||||||
|
finally:
|
||||||
|
sys.path = syspath
|
||||||
|
for m in sys.modules.keys():
|
||||||
|
if m not in self.modules:
|
||||||
|
del sys.modules[m]
|
182
wxPython/wxPython/py/crust.py
Normal file
182
wxPython/wxPython/py/crust.py
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
"""PyCrust Crust combines the shell and filling into one control."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import dispatcher
|
||||||
|
from filling import Filling
|
||||||
|
import frame
|
||||||
|
from shell import Shell
|
||||||
|
from version import VERSION
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class Crust(wx.wxSplitterWindow):
|
||||||
|
"""PyCrust Crust based on wxSplitterWindow."""
|
||||||
|
|
||||||
|
name = 'PyCrust Crust'
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
|
size=wx.wxDefaultSize, style=wx.wxSP_3D,
|
||||||
|
name='Crust Window', rootObject=None, rootLabel=None,
|
||||||
|
rootIsNamespace=True, intro='', locals=None,
|
||||||
|
InterpClass=None, *args, **kwds):
|
||||||
|
"""Create a PyCrust Crust instance."""
|
||||||
|
wx.wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
||||||
|
self.shell = Shell(parent=self, introText=intro,
|
||||||
|
locals=locals, InterpClass=InterpClass,
|
||||||
|
*args, **kwds)
|
||||||
|
self.buffer = self.shell.buffer
|
||||||
|
if rootObject is None:
|
||||||
|
rootObject = self.shell.interp.locals
|
||||||
|
self.notebook = wx.wxNotebook(parent=self, id=-1)
|
||||||
|
self.shell.interp.locals['notebook'] = self.notebook
|
||||||
|
self.filling = Filling(parent=self.notebook,
|
||||||
|
rootObject=rootObject,
|
||||||
|
rootLabel=rootLabel,
|
||||||
|
rootIsNamespace=rootIsNamespace)
|
||||||
|
# Add 'filling' to the interpreter's locals.
|
||||||
|
self.shell.interp.locals['filling'] = self.filling
|
||||||
|
self.notebook.AddPage(page=self.filling, text='Namespace', select=True)
|
||||||
|
self.calltip = Calltip(parent=self.notebook)
|
||||||
|
self.notebook.AddPage(page=self.calltip, text='Calltip')
|
||||||
|
self.sessionlisting = SessionListing(parent=self.notebook)
|
||||||
|
self.notebook.AddPage(page=self.sessionlisting, text='Session')
|
||||||
|
self.dispatcherlisting = DispatcherListing(parent=self.notebook)
|
||||||
|
self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
|
||||||
|
from wxd import wx_
|
||||||
|
self.wxdocs = Filling(parent=self.notebook,
|
||||||
|
rootObject=wx_,
|
||||||
|
rootLabel='wx',
|
||||||
|
rootIsNamespace=False,
|
||||||
|
static=True)
|
||||||
|
self.notebook.AddPage(page=self.wxdocs, text='wxPython Docs')
|
||||||
|
from wxd import stc_
|
||||||
|
self.stcdocs = Filling(parent=self.notebook,
|
||||||
|
rootObject=stc_.StyledTextCtrl,
|
||||||
|
rootLabel='StyledTextCtrl',
|
||||||
|
rootIsNamespace=False,
|
||||||
|
static=True)
|
||||||
|
self.notebook.AddPage(page=self.stcdocs, text='StyledTextCtrl Docs')
|
||||||
|
self.SplitHorizontally(self.shell, self.notebook, 300)
|
||||||
|
self.SetMinimumPaneSize(1)
|
||||||
|
|
||||||
|
|
||||||
|
class Calltip(wx.wxTextCtrl):
|
||||||
|
"""Text control containing the most recent shell calltip."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1):
|
||||||
|
style = wx.wxTE_MULTILINE | wx.wxTE_READONLY | wx.wxTE_RICH2
|
||||||
|
wx.wxTextCtrl.__init__(self, parent=parent, id=id, style=style)
|
||||||
|
self.SetBackgroundColour(wx.wxColour(255, 255, 232))
|
||||||
|
dispatcher.connect(receiver=self.display, signal='Shell.calltip')
|
||||||
|
|
||||||
|
def display(self, calltip):
|
||||||
|
"""Receiver for Shell.calltip signal."""
|
||||||
|
self.SetValue(calltip)
|
||||||
|
|
||||||
|
|
||||||
|
class SessionListing(wx.wxTextCtrl):
|
||||||
|
"""Text control containing all commands for session."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1):
|
||||||
|
style = wx.wxTE_MULTILINE | wx.wxTE_READONLY | \
|
||||||
|
wx.wxTE_RICH2 | wx.wxTE_DONTWRAP
|
||||||
|
wx.wxTextCtrl.__init__(self, parent=parent, id=id, style=style)
|
||||||
|
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
||||||
|
|
||||||
|
def push(self, command, more):
|
||||||
|
"""Receiver for Interpreter.push signal."""
|
||||||
|
if command and not more:
|
||||||
|
self.SetInsertionPointEnd()
|
||||||
|
start, end = self.GetSelection()
|
||||||
|
if start != end:
|
||||||
|
self.SetSelection(0, 0)
|
||||||
|
self.AppendText(command + '\n')
|
||||||
|
|
||||||
|
|
||||||
|
class DispatcherListing(wx.wxTextCtrl):
|
||||||
|
"""Text control containing all dispatches for session."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1):
|
||||||
|
style = wx.wxTE_MULTILINE | wx.wxTE_READONLY | \
|
||||||
|
wx.wxTE_RICH2 | wx.wxTE_DONTWRAP
|
||||||
|
wx.wxTextCtrl.__init__(self, parent=parent, id=id, style=style)
|
||||||
|
dispatcher.connect(receiver=self.spy)
|
||||||
|
|
||||||
|
def spy(self, signal, sender):
|
||||||
|
"""Receiver for Any signal from Any sender."""
|
||||||
|
text = '%r from %s' % (signal, sender)
|
||||||
|
self.SetInsertionPointEnd()
|
||||||
|
start, end = self.GetSelection()
|
||||||
|
if start != end:
|
||||||
|
self.SetSelection(0, 0)
|
||||||
|
self.AppendText(text + '\n')
|
||||||
|
|
||||||
|
|
||||||
|
class CrustFrame(frame.Frame):
|
||||||
|
"""Frame containing all the PyCrust components."""
|
||||||
|
|
||||||
|
name = 'PyCrust Frame'
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1, title='PyCrust',
|
||||||
|
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize,
|
||||||
|
style=wx.wxDEFAULT_FRAME_STYLE,
|
||||||
|
rootObject=None, rootLabel=None, rootIsNamespace=True,
|
||||||
|
locals=None, InterpClass=None, *args, **kwds):
|
||||||
|
"""Create a PyCrust CrustFrame instance."""
|
||||||
|
frame.Frame.__init__(self, parent, id, title, pos, size, style)
|
||||||
|
intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||||
|
intro += '\nSponsored by Orbtech - '
|
||||||
|
intro += 'Your source for Python programming expertise.'
|
||||||
|
self.SetStatusText(intro.replace('\n', ', '))
|
||||||
|
self.crust = Crust(parent=self, intro=intro,
|
||||||
|
rootObject=rootObject,
|
||||||
|
rootLabel=rootLabel,
|
||||||
|
rootIsNamespace=rootIsNamespace,
|
||||||
|
locals=locals,
|
||||||
|
InterpClass=InterpClass, *args, **kwds)
|
||||||
|
self.shell = self.crust.shell
|
||||||
|
# Override the filling so that status messages go to the status bar.
|
||||||
|
self.crust.filling.tree.setStatusText = self.SetStatusText
|
||||||
|
# Override the shell so that status messages go to the status bar.
|
||||||
|
self.shell.setStatusText = self.SetStatusText
|
||||||
|
# Fix a problem with the sash shrinking to nothing.
|
||||||
|
self.crust.filling.SetSashPosition(200)
|
||||||
|
# Set focus to the shell editor.
|
||||||
|
self.shell.SetFocus()
|
||||||
|
|
||||||
|
def OnClose(self, event):
|
||||||
|
"""Event handler for closing."""
|
||||||
|
self.crust.shell.destroy()
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
def OnAbout(self, event):
|
||||||
|
"""Display an About window."""
|
||||||
|
title = 'About PyCrust'
|
||||||
|
text = 'PyCrust %s\n\n' % VERSION + \
|
||||||
|
'Yet another Python shell, only flakier.\n\n' + \
|
||||||
|
'Half-baked by Patrick K. O\'Brien,\n' + \
|
||||||
|
'the other half is still in the oven.\n\n' + \
|
||||||
|
'Shell Revision: %s\n' % self.shell.revision + \
|
||||||
|
'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
|
||||||
|
'Python Version: %s\n' % sys.version.split()[0] + \
|
||||||
|
'wxPython Version: %s\n' % wx.__version__ + \
|
||||||
|
'Platform: %s\n' % sys.platform
|
||||||
|
dialog = wx.wxMessageDialog(self, text, title,
|
||||||
|
wx.wxOK | wx.wxICON_INFORMATION)
|
||||||
|
dialog.ShowModal()
|
||||||
|
dialog.Destroy()
|
208
wxPython/wxPython/py/default.css
Normal file
208
wxPython/wxPython/py/default.css
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
:Author: David Goodger
|
||||||
|
:Contact: goodger@users.sourceforge.net
|
||||||
|
:date: $Date$
|
||||||
|
:version: $Revision$
|
||||||
|
:copyright: This stylesheet has been placed in the public domain.
|
||||||
|
|
||||||
|
Default cascading style sheet for the HTML output of Docutils.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0 }
|
||||||
|
|
||||||
|
.last {
|
||||||
|
margin-bottom: 0 }
|
||||||
|
|
||||||
|
a.toc-backref {
|
||||||
|
text-decoration: none ;
|
||||||
|
color: black }
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-bottom: 0.5em }
|
||||||
|
|
||||||
|
div.abstract {
|
||||||
|
margin: 2em 5em }
|
||||||
|
|
||||||
|
div.abstract p.topic-title {
|
||||||
|
font-weight: bold ;
|
||||||
|
text-align: center }
|
||||||
|
|
||||||
|
div.attention, div.caution, div.danger, div.error, div.hint,
|
||||||
|
div.important, div.note, div.tip, div.warning {
|
||||||
|
margin: 2em ;
|
||||||
|
border: medium outset ;
|
||||||
|
padding: 1em }
|
||||||
|
|
||||||
|
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||||
|
div.danger p.admonition-title, div.error p.admonition-title,
|
||||||
|
div.warning p.admonition-title {
|
||||||
|
color: red ;
|
||||||
|
font-weight: bold ;
|
||||||
|
font-family: sans-serif }
|
||||||
|
|
||||||
|
div.hint p.admonition-title, div.important p.admonition-title,
|
||||||
|
div.note p.admonition-title, div.tip p.admonition-title {
|
||||||
|
font-weight: bold ;
|
||||||
|
font-family: sans-serif }
|
||||||
|
|
||||||
|
div.dedication {
|
||||||
|
margin: 2em 5em ;
|
||||||
|
text-align: center ;
|
||||||
|
font-style: italic }
|
||||||
|
|
||||||
|
div.dedication p.topic-title {
|
||||||
|
font-weight: bold ;
|
||||||
|
font-style: normal }
|
||||||
|
|
||||||
|
div.figure {
|
||||||
|
margin-left: 2em }
|
||||||
|
|
||||||
|
div.footer, div.header {
|
||||||
|
font-size: smaller }
|
||||||
|
|
||||||
|
div.sidebar {
|
||||||
|
margin-left: 1em ;
|
||||||
|
border: medium outset ;
|
||||||
|
padding: 0em 1em ;
|
||||||
|
background-color: #ffffee ;
|
||||||
|
width: 40% ;
|
||||||
|
float: right }
|
||||||
|
|
||||||
|
div.system-messages {
|
||||||
|
margin: 5em }
|
||||||
|
|
||||||
|
div.system-messages h1 {
|
||||||
|
color: red }
|
||||||
|
|
||||||
|
div.system-message {
|
||||||
|
border: medium outset ;
|
||||||
|
padding: 1em }
|
||||||
|
|
||||||
|
div.system-message p.system-message-title {
|
||||||
|
color: red ;
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
margin: 2em }
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
text-align: center }
|
||||||
|
|
||||||
|
h2.subtitle {
|
||||||
|
text-align: center }
|
||||||
|
|
||||||
|
hr {
|
||||||
|
width: 75% }
|
||||||
|
|
||||||
|
ol.simple, ul.simple {
|
||||||
|
margin-bottom: 1em }
|
||||||
|
|
||||||
|
ol.arabic {
|
||||||
|
list-style: decimal }
|
||||||
|
|
||||||
|
ol.loweralpha {
|
||||||
|
list-style: lower-alpha }
|
||||||
|
|
||||||
|
ol.upperalpha {
|
||||||
|
list-style: upper-alpha }
|
||||||
|
|
||||||
|
ol.lowerroman {
|
||||||
|
list-style: lower-roman }
|
||||||
|
|
||||||
|
ol.upperroman {
|
||||||
|
list-style: upper-roman }
|
||||||
|
|
||||||
|
p.caption {
|
||||||
|
font-style: italic }
|
||||||
|
|
||||||
|
p.credits {
|
||||||
|
font-style: italic ;
|
||||||
|
font-size: smaller }
|
||||||
|
|
||||||
|
p.label {
|
||||||
|
white-space: nowrap }
|
||||||
|
|
||||||
|
p.sidebar-title {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-weight: bold ;
|
||||||
|
font-size: larger }
|
||||||
|
|
||||||
|
p.sidebar-subtitle {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
p.topic-title {
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
pre.address {
|
||||||
|
margin-bottom: 0 ;
|
||||||
|
margin-top: 0 ;
|
||||||
|
font-family: serif ;
|
||||||
|
font-size: 100% }
|
||||||
|
|
||||||
|
pre.line-block {
|
||||||
|
font-family: serif ;
|
||||||
|
font-size: 100% }
|
||||||
|
|
||||||
|
pre.literal-block, pre.doctest-block {
|
||||||
|
margin-left: 2em ;
|
||||||
|
margin-right: 2em ;
|
||||||
|
background-color: #eeeeee }
|
||||||
|
|
||||||
|
span.classifier {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-style: oblique }
|
||||||
|
|
||||||
|
span.classifier-delimiter {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
span.interpreted {
|
||||||
|
font-family: sans-serif }
|
||||||
|
|
||||||
|
span.option {
|
||||||
|
white-space: nowrap }
|
||||||
|
|
||||||
|
span.option-argument {
|
||||||
|
font-style: italic }
|
||||||
|
|
||||||
|
span.pre {
|
||||||
|
white-space: pre }
|
||||||
|
|
||||||
|
span.problematic {
|
||||||
|
color: red }
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-top: 0.5em ;
|
||||||
|
margin-bottom: 0.5em }
|
||||||
|
|
||||||
|
table.citation {
|
||||||
|
border-left: solid thin gray ;
|
||||||
|
padding-left: 0.5ex }
|
||||||
|
|
||||||
|
table.docinfo {
|
||||||
|
margin: 2em 4em }
|
||||||
|
|
||||||
|
table.footnote {
|
||||||
|
border-left: solid thin black ;
|
||||||
|
padding-left: 0.5ex }
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
padding-left: 0.5em ;
|
||||||
|
padding-right: 0.5em ;
|
||||||
|
vertical-align: top }
|
||||||
|
|
||||||
|
th.docinfo-name, th.field-name {
|
||||||
|
font-weight: bold ;
|
||||||
|
text-align: left ;
|
||||||
|
white-space: nowrap }
|
||||||
|
|
||||||
|
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||||
|
font-size: 100% }
|
||||||
|
|
||||||
|
tt {
|
||||||
|
background-color: #eeeeee }
|
||||||
|
|
||||||
|
ul.auto-toc {
|
||||||
|
list-style-type: none }
|
46
wxPython/wxPython/py/document.py
Normal file
46
wxPython/wxPython/py/document.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
"""Document class."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class Document:
|
||||||
|
"""Document class."""
|
||||||
|
|
||||||
|
def __init__(self, filename=None):
|
||||||
|
"""Create a Document instance."""
|
||||||
|
self.filename = filename
|
||||||
|
self.filepath = None
|
||||||
|
self.filedir = None
|
||||||
|
self.filebase = None
|
||||||
|
self.fileext = None
|
||||||
|
if self.filename:
|
||||||
|
self.filepath = os.path.abspath(self.filename)
|
||||||
|
self.filedir, self.filename = os.path.split(self.filepath)
|
||||||
|
self.filebase, self.fileext = os.path.splitext(self.filename)
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
"""Return contents of file."""
|
||||||
|
f = file(self.filepath, 'rb')
|
||||||
|
try:
|
||||||
|
return f.read()
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
def write(self, text):
|
||||||
|
"""Write text to file."""
|
||||||
|
try:
|
||||||
|
f = file(self.filepath, 'wb')
|
||||||
|
f.write(text)
|
||||||
|
finally:
|
||||||
|
if f:
|
||||||
|
f.close()
|
733
wxPython/wxPython/py/editor.py
Normal file
733
wxPython/wxPython/py/editor.py
Normal file
@@ -0,0 +1,733 @@
|
|||||||
|
"""PyAlaCarte and PyAlaMode editors."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
import base
|
||||||
|
import buffer
|
||||||
|
import crust
|
||||||
|
import dispatcher
|
||||||
|
import frame
|
||||||
|
import interpreter
|
||||||
|
import shell
|
||||||
|
import version
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class EditorFrame(frame.Frame):
|
||||||
|
"""Frame containing one editor."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1, title='PyAlaCarte',
|
||||||
|
pos=wx.wxDefaultPosition, size=(800, 600),
|
||||||
|
style=wx.wxDEFAULT_FRAME_STYLE, filename=None):
|
||||||
|
"""Create an EditorFrame instance."""
|
||||||
|
frame.Frame.__init__(self, parent, id, title, pos, size, style)
|
||||||
|
self._buffers = {}
|
||||||
|
self._buffer = None # Current buffer.
|
||||||
|
self.editor = None
|
||||||
|
self._statusText = title + ' - the tastiest Python editor.'
|
||||||
|
self.SetStatusText(self._statusText)
|
||||||
|
wx.EVT_IDLE(self, self.OnIdle)
|
||||||
|
self._setup()
|
||||||
|
if filename:
|
||||||
|
self.bufferCreate(filename)
|
||||||
|
|
||||||
|
def _setup(self):
|
||||||
|
"""Setup prior to first buffer creation.
|
||||||
|
|
||||||
|
Useful for subclasses."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def OnAbout(self, event):
|
||||||
|
"""Display an About window."""
|
||||||
|
title = 'About PyAlaCarte'
|
||||||
|
text = 'Another fine, flaky program.'
|
||||||
|
dialog = wx.wxMessageDialog(self, text, title,
|
||||||
|
wx.wxOK | wx.wxICON_INFORMATION)
|
||||||
|
dialog.ShowModal()
|
||||||
|
dialog.Destroy()
|
||||||
|
|
||||||
|
def OnClose(self, event):
|
||||||
|
"""Event handler for closing."""
|
||||||
|
for buffer in self._buffers.values():
|
||||||
|
self._buffer = buffer
|
||||||
|
if buffer.hasChanged():
|
||||||
|
cancel = self.bufferSuggestSave()
|
||||||
|
if cancel and event.CanVeto():
|
||||||
|
event.Veto()
|
||||||
|
return
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
def OnIdle(self, event):
|
||||||
|
"""Event handler for idle time."""
|
||||||
|
self._updateStatus()
|
||||||
|
self._updateTitle()
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
def _updateStatus(self):
|
||||||
|
"""Show current status information."""
|
||||||
|
if self._buffer:
|
||||||
|
status = self._buffer.getStatus()
|
||||||
|
text = 'File: %s | Line: %d | Column: %d' % status
|
||||||
|
if text != self._statusText:
|
||||||
|
self.SetStatusText(text)
|
||||||
|
self._statusText = text
|
||||||
|
|
||||||
|
def _updateTitle(self):
|
||||||
|
"""Show current title information."""
|
||||||
|
title = self.GetTitle()
|
||||||
|
if self.bufferHasChanged():
|
||||||
|
if title.startswith('* '):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.SetTitle('* ' + title)
|
||||||
|
else:
|
||||||
|
if title.startswith('* '):
|
||||||
|
self.SetTitle(title[2:])
|
||||||
|
|
||||||
|
def hasBuffer(self):
|
||||||
|
"""Return True if there is a current buffer."""
|
||||||
|
if self._buffer:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def bufferClose(self):
|
||||||
|
"""Close buffer."""
|
||||||
|
if self.bufferHasChanged():
|
||||||
|
cancel = self.bufferSuggestSave()
|
||||||
|
if cancel:
|
||||||
|
return cancel
|
||||||
|
self.bufferDestroy()
|
||||||
|
cancel = False
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
def bufferCreate(self, filename=None):
|
||||||
|
"""Create new buffer."""
|
||||||
|
self.bufferDestroy()
|
||||||
|
interp = interpreter.Interpreter(locals={})
|
||||||
|
self.editor = Editor(interp=interp, parent=self, filename=filename)
|
||||||
|
self._buffer = self.editor.buffer
|
||||||
|
self._buffers[self._buffer.id] = self._buffer
|
||||||
|
self._buffer.editor.SetFocus()
|
||||||
|
|
||||||
|
def bufferDestroy(self):
|
||||||
|
"""Destroy the current buffer."""
|
||||||
|
if self._buffer:
|
||||||
|
del self._buffers[self._buffer.id]
|
||||||
|
self._buffer = None
|
||||||
|
if self.editor:
|
||||||
|
self.editor.Destroy()
|
||||||
|
self.editor = None
|
||||||
|
|
||||||
|
def bufferHasChanged(self):
|
||||||
|
"""Return True if buffer has changed since last save."""
|
||||||
|
if self._buffer:
|
||||||
|
return self._buffer.hasChanged()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def bufferNew(self):
|
||||||
|
"""Create new buffer."""
|
||||||
|
if self.bufferHasChanged():
|
||||||
|
cancel = self.bufferSuggestSave()
|
||||||
|
if cancel:
|
||||||
|
return cancel
|
||||||
|
self.bufferCreate()
|
||||||
|
cancel = False
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
def bufferOpen(self):
|
||||||
|
"""Open file in buffer."""
|
||||||
|
if self.bufferHasChanged():
|
||||||
|
cancel = self.bufferSuggestSave()
|
||||||
|
if cancel:
|
||||||
|
return cancel
|
||||||
|
filedir = ''
|
||||||
|
if self._buffer and self._buffer.doc.filedir:
|
||||||
|
filedir = self._buffer.doc.filedir
|
||||||
|
result = openSingle(directory=filedir)
|
||||||
|
if result.path:
|
||||||
|
self.bufferCreate(result.path)
|
||||||
|
cancel = False
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
## def bufferPrint(self):
|
||||||
|
## """Print buffer."""
|
||||||
|
## pass
|
||||||
|
|
||||||
|
## def bufferRevert(self):
|
||||||
|
## """Revert buffer to version of file on disk."""
|
||||||
|
## pass
|
||||||
|
|
||||||
|
def bufferSave(self):
|
||||||
|
"""Save buffer to its file."""
|
||||||
|
if self._buffer.doc.filepath:
|
||||||
|
self._buffer.save()
|
||||||
|
cancel = False
|
||||||
|
else:
|
||||||
|
cancel = self.bufferSaveAs()
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
def bufferSaveAs(self):
|
||||||
|
"""Save buffer to a new filename."""
|
||||||
|
if self.bufferHasChanged() and self._buffer.doc.filepath:
|
||||||
|
cancel = self.bufferSuggestSave()
|
||||||
|
if cancel:
|
||||||
|
return cancel
|
||||||
|
filedir = ''
|
||||||
|
if self._buffer and self._buffer.doc.filedir:
|
||||||
|
filedir = self._buffer.doc.filedir
|
||||||
|
result = saveSingle(directory=filedir)
|
||||||
|
if result.path:
|
||||||
|
self._buffer.saveAs(result.path)
|
||||||
|
cancel = False
|
||||||
|
else:
|
||||||
|
cancel = True
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
def bufferSuggestSave(self):
|
||||||
|
"""Suggest saving changes. Return True if user selected Cancel."""
|
||||||
|
result = messageDialog(parent=None,
|
||||||
|
message='%s has changed.\n'
|
||||||
|
'Would you like to save it first'
|
||||||
|
'?' % self._buffer.name,
|
||||||
|
title='Save current file?')
|
||||||
|
if result.positive:
|
||||||
|
cancel = self.bufferSave()
|
||||||
|
else:
|
||||||
|
cancel = result.text == 'Cancel'
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
def updateNamespace(self):
|
||||||
|
"""Update the buffer namespace for autocompletion and calltips."""
|
||||||
|
if self._buffer.updateNamespace():
|
||||||
|
self.SetStatusText('Namespace updated')
|
||||||
|
else:
|
||||||
|
self.SetStatusText('Error executing, unable to update namespace')
|
||||||
|
|
||||||
|
|
||||||
|
class EditorNotebookFrame(EditorFrame):
|
||||||
|
"""Frame containing one or more editors in a notebook."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1, title='PyAlaMode',
|
||||||
|
pos=wx.wxDefaultPosition, size=(800, 600),
|
||||||
|
style=wx.wxDEFAULT_FRAME_STYLE, filename=None):
|
||||||
|
"""Create an EditorNotebookFrame instance."""
|
||||||
|
EditorFrame.__init__(self, parent, id, title, pos,
|
||||||
|
size, style, filename)
|
||||||
|
|
||||||
|
def _setup(self):
|
||||||
|
"""Setup prior to first buffer creation.
|
||||||
|
|
||||||
|
Useful for subclasses."""
|
||||||
|
self._notebook = BufferNotebook(parent=self)
|
||||||
|
dispatcher.connect(receiver=self._bufferChange,
|
||||||
|
signal='BufferChange', sender=self._notebook)
|
||||||
|
intro = 'PyCrust %s' % version.VERSION
|
||||||
|
import imp
|
||||||
|
module = imp.new_module('__main__')
|
||||||
|
import __builtin__
|
||||||
|
module.__dict__['__builtins__'] = __builtin__
|
||||||
|
namespace = module.__dict__.copy()
|
||||||
|
self.crust = crust.Crust(parent=self._notebook, intro=intro, locals=namespace)
|
||||||
|
self.shell = self.crust.shell
|
||||||
|
# Override the filling so that status messages go to the status bar.
|
||||||
|
self.crust.filling.tree.setStatusText = self.SetStatusText
|
||||||
|
# Override the shell so that status messages go to the status bar.
|
||||||
|
self.shell.setStatusText = self.SetStatusText
|
||||||
|
# Fix a problem with the sash shrinking to nothing.
|
||||||
|
self.crust.filling.SetSashPosition(200)
|
||||||
|
self._notebook.AddPage(page=self.crust, text='PyCrust', select=True)
|
||||||
|
self._buffer = self.crust.buffer
|
||||||
|
self._buffers[self._buffer.id] = self._buffer
|
||||||
|
self._buffer.editor.SetFocus()
|
||||||
|
|
||||||
|
def _bufferChange(self, buffer):
|
||||||
|
"""Buffer change signal receiver."""
|
||||||
|
self._buffer = buffer
|
||||||
|
|
||||||
|
def OnAbout(self, event):
|
||||||
|
"""Display an About window."""
|
||||||
|
title = 'About PyAlaMode'
|
||||||
|
text = 'Another fine, flaky program.'
|
||||||
|
dialog = wx.wxMessageDialog(self, text, title,
|
||||||
|
wx.wxOK | wx.wxICON_INFORMATION)
|
||||||
|
dialog.ShowModal()
|
||||||
|
dialog.Destroy()
|
||||||
|
|
||||||
|
def _updateTitle(self):
|
||||||
|
"""Show current title information."""
|
||||||
|
title = self.GetTitle()
|
||||||
|
if self.bufferHasChanged():
|
||||||
|
if title.startswith('* '):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.SetTitle('* ' + title)
|
||||||
|
else:
|
||||||
|
if title.startswith('* '):
|
||||||
|
self.SetTitle(title[2:])
|
||||||
|
|
||||||
|
def bufferCreate(self, filename=None):
|
||||||
|
"""Create new buffer."""
|
||||||
|
interp = interpreter.Interpreter(locals={})
|
||||||
|
editor = Editor(interp=interp, parent=self._notebook,
|
||||||
|
filename=filename)
|
||||||
|
self._buffer = editor.buffer
|
||||||
|
self._buffers[self._buffer.id] = self._buffer
|
||||||
|
self._notebook.AddPage(page=editor, text=self._buffer.name,
|
||||||
|
select=True)
|
||||||
|
self._buffer.editor.SetFocus()
|
||||||
|
|
||||||
|
def bufferDestroy(self):
|
||||||
|
"""Destroy the current buffer."""
|
||||||
|
selection = self._notebook.GetSelection()
|
||||||
|
## print "Destroy Selection:", selection
|
||||||
|
if selection > 0: # Don't destroy the PyCrust tab.
|
||||||
|
if self._buffer:
|
||||||
|
del self._buffers[self._buffer.id]
|
||||||
|
self._buffer = None # Do this before DeletePage().
|
||||||
|
self._notebook.DeletePage(selection)
|
||||||
|
|
||||||
|
def bufferNew(self):
|
||||||
|
"""Create new buffer."""
|
||||||
|
self.bufferCreate()
|
||||||
|
cancel = False
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
def bufferOpen(self):
|
||||||
|
"""Open file in buffer."""
|
||||||
|
filedir = ''
|
||||||
|
if self._buffer and self._buffer.doc.filedir:
|
||||||
|
filedir = self._buffer.doc.filedir
|
||||||
|
result = openMultiple(directory=filedir)
|
||||||
|
for path in result.paths:
|
||||||
|
self.bufferCreate(path)
|
||||||
|
cancel = False
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
|
||||||
|
class BufferNotebook(wx.wxNotebook):
|
||||||
|
"""A notebook containing a page for each buffer."""
|
||||||
|
|
||||||
|
def __init__(self, parent):
|
||||||
|
"""Create a BufferNotebook instance."""
|
||||||
|
wx.wxNotebook.__init__(self, parent, id=-1)
|
||||||
|
wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(), self.OnPageChanging)
|
||||||
|
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
||||||
|
|
||||||
|
def OnPageChanging(self, event):
|
||||||
|
"""Page changing event handler."""
|
||||||
|
## old = event.GetOldSelection()
|
||||||
|
## print "Changing from old:", old
|
||||||
|
## new = event.GetOldSelection()
|
||||||
|
## print "Changing to new:", new
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
def OnPageChanged(self, event):
|
||||||
|
"""Page changed event handler."""
|
||||||
|
## old = event.GetOldSelection()
|
||||||
|
## print "Changed from:", old
|
||||||
|
new = event.GetSelection()
|
||||||
|
## print "Changed to new:", new
|
||||||
|
page = self.GetPage(new)
|
||||||
|
buffer = page.buffer
|
||||||
|
buffer.editor.SetFocus()
|
||||||
|
dispatcher.send(signal='BufferChange', sender=self, buffer=buffer)
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
|
||||||
|
class BufferEditorShellNotebookFrame(EditorFrame):
|
||||||
|
"""Frame containing one or more editor notebooks."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1, title='PyAlaMode',
|
||||||
|
pos=wx.wxDefaultPosition, size=(600, 400),
|
||||||
|
style=wx.wxDEFAULT_FRAME_STYLE,
|
||||||
|
filename=None, singlefile=False):
|
||||||
|
"""Create a BufferEditorShellNotebookFrame instance."""
|
||||||
|
self._singlefile = singlefile
|
||||||
|
EditorFrame.__init__(self, parent, id, title, pos,
|
||||||
|
size, style, filename)
|
||||||
|
|
||||||
|
def _setup(self):
|
||||||
|
"""Setup prior to first buffer creation.
|
||||||
|
|
||||||
|
Useful for subclasses."""
|
||||||
|
if not self._singlefile:
|
||||||
|
self._notebook = BufferNotebook(parent=self)
|
||||||
|
dispatcher.connect(receiver=self._bufferChange,
|
||||||
|
signal='BufferChange', sender=self._notebook)
|
||||||
|
|
||||||
|
def _bufferChange(self, buffer):
|
||||||
|
"""Buffer change signal receiver."""
|
||||||
|
self._buffer = buffer
|
||||||
|
|
||||||
|
def OnAbout(self, event):
|
||||||
|
"""Display an About window."""
|
||||||
|
title = 'About PyAlaMode'
|
||||||
|
text = 'Another fine, flaky program.'
|
||||||
|
dialog = wx.wxMessageDialog(self, text, title,
|
||||||
|
wx.wxOK | wx.wxICON_INFORMATION)
|
||||||
|
dialog.ShowModal()
|
||||||
|
dialog.Destroy()
|
||||||
|
|
||||||
|
def _updateTitle(self):
|
||||||
|
"""Show current title information."""
|
||||||
|
title = self.GetTitle()
|
||||||
|
if self.bufferHasChanged():
|
||||||
|
if title.startswith('* '):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.SetTitle('* ' + title)
|
||||||
|
else:
|
||||||
|
if title.startswith('* '):
|
||||||
|
self.SetTitle(title[2:])
|
||||||
|
|
||||||
|
def bufferCreate(self, filename=None):
|
||||||
|
"""Create new buffer."""
|
||||||
|
if self._singlefile:
|
||||||
|
self.bufferDestroy()
|
||||||
|
notebook = self._notebook = EditorShellNotebook(parent=self,
|
||||||
|
filename=filename)
|
||||||
|
else:
|
||||||
|
notebook = EditorShellNotebook(parent=self._notebook,
|
||||||
|
filename=filename)
|
||||||
|
self._buffer = notebook.buffer
|
||||||
|
if not self._singlefile:
|
||||||
|
self._notebook.AddPage(page=notebook, text=self._buffer.name,
|
||||||
|
select=True)
|
||||||
|
self._buffers[self._buffer.id] = self._buffer
|
||||||
|
self._buffer.editor.SetFocus()
|
||||||
|
|
||||||
|
def bufferDestroy(self):
|
||||||
|
"""Destroy the current buffer."""
|
||||||
|
if self._buffer:
|
||||||
|
del self._buffers[self._buffer.id]
|
||||||
|
self._buffer = None # Do this before DeletePage().
|
||||||
|
if self._singlefile:
|
||||||
|
self._notebook.Destroy()
|
||||||
|
self._notebook = None
|
||||||
|
else:
|
||||||
|
selection = self._notebook.GetSelection()
|
||||||
|
print "Destroy Selection:", selection
|
||||||
|
self._notebook.DeletePage(selection)
|
||||||
|
|
||||||
|
def bufferNew(self):
|
||||||
|
"""Create new buffer."""
|
||||||
|
if self._singlefile and self.bufferHasChanged():
|
||||||
|
cancel = self.bufferSuggestSave()
|
||||||
|
if cancel:
|
||||||
|
return cancel
|
||||||
|
self.bufferCreate()
|
||||||
|
cancel = False
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
def bufferOpen(self):
|
||||||
|
"""Open file in buffer."""
|
||||||
|
if self._singlefile and self.bufferHasChanged():
|
||||||
|
cancel = self.bufferSuggestSave()
|
||||||
|
if cancel:
|
||||||
|
return cancel
|
||||||
|
filedir = ''
|
||||||
|
if self._buffer and self._buffer.doc.filedir:
|
||||||
|
filedir = self._buffer.doc.filedir
|
||||||
|
if self._singlefile:
|
||||||
|
result = openSingle(directory=filedir)
|
||||||
|
if result.path:
|
||||||
|
self.bufferCreate(result.path)
|
||||||
|
else:
|
||||||
|
result = openMultiple(directory=filedir)
|
||||||
|
for path in result.paths:
|
||||||
|
self.bufferCreate(path)
|
||||||
|
cancel = False
|
||||||
|
return cancel
|
||||||
|
|
||||||
|
|
||||||
|
class BufferEditorShellNotebook(wx.wxNotebook):
|
||||||
|
"""A notebook containing a page for each buffer."""
|
||||||
|
|
||||||
|
def __init__(self, parent):
|
||||||
|
"""Create a BufferEditorShellNotebook instance."""
|
||||||
|
wx.wxNotebook.__init__(self, parent, id=-1)
|
||||||
|
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
||||||
|
|
||||||
|
def OnPageChanged(self, event):
|
||||||
|
"""Page changed event handler."""
|
||||||
|
## old = event.GetOldSelection()
|
||||||
|
## print "Changed from old:", old
|
||||||
|
new = event.GetSelection()
|
||||||
|
## print "Changed to new:", new
|
||||||
|
page = self.GetPage(new)
|
||||||
|
buffer = page.buffer
|
||||||
|
subselection = page.GetSelection()
|
||||||
|
page.focus(subselection)
|
||||||
|
dispatcher.send(signal='BufferChange', sender=self, buffer=buffer)
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
|
||||||
|
class EditorShellNotebook(wx.wxNotebook):
|
||||||
|
"""A notebook containing an editor page and a shell page."""
|
||||||
|
|
||||||
|
def __init__(self, parent, filename=None):
|
||||||
|
"""Create an EditorShellNotebook instance."""
|
||||||
|
wx.wxNotebook.__init__(self, parent, id=-1)
|
||||||
|
usePanels = True
|
||||||
|
if usePanels:
|
||||||
|
shellparent = shellpanel = wx.wxPanel(self, -1)
|
||||||
|
editorparent = editorpanel = wx.wxPanel(self, -1)
|
||||||
|
else:
|
||||||
|
shellparent = self
|
||||||
|
editorparent = self
|
||||||
|
self.shell = shell.Shell(parent=shellparent,
|
||||||
|
style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER)
|
||||||
|
self.editor = Editor(interp=self.shell.interp, parent=editorparent,
|
||||||
|
filename=filename)
|
||||||
|
if usePanels:
|
||||||
|
self.AddPage(page=editorpanel, text='File', select=True)
|
||||||
|
self.AddPage(page=shellpanel, text='Shell')
|
||||||
|
# Setup sizers
|
||||||
|
shellsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||||
|
shellsizer.Add(self.shell, 1, wx.wxEXPAND)
|
||||||
|
shellpanel.SetSizer(shellsizer)
|
||||||
|
shellpanel.SetAutoLayout(True)
|
||||||
|
editorsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||||
|
editorsizer.Add(self.editor, 1, wx.wxEXPAND)
|
||||||
|
editorpanel.SetSizer(editorsizer)
|
||||||
|
editorpanel.SetAutoLayout(True)
|
||||||
|
else:
|
||||||
|
self.AddPage(page=self.editor, text='File', select=True)
|
||||||
|
self.AddPage(page=self.shell, text='Shell')
|
||||||
|
self.buffer = self.editor.buffer
|
||||||
|
self.editor.SetFocus()
|
||||||
|
wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
|
||||||
|
|
||||||
|
def OnPageChanged(self, event):
|
||||||
|
"""Page changed event handler."""
|
||||||
|
selection = event.GetSelection()
|
||||||
|
self.focus(selection)
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
def focus(self, selection):
|
||||||
|
if selection == 0:
|
||||||
|
self.editor.SetFocus()
|
||||||
|
else:
|
||||||
|
self.shell.SetFocus()
|
||||||
|
|
||||||
|
|
||||||
|
class Editor(base.Editor):
|
||||||
|
"""Editor based on StyledTextCtrl."""
|
||||||
|
|
||||||
|
def __init__(self, interp, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
|
size=wx.wxDefaultSize,
|
||||||
|
style=wx.wxCLIP_CHILDREN | wx.wxSUNKEN_BORDER,
|
||||||
|
filename=None):
|
||||||
|
"""Create a Editor instance."""
|
||||||
|
base.Editor.__init__(self, parent, id, pos, size, style)
|
||||||
|
self.interp = interp
|
||||||
|
# Find out for which keycodes the interpreter will autocomplete.
|
||||||
|
self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
|
||||||
|
# Assign handlers for keyboard events.
|
||||||
|
wx.EVT_CHAR(self, self.OnChar)
|
||||||
|
wx.EVT_KEY_DOWN(self, self.OnKeyDown)
|
||||||
|
self.buffer = buffer.Buffer(editor=self, interp=self.interp,
|
||||||
|
filename=filename)
|
||||||
|
|
||||||
|
def OnChar(self, event):
|
||||||
|
"""Keypress event handler.
|
||||||
|
|
||||||
|
Only receives an event if OnKeyDown calls event.Skip() for the
|
||||||
|
corresponding event."""
|
||||||
|
|
||||||
|
key = event.KeyCode()
|
||||||
|
if key in self.autoCompleteKeys:
|
||||||
|
# Usually the dot (period) key activates auto completion.
|
||||||
|
if self.AutoCompActive():
|
||||||
|
self.AutoCompCancel()
|
||||||
|
self.ReplaceSelection('')
|
||||||
|
self.AddText(chr(key))
|
||||||
|
text, pos = self.GetCurLine()
|
||||||
|
text = text[:pos]
|
||||||
|
if self.autoComplete:
|
||||||
|
self.autoCompleteShow(text)
|
||||||
|
elif key == ord('('):
|
||||||
|
# The left paren activates a call tip and cancels an
|
||||||
|
# active auto completion.
|
||||||
|
if self.AutoCompActive():
|
||||||
|
self.AutoCompCancel()
|
||||||
|
self.ReplaceSelection('')
|
||||||
|
self.AddText('(')
|
||||||
|
text, pos = self.GetCurLine()
|
||||||
|
text = text[:pos]
|
||||||
|
self.autoCallTipShow(text)
|
||||||
|
else:
|
||||||
|
# Allow the normal event handling to take place.
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
def OnKeyDown(self, event):
|
||||||
|
"""Key down event handler."""
|
||||||
|
|
||||||
|
key = event.KeyCode()
|
||||||
|
# If the auto-complete window is up let it do its thing.
|
||||||
|
if self.AutoCompActive():
|
||||||
|
event.Skip()
|
||||||
|
return
|
||||||
|
controlDown = event.ControlDown()
|
||||||
|
altDown = event.AltDown()
|
||||||
|
shiftDown = event.ShiftDown()
|
||||||
|
# Let Ctrl-Alt-* get handled normally.
|
||||||
|
if controlDown and altDown:
|
||||||
|
event.Skip()
|
||||||
|
# Increase font size.
|
||||||
|
elif controlDown and key in (ord(']'),):
|
||||||
|
dispatcher.send(signal='FontIncrease')
|
||||||
|
# Decrease font size.
|
||||||
|
elif controlDown and key in (ord('['),):
|
||||||
|
dispatcher.send(signal='FontDecrease')
|
||||||
|
# Default font size.
|
||||||
|
elif controlDown and key in (ord('='),):
|
||||||
|
dispatcher.send(signal='FontDefault')
|
||||||
|
else:
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
def autoCompleteShow(self, command):
|
||||||
|
"""Display auto-completion popup list."""
|
||||||
|
list = self.interp.getAutoCompleteList(command,
|
||||||
|
includeMagic=self.autoCompleteIncludeMagic,
|
||||||
|
includeSingle=self.autoCompleteIncludeSingle,
|
||||||
|
includeDouble=self.autoCompleteIncludeDouble)
|
||||||
|
if list and len(list) < 2000:
|
||||||
|
options = ' '.join(list)
|
||||||
|
offset = 0
|
||||||
|
self.AutoCompShow(offset, options)
|
||||||
|
|
||||||
|
def autoCallTipShow(self, command):
|
||||||
|
"""Display argument spec and docstring in a popup window."""
|
||||||
|
if self.CallTipActive():
|
||||||
|
self.CallTipCancel()
|
||||||
|
(name, argspec, tip) = self.interp.getCallTip(command)
|
||||||
|
if tip:
|
||||||
|
dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
|
||||||
|
if not self.autoCallTip:
|
||||||
|
return
|
||||||
|
if argspec:
|
||||||
|
startpos = self.GetCurrentPos()
|
||||||
|
self.AddText(argspec + ')')
|
||||||
|
endpos = self.GetCurrentPos()
|
||||||
|
self.SetSelection(endpos, startpos)
|
||||||
|
if tip:
|
||||||
|
curpos = self.GetCurrentPos()
|
||||||
|
size = len(name)
|
||||||
|
tippos = curpos - (size + 1)
|
||||||
|
fallback = curpos - self.GetColumn(curpos)
|
||||||
|
# In case there isn't enough room, only go back to the
|
||||||
|
# fallback.
|
||||||
|
tippos = max(tippos, fallback)
|
||||||
|
self.CallTipShow(tippos, tip)
|
||||||
|
self.CallTipSetHighlight(0, size)
|
||||||
|
|
||||||
|
|
||||||
|
class DialogResults:
|
||||||
|
"""DialogResults class."""
|
||||||
|
|
||||||
|
def __init__(self, returned):
|
||||||
|
"""Create a wrapper for the results returned by a dialog."""
|
||||||
|
self.returned = returned
|
||||||
|
self.positive = returned in (wx.wxID_OK, wx.wxID_YES)
|
||||||
|
self.text = self._asString()
|
||||||
|
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self.__dict__)
|
||||||
|
|
||||||
|
def _asString(self):
|
||||||
|
returned = self.returned
|
||||||
|
if returned == wx.wxID_OK:
|
||||||
|
return "Ok"
|
||||||
|
elif returned == wx.wxID_CANCEL:
|
||||||
|
return "Cancel"
|
||||||
|
elif returned == wx.wxID_YES:
|
||||||
|
return "Yes"
|
||||||
|
elif returned == wx.wxID_NO:
|
||||||
|
return "No"
|
||||||
|
|
||||||
|
|
||||||
|
def fileDialog(parent=None, title='Open', directory='', filename='',
|
||||||
|
wildcard='All Files (*.*)|*.*',
|
||||||
|
style=wx.wxOPEN | wx.wxMULTIPLE):
|
||||||
|
"""File dialog wrapper function."""
|
||||||
|
dialog = wx.wxFileDialog(parent, title, directory, filename,
|
||||||
|
wildcard, style)
|
||||||
|
result = DialogResults(dialog.ShowModal())
|
||||||
|
if result.positive:
|
||||||
|
result.paths = dialog.GetPaths()
|
||||||
|
else:
|
||||||
|
result.paths = []
|
||||||
|
dialog.Destroy()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def openSingle(parent=None, title='Open', directory='', filename='',
|
||||||
|
wildcard='All Files (*.*)|*.*', style=wx.wxOPEN):
|
||||||
|
"""File dialog wrapper function."""
|
||||||
|
dialog = wx.wxFileDialog(parent, title, directory, filename,
|
||||||
|
wildcard, style)
|
||||||
|
result = DialogResults(dialog.ShowModal())
|
||||||
|
if result.positive:
|
||||||
|
result.path = dialog.GetPath()
|
||||||
|
else:
|
||||||
|
result.path = None
|
||||||
|
dialog.Destroy()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def openMultiple(parent=None, title='Open', directory='', filename='',
|
||||||
|
wildcard='All Files (*.*)|*.*',
|
||||||
|
style=wx.wxOPEN | wx.wxMULTIPLE):
|
||||||
|
"""File dialog wrapper function."""
|
||||||
|
return fileDialog(parent, title, directory, filename, wildcard, style)
|
||||||
|
|
||||||
|
|
||||||
|
def saveSingle(parent=None, title='Save', directory='', filename='',
|
||||||
|
wildcard='All Files (*.*)|*.*',
|
||||||
|
style=wx.wxSAVE | wx.wxHIDE_READONLY | wx.wxOVERWRITE_PROMPT):
|
||||||
|
"""File dialog wrapper function."""
|
||||||
|
dialog = wx.wxFileDialog(parent, title, directory, filename,
|
||||||
|
wildcard, style)
|
||||||
|
result = DialogResults(dialog.ShowModal())
|
||||||
|
if result.positive:
|
||||||
|
result.path = dialog.GetPath()
|
||||||
|
else:
|
||||||
|
result.path = None
|
||||||
|
dialog.Destroy()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def directory(parent=None, message='Choose a directory', path='', style=0,
|
||||||
|
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize):
|
||||||
|
"""Dir dialog wrapper function."""
|
||||||
|
dialog = wx.wxDirDialog(parent, message, path, style, pos, size)
|
||||||
|
result = DialogResults(dialog.ShowModal())
|
||||||
|
if result.positive:
|
||||||
|
result.path = dialog.GetPath()
|
||||||
|
else:
|
||||||
|
result.path = None
|
||||||
|
dialog.Destroy()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def messageDialog(parent=None, message='', title='Message box',
|
||||||
|
style=wx.wxYES_NO | wx.wxCANCEL | wx.wxCENTRE | wx.wxICON_QUESTION,
|
||||||
|
pos=wx.wxDefaultPosition):
|
||||||
|
"""Message dialog wrapper function."""
|
||||||
|
dialog = wx.wxMessageDialog(parent, message, title, style, pos)
|
||||||
|
result = DialogResults(dialog.ShowModal())
|
||||||
|
dialog.Destroy()
|
||||||
|
return result
|
335
wxPython/wxPython/py/filling.py
Normal file
335
wxPython/wxPython/py/filling.py
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
"""PyCrust Filling is the gui tree control through which a user can
|
||||||
|
navigate the local namespace or any object."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
|
||||||
|
import base
|
||||||
|
import dispatcher
|
||||||
|
import inspect
|
||||||
|
import introspect
|
||||||
|
import keyword
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
from version import VERSION
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
COMMONTYPES = [getattr(types, t) for t in dir(types) \
|
||||||
|
if not t.startswith('_') \
|
||||||
|
and t not in ('ClassType', 'InstanceType', 'ModuleType')]
|
||||||
|
|
||||||
|
DOCTYPES = ('BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
|
||||||
|
'FunctionType', 'GeneratorType', 'InstanceType',
|
||||||
|
'LambdaType', 'MethodType', 'ModuleType',
|
||||||
|
'UnboundMethodType', 'method-wrapper')
|
||||||
|
|
||||||
|
SIMPLETYPES = [getattr(types, t) for t in dir(types) \
|
||||||
|
if not t.startswith('_') and t not in DOCTYPES]
|
||||||
|
|
||||||
|
try:
|
||||||
|
COMMONTYPES.append(type(''.__repr__)) # Method-wrapper in version 2.2.x.
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FillingTree(wx.wxTreeCtrl):
|
||||||
|
"""PyCrust FillingTree based on wxTreeCtrl."""
|
||||||
|
|
||||||
|
name = 'PyCrust Filling Tree'
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
|
size=wx.wxDefaultSize, style=wx.wxTR_DEFAULT_STYLE,
|
||||||
|
rootObject=None, rootLabel=None, rootIsNamespace=False,
|
||||||
|
static=False):
|
||||||
|
"""Create a PyCrust FillingTree instance."""
|
||||||
|
wx.wxTreeCtrl.__init__(self, parent, id, pos, size, style)
|
||||||
|
self.rootIsNamespace = rootIsNamespace
|
||||||
|
import __main__
|
||||||
|
if rootObject is None:
|
||||||
|
rootObject = __main__.__dict__
|
||||||
|
self.rootIsNamespace = True
|
||||||
|
if rootObject is __main__.__dict__ and rootLabel is None:
|
||||||
|
rootLabel = 'locals()'
|
||||||
|
if not rootLabel:
|
||||||
|
rootLabel = 'Ingredients'
|
||||||
|
rootData = wx.wxTreeItemData(rootObject)
|
||||||
|
self.item = self.root = self.AddRoot(rootLabel, -1, -1, rootData)
|
||||||
|
self.SetItemHasChildren(self.root, self.objHasChildren(rootObject))
|
||||||
|
wx.EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
|
||||||
|
wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
|
||||||
|
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
||||||
|
wx.EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated)
|
||||||
|
if not static:
|
||||||
|
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
||||||
|
|
||||||
|
def push(self, command, more):
|
||||||
|
"""Receiver for Interpreter.push signal."""
|
||||||
|
self.display()
|
||||||
|
|
||||||
|
def OnItemExpanding(self, event):
|
||||||
|
"""Add children to the item."""
|
||||||
|
busy = wx.wxBusyCursor()
|
||||||
|
item = event.GetItem()
|
||||||
|
if self.IsExpanded(item):
|
||||||
|
return
|
||||||
|
self.addChildren(item)
|
||||||
|
# self.SelectItem(item)
|
||||||
|
|
||||||
|
def OnItemCollapsed(self, event):
|
||||||
|
"""Remove all children from the item."""
|
||||||
|
busy = wx.wxBusyCursor()
|
||||||
|
item = event.GetItem()
|
||||||
|
# self.CollapseAndReset(item)
|
||||||
|
# self.DeleteChildren(item)
|
||||||
|
# self.SelectItem(item)
|
||||||
|
|
||||||
|
def OnSelChanged(self, event):
|
||||||
|
"""Display information about the item."""
|
||||||
|
busy = wx.wxBusyCursor()
|
||||||
|
self.item = event.GetItem()
|
||||||
|
self.display()
|
||||||
|
|
||||||
|
def OnItemActivated(self, event):
|
||||||
|
"""Launch a DirFrame."""
|
||||||
|
item = event.GetItem()
|
||||||
|
text = self.getFullName(item)
|
||||||
|
obj = self.GetPyData(item)
|
||||||
|
frame = FillingFrame(parent=self, size=(600, 100), rootObject=obj,
|
||||||
|
rootLabel=text, rootIsNamespace=False)
|
||||||
|
frame.Show()
|
||||||
|
|
||||||
|
def objHasChildren(self, obj):
|
||||||
|
"""Return true if object has children."""
|
||||||
|
if self.objGetChildren(obj):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def objGetChildren(self, obj):
|
||||||
|
"""Return dictionary with attributes or contents of object."""
|
||||||
|
busy = wx.wxBusyCursor()
|
||||||
|
otype = type(obj)
|
||||||
|
if otype is types.DictType \
|
||||||
|
or str(otype)[17:23] == 'BTrees' and hasattr(obj, 'keys'):
|
||||||
|
return obj
|
||||||
|
d = {}
|
||||||
|
if otype is types.ListType or otype is types.TupleType:
|
||||||
|
for n in range(len(obj)):
|
||||||
|
key = '[' + str(n) + ']'
|
||||||
|
d[key] = obj[n]
|
||||||
|
if otype not in COMMONTYPES:
|
||||||
|
for key in introspect.getAttributeNames(obj):
|
||||||
|
# Believe it or not, some attributes can disappear,
|
||||||
|
# such as the exc_traceback attribute of the sys
|
||||||
|
# module. So this is nested in a try block.
|
||||||
|
try:
|
||||||
|
d[key] = getattr(obj, key)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return d
|
||||||
|
|
||||||
|
def addChildren(self, item):
|
||||||
|
self.DeleteChildren(item)
|
||||||
|
obj = self.GetPyData(item)
|
||||||
|
children = self.objGetChildren(obj)
|
||||||
|
if not children:
|
||||||
|
return
|
||||||
|
keys = children.keys()
|
||||||
|
keys.sort(lambda x, y: cmp(x.lower(), y.lower()))
|
||||||
|
for key in keys:
|
||||||
|
itemtext = str(key)
|
||||||
|
# Show string dictionary items with single quotes, except
|
||||||
|
# for the first level of items, if they represent a
|
||||||
|
# namespace.
|
||||||
|
if type(obj) is types.DictType \
|
||||||
|
and type(key) is types.StringType \
|
||||||
|
and (item != self.root \
|
||||||
|
or (item == self.root and not self.rootIsNamespace)):
|
||||||
|
itemtext = repr(key)
|
||||||
|
child = children[key]
|
||||||
|
data = wx.wxTreeItemData(child)
|
||||||
|
branch = self.AppendItem(parent=item, text=itemtext, data=data)
|
||||||
|
self.SetItemHasChildren(branch, self.objHasChildren(child))
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
item = self.item
|
||||||
|
if self.IsExpanded(item):
|
||||||
|
self.addChildren(item)
|
||||||
|
self.setText('')
|
||||||
|
obj = self.GetPyData(item)
|
||||||
|
if wx.wxPlatform == '__WXMSW__':
|
||||||
|
if obj is None: # Windows bug fix.
|
||||||
|
return
|
||||||
|
self.SetItemHasChildren(item, self.objHasChildren(obj))
|
||||||
|
otype = type(obj)
|
||||||
|
text = ''
|
||||||
|
text += self.getFullName(item)
|
||||||
|
text += '\n\nType: ' + str(otype)
|
||||||
|
try:
|
||||||
|
value = str(obj)
|
||||||
|
except:
|
||||||
|
value = ''
|
||||||
|
if otype is types.StringType or otype is types.UnicodeType:
|
||||||
|
value = repr(obj)
|
||||||
|
text += '\n\nValue: ' + value
|
||||||
|
if otype not in SIMPLETYPES:
|
||||||
|
try:
|
||||||
|
text += '\n\nDocstring:\n\n"""' + \
|
||||||
|
inspect.getdoc(obj).strip() + '"""'
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if otype is types.InstanceType:
|
||||||
|
try:
|
||||||
|
text += '\n\nClass Definition:\n\n' + \
|
||||||
|
inspect.getsource(obj.__class__)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
text += '\n\nSource Code:\n\n' + \
|
||||||
|
inspect.getsource(obj)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.setText(text)
|
||||||
|
|
||||||
|
def getFullName(self, item, partial=''):
|
||||||
|
"""Return a syntactically proper name for item."""
|
||||||
|
name = self.GetItemText(item)
|
||||||
|
parent = None
|
||||||
|
obj = None
|
||||||
|
if item != self.root:
|
||||||
|
parent = self.GetItemParent(item)
|
||||||
|
obj = self.GetPyData(parent)
|
||||||
|
# Apply dictionary syntax to dictionary items, except the root
|
||||||
|
# and first level children of a namepace.
|
||||||
|
if (type(obj) is types.DictType \
|
||||||
|
or str(type(obj))[17:23] == 'BTrees' \
|
||||||
|
and hasattr(obj, 'keys')) \
|
||||||
|
and ((item != self.root and parent != self.root) \
|
||||||
|
or (parent == self.root and not self.rootIsNamespace)):
|
||||||
|
name = '[' + name + ']'
|
||||||
|
# Apply dot syntax to multipart names.
|
||||||
|
if partial:
|
||||||
|
if partial[0] == '[':
|
||||||
|
name += partial
|
||||||
|
else:
|
||||||
|
name += '.' + partial
|
||||||
|
# Repeat for everything but the root item
|
||||||
|
# and first level children of a namespace.
|
||||||
|
if (item != self.root and parent != self.root) \
|
||||||
|
or (parent == self.root and not self.rootIsNamespace):
|
||||||
|
name = self.getFullName(parent, partial=name)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def setText(self, text):
|
||||||
|
"""Display information about the current selection."""
|
||||||
|
|
||||||
|
# This method will likely be replaced by the enclosing app to
|
||||||
|
# do something more interesting, like write to a text control.
|
||||||
|
print text
|
||||||
|
|
||||||
|
def setStatusText(self, text):
|
||||||
|
"""Display status information."""
|
||||||
|
|
||||||
|
# This method will likely be replaced by the enclosing app to
|
||||||
|
# do something more interesting, like write to a status bar.
|
||||||
|
print text
|
||||||
|
|
||||||
|
|
||||||
|
class FillingText(base.Editor):
|
||||||
|
"""FillingText based on StyledTextCtrl."""
|
||||||
|
|
||||||
|
name = 'PyFilling Text'
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
|
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN,
|
||||||
|
static=False):
|
||||||
|
"""Create a FillingText instance."""
|
||||||
|
base.Editor.__init__(self, parent, id, pos, size, style)
|
||||||
|
# Configure various defaults and user preferences.
|
||||||
|
self.SetReadOnly(True)
|
||||||
|
self.SetWrapMode(True)
|
||||||
|
self.SetMarginWidth(1, 0)
|
||||||
|
if not static:
|
||||||
|
dispatcher.connect(receiver=self.push, signal='Interpreter.push')
|
||||||
|
|
||||||
|
def push(self, command, more):
|
||||||
|
"""Receiver for Interpreter.push signal."""
|
||||||
|
self.Refresh()
|
||||||
|
|
||||||
|
def SetText(self, *args, **kwds):
|
||||||
|
self.SetReadOnly(False)
|
||||||
|
base.Editor.SetText(self, *args, **kwds)
|
||||||
|
self.SetReadOnly(True)
|
||||||
|
|
||||||
|
|
||||||
|
class Filling(wx.wxSplitterWindow):
|
||||||
|
"""Filling based on wxSplitterWindow."""
|
||||||
|
|
||||||
|
name = 'PyFilling'
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
|
size=wx.wxDefaultSize, style=wx.wxSP_3D,
|
||||||
|
name='Filling Window', rootObject=None,
|
||||||
|
rootLabel=None, rootIsNamespace=False, static=False):
|
||||||
|
"""Create a Filling instance."""
|
||||||
|
wx.wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
||||||
|
self.tree = FillingTree(parent=self, rootObject=rootObject,
|
||||||
|
rootLabel=rootLabel,
|
||||||
|
rootIsNamespace=rootIsNamespace,
|
||||||
|
static=static)
|
||||||
|
self.text = FillingText(parent=self, static=static)
|
||||||
|
self.SplitVertically(self.tree, self.text, 130)
|
||||||
|
self.SetMinimumPaneSize(1)
|
||||||
|
# Override the filling so that descriptions go to FillingText.
|
||||||
|
self.tree.setText = self.text.SetText
|
||||||
|
# Display the root item.
|
||||||
|
## self.tree.SelectItem(self.tree.root)
|
||||||
|
self.tree.display()
|
||||||
|
|
||||||
|
|
||||||
|
class FillingFrame(wx.wxFrame):
|
||||||
|
"""Frame containing the namespace tree component."""
|
||||||
|
|
||||||
|
name = 'PyFilling Frame'
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1, title='PyFilling',
|
||||||
|
pos=wx.wxDefaultPosition, size=(600, 400),
|
||||||
|
style=wx.wxDEFAULT_FRAME_STYLE, rootObject=None,
|
||||||
|
rootLabel=None, rootIsNamespace=False, static=False):
|
||||||
|
"""Create a FillingFrame instance."""
|
||||||
|
wx.wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||||
|
intro = 'PyFilling - The Tastiest Namespace Inspector'
|
||||||
|
self.CreateStatusBar()
|
||||||
|
self.SetStatusText(intro)
|
||||||
|
import images
|
||||||
|
self.SetIcon(images.getPyCrustIcon())
|
||||||
|
self.filling = Filling(parent=self, rootObject=rootObject,
|
||||||
|
rootLabel=rootLabel,
|
||||||
|
rootIsNamespace=rootIsNamespace,
|
||||||
|
static=static)
|
||||||
|
# Override so that status messages go to the status bar.
|
||||||
|
self.filling.tree.setStatusText = self.SetStatusText
|
||||||
|
|
||||||
|
|
||||||
|
class App(wx.wxApp):
|
||||||
|
"""PyFilling standalone application."""
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
wx.wxInitAllImageHandlers()
|
||||||
|
self.fillingFrame = FillingFrame()
|
||||||
|
self.fillingFrame.Show(True)
|
||||||
|
self.SetTopWindow(self.fillingFrame)
|
||||||
|
return True
|
348
wxPython/wxPython/py/frame.py
Normal file
348
wxPython/wxPython/py/frame.py
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
"""Base frame with menu."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
from version import VERSION
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
ID_NEW = wx.wxID_NEW
|
||||||
|
ID_OPEN = wx.wxID_OPEN
|
||||||
|
ID_REVERT = wx.wxID_REVERT
|
||||||
|
ID_CLOSE = wx.wxID_CLOSE
|
||||||
|
ID_SAVE = wx.wxID_SAVE
|
||||||
|
ID_SAVEAS = wx.wxID_SAVEAS
|
||||||
|
ID_PRINT = wx.wxID_PRINT
|
||||||
|
ID_EXIT = wx.wxID_EXIT
|
||||||
|
ID_UNDO = wx.wxID_UNDO
|
||||||
|
ID_REDO = wx.wxID_REDO
|
||||||
|
ID_CUT = wx.wxID_CUT
|
||||||
|
ID_COPY = wx.wxID_COPY
|
||||||
|
ID_PASTE = wx.wxID_PASTE
|
||||||
|
ID_CLEAR = wx.wxID_CLEAR
|
||||||
|
ID_SELECTALL = wx.wxID_SELECTALL
|
||||||
|
ID_ABOUT = wx.wxID_ABOUT
|
||||||
|
ID_AUTOCOMP = wx.wxNewId()
|
||||||
|
ID_AUTOCOMP_SHOW = wx.wxNewId()
|
||||||
|
ID_AUTOCOMP_MAGIC = wx.wxNewId()
|
||||||
|
ID_AUTOCOMP_SINGLE = wx.wxNewId()
|
||||||
|
ID_AUTOCOMP_DOUBLE = wx.wxNewId()
|
||||||
|
ID_CALLTIPS = wx.wxNewId()
|
||||||
|
ID_CALLTIPS_SHOW = wx.wxNewId()
|
||||||
|
ID_COPY_PLUS = wx.wxNewId()
|
||||||
|
ID_NAMESPACE = wx.wxNewId()
|
||||||
|
ID_PASTE_PLUS = wx.wxNewId()
|
||||||
|
ID_WRAP = wx.wxNewId()
|
||||||
|
|
||||||
|
|
||||||
|
class Frame(wx.wxFrame):
|
||||||
|
"""Frame with standard menu items."""
|
||||||
|
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1, title='Editor',
|
||||||
|
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize,
|
||||||
|
style=wx.wxDEFAULT_FRAME_STYLE):
|
||||||
|
"""Create a Frame instance."""
|
||||||
|
wx.wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||||
|
self.CreateStatusBar()
|
||||||
|
self.SetStatusText('Frame')
|
||||||
|
import images
|
||||||
|
self.SetIcon(images.getPyCrustIcon())
|
||||||
|
self.__createMenus()
|
||||||
|
wx.EVT_CLOSE(self, self.OnClose)
|
||||||
|
|
||||||
|
def OnClose(self, event):
|
||||||
|
"""Event handler for closing."""
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
def __createMenus(self):
|
||||||
|
m = self.fileMenu = wx.wxMenu()
|
||||||
|
m.Append(ID_NEW, '&New \tCtrl+N',
|
||||||
|
'New file')
|
||||||
|
m.Append(ID_OPEN, '&Open... \tCtrl+O',
|
||||||
|
'Open file')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_REVERT, '&Revert \tCtrl+R',
|
||||||
|
'Revert to last saved version')
|
||||||
|
m.Append(ID_CLOSE, '&Close \tCtrl+W',
|
||||||
|
'Close file')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_SAVE, '&Save... \tCtrl+S',
|
||||||
|
'Save file')
|
||||||
|
m.Append(ID_SAVEAS, 'Save &As \tShift+Ctrl+S',
|
||||||
|
'Save file with new name')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_PRINT, '&Print... \tCtrl+P',
|
||||||
|
'Print file')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_NAMESPACE, '&Update Namespace \tShift+Ctrl+N',
|
||||||
|
'Update namespace for autocompletion and calltips')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_EXIT, 'E&xit', 'Exit Program')
|
||||||
|
|
||||||
|
m = self.editMenu = wx.wxMenu()
|
||||||
|
m.Append(ID_UNDO, '&Undo \tCtrl+Z',
|
||||||
|
'Undo the last action')
|
||||||
|
m.Append(ID_REDO, '&Redo \tCtrl+Y',
|
||||||
|
'Redo the last undone action')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_CUT, 'Cu&t \tCtrl+X',
|
||||||
|
'Cut the selection')
|
||||||
|
m.Append(ID_COPY, '&Copy \tCtrl+C',
|
||||||
|
'Copy the selection')
|
||||||
|
m.Append(ID_COPY_PLUS, 'Cop&y Plus \tShift+Ctrl+C',
|
||||||
|
'Copy the selection - retaining prompts')
|
||||||
|
m.Append(ID_PASTE, '&Paste \tCtrl+V', 'Paste from clipboard')
|
||||||
|
m.Append(ID_PASTE_PLUS, 'Past&e Plus \tShift+Ctrl+V',
|
||||||
|
'Paste and run commands')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_CLEAR, 'Cle&ar',
|
||||||
|
'Delete the selection')
|
||||||
|
m.Append(ID_SELECTALL, 'Select A&ll \tCtrl+A',
|
||||||
|
'Select all text')
|
||||||
|
|
||||||
|
m = self.autocompMenu = wx.wxMenu()
|
||||||
|
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion',
|
||||||
|
'Show auto completion list', 1)
|
||||||
|
m.Append(ID_AUTOCOMP_MAGIC, 'Include Magic Attributes',
|
||||||
|
'Include attributes visible to __getattr__ and __setattr__',
|
||||||
|
1)
|
||||||
|
m.Append(ID_AUTOCOMP_SINGLE, 'Include Single Underscores',
|
||||||
|
'Include attibutes prefixed by a single underscore', 1)
|
||||||
|
m.Append(ID_AUTOCOMP_DOUBLE, 'Include Double Underscores',
|
||||||
|
'Include attibutes prefixed by a double underscore', 1)
|
||||||
|
|
||||||
|
m = self.calltipsMenu = wx.wxMenu()
|
||||||
|
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips',
|
||||||
|
'Show call tips with argument signature and docstring', 1)
|
||||||
|
|
||||||
|
m = self.optionsMenu = wx.wxMenu()
|
||||||
|
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu,
|
||||||
|
'Auto Completion Options')
|
||||||
|
m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu,
|
||||||
|
'Call Tip Options')
|
||||||
|
m.Append(ID_WRAP, '&Wrap Lines',
|
||||||
|
'Wrap lines at right edge', 1)
|
||||||
|
|
||||||
|
m = self.helpMenu = wx.wxMenu()
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(ID_ABOUT, '&About...', 'About this program')
|
||||||
|
|
||||||
|
b = self.menuBar = wx.wxMenuBar()
|
||||||
|
b.Append(self.fileMenu, '&File')
|
||||||
|
b.Append(self.editMenu, '&Edit')
|
||||||
|
b.Append(self.optionsMenu, '&Options')
|
||||||
|
b.Append(self.helpMenu, '&Help')
|
||||||
|
self.SetMenuBar(b)
|
||||||
|
|
||||||
|
wx.EVT_MENU(self, ID_NEW, self.OnFileNew)
|
||||||
|
wx.EVT_MENU(self, ID_OPEN, self.OnFileOpen)
|
||||||
|
wx.EVT_MENU(self, ID_REVERT, self.OnFileRevert)
|
||||||
|
wx.EVT_MENU(self, ID_CLOSE, self.OnFileClose)
|
||||||
|
wx.EVT_MENU(self, ID_SAVE, self.OnFileSave)
|
||||||
|
wx.EVT_MENU(self, ID_SAVEAS, self.OnFileSaveAs)
|
||||||
|
wx.EVT_MENU(self, ID_NAMESPACE, self.OnFileUpdateNamespace)
|
||||||
|
wx.EVT_MENU(self, ID_PRINT, self.OnFilePrint)
|
||||||
|
wx.EVT_MENU(self, ID_EXIT, self.OnExit)
|
||||||
|
wx.EVT_MENU(self, ID_UNDO, self.OnUndo)
|
||||||
|
wx.EVT_MENU(self, ID_REDO, self.OnRedo)
|
||||||
|
wx.EVT_MENU(self, ID_CUT, self.OnCut)
|
||||||
|
wx.EVT_MENU(self, ID_COPY, self.OnCopy)
|
||||||
|
wx.EVT_MENU(self, ID_COPY_PLUS, self.OnCopyPlus)
|
||||||
|
wx.EVT_MENU(self, ID_PASTE, self.OnPaste)
|
||||||
|
wx.EVT_MENU(self, ID_PASTE_PLUS, self.OnPastePlus)
|
||||||
|
wx.EVT_MENU(self, ID_CLEAR, self.OnClear)
|
||||||
|
wx.EVT_MENU(self, ID_SELECTALL, self.OnSelectAll)
|
||||||
|
wx.EVT_MENU(self, ID_ABOUT, self.OnAbout)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_SHOW, self.OnAutoCompleteShow)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_MAGIC, self.OnAutoCompleteMagic)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_SINGLE, self.OnAutoCompleteSingle)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_DOUBLE, self.OnAutoCompleteDouble)
|
||||||
|
wx.EVT_MENU(self, ID_CALLTIPS_SHOW, self.OnCallTipsShow)
|
||||||
|
wx.EVT_MENU(self, ID_WRAP, self.OnWrap)
|
||||||
|
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_NEW, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_OPEN, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_REVERT, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_CLOSE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_SAVE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_SAVEAS, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_NAMESPACE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_PRINT, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_UNDO, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_REDO, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_CUT, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_COPY, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_COPY_PLUS, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_PASTE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_PASTE_PLUS, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_CLEAR, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_SELECTALL, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SHOW, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_MAGIC, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SINGLE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_DOUBLE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_CALLTIPS_SHOW, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_WRAP, self.OnUpdateMenu)
|
||||||
|
|
||||||
|
def OnFileNew(self, event):
|
||||||
|
self.bufferNew()
|
||||||
|
|
||||||
|
def OnFileOpen(self, event):
|
||||||
|
self.bufferOpen()
|
||||||
|
|
||||||
|
def OnFileRevert(self, event):
|
||||||
|
self.bufferRevert()
|
||||||
|
|
||||||
|
def OnFileClose(self, event):
|
||||||
|
self.bufferClose()
|
||||||
|
|
||||||
|
def OnFileSave(self, event):
|
||||||
|
self.bufferSave()
|
||||||
|
|
||||||
|
def OnFileSaveAs(self, event):
|
||||||
|
self.bufferSaveAs()
|
||||||
|
|
||||||
|
def OnFileUpdateNamespace(self, event):
|
||||||
|
self.updateNamespace()
|
||||||
|
|
||||||
|
def OnFilePrint(self, event):
|
||||||
|
self.bufferPrint()
|
||||||
|
|
||||||
|
def OnExit(self, event):
|
||||||
|
self.Close(False)
|
||||||
|
|
||||||
|
def OnUndo(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.Undo()
|
||||||
|
|
||||||
|
def OnRedo(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.Redo()
|
||||||
|
|
||||||
|
def OnCut(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.Cut()
|
||||||
|
|
||||||
|
def OnCopy(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.Copy()
|
||||||
|
|
||||||
|
def OnCopyPlus(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.CopyWithPrompts()
|
||||||
|
|
||||||
|
def OnPaste(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.Paste()
|
||||||
|
|
||||||
|
def OnPastePlus(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.PasteAndRun()
|
||||||
|
|
||||||
|
def OnClear(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.Clear()
|
||||||
|
|
||||||
|
def OnSelectAll(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.SelectAll()
|
||||||
|
|
||||||
|
def OnAbout(self, event):
|
||||||
|
"""Display an About window."""
|
||||||
|
title = 'About'
|
||||||
|
text = 'Your message here.'
|
||||||
|
dialog = wx.wxMessageDialog(self, text, title,
|
||||||
|
wx.wxOK | wx.wxICON_INFORMATION)
|
||||||
|
dialog.ShowModal()
|
||||||
|
dialog.Destroy()
|
||||||
|
|
||||||
|
def OnAutoCompleteShow(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.autoComplete = event.IsChecked()
|
||||||
|
|
||||||
|
def OnAutoCompleteMagic(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.autoCompleteIncludeMagic = event.IsChecked()
|
||||||
|
|
||||||
|
def OnAutoCompleteSingle(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.autoCompleteIncludeSingle = event.IsChecked()
|
||||||
|
|
||||||
|
def OnAutoCompleteDouble(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.autoCompleteIncludeDouble = event.IsChecked()
|
||||||
|
|
||||||
|
def OnCallTipsShow(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.autoCallTip = event.IsChecked()
|
||||||
|
|
||||||
|
def OnWrap(self, event):
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
win.SetWrapMode(event.IsChecked())
|
||||||
|
|
||||||
|
def OnUpdateMenu(self, event):
|
||||||
|
"""Update menu items based on current status and context."""
|
||||||
|
win = wx.wxWindow_FindFocus()
|
||||||
|
id = event.GetId()
|
||||||
|
event.Enable(True)
|
||||||
|
try:
|
||||||
|
if id == ID_NEW:
|
||||||
|
event.Enable(hasattr(self, 'bufferNew'))
|
||||||
|
elif id == ID_OPEN:
|
||||||
|
event.Enable(hasattr(self, 'bufferOpen'))
|
||||||
|
elif id == ID_REVERT:
|
||||||
|
event.Enable(hasattr(self, 'bufferRevert') and self.hasBuffer())
|
||||||
|
elif id == ID_CLOSE:
|
||||||
|
event.Enable(hasattr(self, 'bufferClose') and self.hasBuffer())
|
||||||
|
elif id == ID_SAVE:
|
||||||
|
event.Enable(hasattr(self, 'bufferSave') and self.bufferHasChanged())
|
||||||
|
elif id == ID_SAVEAS:
|
||||||
|
event.Enable(hasattr(self, 'bufferSaveAs') and self.hasBuffer())
|
||||||
|
elif id == ID_NAMESPACE:
|
||||||
|
event.Enable(hasattr(self, 'updateNamespace') and self.hasBuffer())
|
||||||
|
elif id == ID_PRINT:
|
||||||
|
event.Enable(hasattr(self, 'bufferPrint') and self.hasBuffer())
|
||||||
|
elif id == ID_UNDO:
|
||||||
|
event.Enable(win.CanUndo())
|
||||||
|
elif id == ID_REDO:
|
||||||
|
event.Enable(win.CanRedo())
|
||||||
|
elif id == ID_CUT:
|
||||||
|
event.Enable(win.CanCut())
|
||||||
|
elif id == ID_COPY:
|
||||||
|
event.Enable(win.CanCopy())
|
||||||
|
elif id == ID_COPY_PLUS:
|
||||||
|
event.Enable(win.CanCopy() and hasattr(win, 'CopyWithPrompts'))
|
||||||
|
elif id == ID_PASTE:
|
||||||
|
event.Enable(win.CanPaste())
|
||||||
|
elif id == ID_PASTE_PLUS:
|
||||||
|
event.Enable(win.CanPaste() and hasattr(win, 'PasteAndRun'))
|
||||||
|
elif id == ID_CLEAR:
|
||||||
|
event.Enable(win.CanCut())
|
||||||
|
elif id == ID_SELECTALL:
|
||||||
|
event.Enable(hasattr(win, 'SelectAll'))
|
||||||
|
elif id == ID_AUTOCOMP_SHOW:
|
||||||
|
event.Check(win.autoComplete)
|
||||||
|
elif id == ID_AUTOCOMP_MAGIC:
|
||||||
|
event.Check(win.autoCompleteIncludeMagic)
|
||||||
|
elif id == ID_AUTOCOMP_SINGLE:
|
||||||
|
event.Check(win.autoCompleteIncludeSingle)
|
||||||
|
elif id == ID_AUTOCOMP_DOUBLE:
|
||||||
|
event.Check(win.autoCompleteIncludeDouble)
|
||||||
|
elif id == ID_CALLTIPS_SHOW:
|
||||||
|
event.Check(win.autoCallTip)
|
||||||
|
elif id == ID_WRAP:
|
||||||
|
event.Check(win.GetWrapMode())
|
||||||
|
else:
|
||||||
|
event.Enable(False)
|
||||||
|
except AttributeError:
|
||||||
|
# This menu option is not supported in the current context.
|
||||||
|
event.Enable(False)
|
@@ -9,6 +9,7 @@ from __future__ import nested_scopes
|
|||||||
|
|
||||||
import cStringIO
|
import cStringIO
|
||||||
import inspect
|
import inspect
|
||||||
|
import sys
|
||||||
import tokenize
|
import tokenize
|
||||||
import types
|
import types
|
||||||
|
|
||||||
@@ -200,6 +201,10 @@ def getRoot(command, terminator=None):
|
|||||||
effects. The command would normally terminate with a '(' or
|
effects. The command would normally terminate with a '(' or
|
||||||
'.'. The terminator and anything after the terminator will be
|
'.'. The terminator and anything after the terminator will be
|
||||||
dropped."""
|
dropped."""
|
||||||
|
command = command.split('\n')[-1]
|
||||||
|
if command.startswith(sys.ps2):
|
||||||
|
command = command[len(sys.ps2):]
|
||||||
|
command = command.lstrip()
|
||||||
command = rtrimTerminus(command, terminator)
|
command = rtrimTerminus(command, terminator)
|
||||||
tokens = getTokens(command)
|
tokens = getTokens(command)
|
||||||
if not tokens:
|
if not tokens:
|
||||||
@@ -207,13 +212,17 @@ def getRoot(command, terminator=None):
|
|||||||
if tokens[-1][0] is tokenize.ENDMARKER:
|
if tokens[-1][0] is tokenize.ENDMARKER:
|
||||||
# Remove the end marker.
|
# Remove the end marker.
|
||||||
del tokens[-1]
|
del tokens[-1]
|
||||||
|
if not tokens:
|
||||||
|
return ''
|
||||||
if terminator == '.' and \
|
if terminator == '.' and \
|
||||||
(tokens[-1][1] <> '.' or tokens[-1][0] is not tokenize.OP):
|
(tokens[-1][1] <> '.' or tokens[-1][0] is not tokenize.OP):
|
||||||
# Trap decimals in numbers, versus the dot operator.
|
# Trap decimals in numbers, versus the dot operator.
|
||||||
return ''
|
return ''
|
||||||
else:
|
else:
|
||||||
# Strip off the terminator.
|
# Strip off the terminator.
|
||||||
command = command[:-1]
|
if terminator and command.endswith(terminator):
|
||||||
|
size = 0 - len(terminator)
|
||||||
|
command = command[:size]
|
||||||
command = command.rstrip()
|
command = command.rstrip()
|
||||||
tokens = getTokens(command)
|
tokens = getTokens(command)
|
||||||
tokens.reverse()
|
tokens.reverse()
|
||||||
@@ -293,7 +302,7 @@ def getTokens(command):
|
|||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
def rtrimTerminus(command, terminator=None):
|
def rtrimTerminus(command, terminator=None):
|
||||||
"""Return command minus anything that fillows the final terminator."""
|
"""Return command minus anything that follows the final terminator."""
|
||||||
if terminator:
|
if terminator:
|
||||||
pieces = command.split(terminator)
|
pieces = command.split(terminator)
|
||||||
if len(pieces) > 1:
|
if len(pieces) > 1:
|
1021
wxPython/wxPython/py/shell.py
Normal file
1021
wxPython/wxPython/py/shell.py
Normal file
File diff suppressed because it is too large
Load Diff
82
wxPython/wxPython/py/tests/test_interpreter.py
Normal file
82
wxPython/wxPython/py/tests/test_interpreter.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# Import from this module's parent directory.
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.pardir)
|
||||||
|
import interpreter
|
||||||
|
del sys.path[0]
|
||||||
|
del sys
|
||||||
|
del os
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
These unittest methods are preferred:
|
||||||
|
-------------------------------------
|
||||||
|
self.assert_(expr, msg=None)
|
||||||
|
self.assertEqual(first, second, msg=None)
|
||||||
|
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
||||||
|
self.fail(msg=None)
|
||||||
|
self.failIf(expr, msg=None)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_module(self):
|
||||||
|
module = interpreter
|
||||||
|
self.assert_(module.__author__)
|
||||||
|
self.assert_(module.__cvsid__)
|
||||||
|
self.assert_(module.__revision__)
|
||||||
|
self.assert_(module.Interpreter)
|
||||||
|
self.assert_(module.Interpreter.push)
|
||||||
|
self.assert_(module.Interpreter.runsource)
|
||||||
|
self.assert_(module.Interpreter.getAutoCompleteList)
|
||||||
|
self.assert_(module.Interpreter.getCallTip)
|
||||||
|
self.assert_(module.InterpreterAlaCarte)
|
||||||
|
|
||||||
|
|
||||||
|
class InterpreterTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.output = ''
|
||||||
|
self.i = interpreter.Interpreter(stdout=self)
|
||||||
|
|
||||||
|
def write(self, text):
|
||||||
|
"""Capture output from self.i.push()."""
|
||||||
|
self.output += text
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.output = ''
|
||||||
|
self.i = None
|
||||||
|
del self.i
|
||||||
|
|
||||||
|
def test_more(self):
|
||||||
|
self.assertEqual(self.i.push('dir()'), 0)
|
||||||
|
self.assertEqual(self.i.push('for n in range(3):'), 1)
|
||||||
|
|
||||||
|
def test_push(self):
|
||||||
|
values = (
|
||||||
|
('dir', '<built-in function dir>'),
|
||||||
|
('dir()', "['__builtins__', '__doc__', '__name__']"),
|
||||||
|
('2 + 2', '4'),
|
||||||
|
('d = {}', ''),
|
||||||
|
('d', '{}'),
|
||||||
|
('del d', ''),
|
||||||
|
('len([4,5,6])', '3'),
|
||||||
|
)
|
||||||
|
for input, output in values:
|
||||||
|
if output: output += '\n'
|
||||||
|
self.i.push(input)
|
||||||
|
self.assertEqual(self.output, output)
|
||||||
|
self.output = ''
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
862
wxPython/wxPython/py/tests/test_introspect.py
Normal file
862
wxPython/wxPython/py/tests/test_introspect.py
Normal file
@@ -0,0 +1,862 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# Import from this module's parent directory.
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.pardir)
|
||||||
|
import introspect
|
||||||
|
del sys.path[0]
|
||||||
|
del sys
|
||||||
|
del os
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
These unittest methods are preferred:
|
||||||
|
-------------------------------------
|
||||||
|
self.assert_(expr, msg=None)
|
||||||
|
self.assertEqual(first, second, msg=None)
|
||||||
|
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
||||||
|
self.fail(msg=None)
|
||||||
|
self.failIf(expr, msg=None)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_module(self):
|
||||||
|
module = introspect
|
||||||
|
self.assert_(module.__author__)
|
||||||
|
self.assert_(module.__cvsid__)
|
||||||
|
self.assert_(module.__revision__)
|
||||||
|
self.assert_(module.getAllAttributeNames)
|
||||||
|
self.assert_(module.getAttributeNames)
|
||||||
|
self.assert_(module.getAutoCompleteList)
|
||||||
|
self.assert_(module.getBaseObject)
|
||||||
|
self.assert_(module.getCallTip)
|
||||||
|
self.assert_(module.getConstructor)
|
||||||
|
self.assert_(module.getRoot)
|
||||||
|
self.assert_(module.rtrimTerminus)
|
||||||
|
|
||||||
|
|
||||||
|
class RtrimTerminusTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_rtrimTerminus(self):
|
||||||
|
values = (
|
||||||
|
('', '', ''),
|
||||||
|
('', None, ''),
|
||||||
|
('', '.', ''),
|
||||||
|
('', '(', ''),
|
||||||
|
|
||||||
|
('.', '', '.'),
|
||||||
|
('.', None, '.'),
|
||||||
|
('.', '.', '.'),
|
||||||
|
('.', '(', '.'),
|
||||||
|
|
||||||
|
('(', '', '('),
|
||||||
|
('(', None, '('),
|
||||||
|
('(', '.', '('),
|
||||||
|
('(', '(', '('),
|
||||||
|
|
||||||
|
('spam', '', 'spam'),
|
||||||
|
('spam', None, 'spam'),
|
||||||
|
('spam', '.', 'spam'),
|
||||||
|
('spam', '(', 'spam'),
|
||||||
|
|
||||||
|
('spam.', '', 'spam.'),
|
||||||
|
('spam.', None, 'spam.'),
|
||||||
|
('spam.', '.', 'spam.'),
|
||||||
|
('spam.', '(', 'spam.'),
|
||||||
|
|
||||||
|
('spam(', '', 'spam('),
|
||||||
|
('spam(', None, 'spam('),
|
||||||
|
('spam(', '.', 'spam('),
|
||||||
|
('spam(', '(', 'spam('),
|
||||||
|
|
||||||
|
('spam.eggs', '.', 'spam.'),
|
||||||
|
('spam.eggs.', '.', 'spam.eggs.'),
|
||||||
|
('spam.eggs(', '(', 'spam.eggs('),
|
||||||
|
('spam.eggs.', '(', 'spam.eggs.'),
|
||||||
|
('spam.eggs(', '.', 'spam.'),
|
||||||
|
|
||||||
|
('x = spam.', '.', 'x = spam.'),
|
||||||
|
('x = spam.eggs', '.', 'x = spam.'),
|
||||||
|
('x = spam.eggs.', '.', 'x = spam.eggs.'),
|
||||||
|
('x = spam.eggs(', '(', 'x = spam.eggs('),
|
||||||
|
)
|
||||||
|
for input, terminator, output in values:
|
||||||
|
result = introspect.rtrimTerminus(input, terminator)
|
||||||
|
self.assertEqual(result, output,
|
||||||
|
':in: %r :t: %r :out: %r :result: %r' %
|
||||||
|
(input, terminator, output, result))
|
||||||
|
|
||||||
|
|
||||||
|
class GetRootTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def _checkRoot(self, input, terminator, output):
|
||||||
|
root = introspect.getRoot(command=input, terminator=terminator)
|
||||||
|
self.assertEqual(root, output,
|
||||||
|
':in: %r :t: %r :out: %r :root: %r' %
|
||||||
|
(input, terminator, output, root))
|
||||||
|
|
||||||
|
def test_getRoot(self):
|
||||||
|
values = (
|
||||||
|
('', '', ''),
|
||||||
|
('', None, ''),
|
||||||
|
('', '.', ''),
|
||||||
|
('', '(', ''),
|
||||||
|
|
||||||
|
('.', '', '.'),
|
||||||
|
('.', None, '.'),
|
||||||
|
('.', '.', ''),
|
||||||
|
('.', '(', '.'),
|
||||||
|
|
||||||
|
('(', '', ''),
|
||||||
|
('(', None, ''),
|
||||||
|
('(', '.', ''),
|
||||||
|
('(', '(', ''),
|
||||||
|
|
||||||
|
('spam', '', 'spam'),
|
||||||
|
('spam', None, 'spam'),
|
||||||
|
('spam', '.', ''),
|
||||||
|
('spam', '(', 'spam'),
|
||||||
|
|
||||||
|
('spam.', '', 'spam.'),
|
||||||
|
('spam.', None, 'spam.'),
|
||||||
|
('spam.', '.', 'spam'),
|
||||||
|
('spam.', '(', 'spam.'),
|
||||||
|
|
||||||
|
('spam(', '', ''),
|
||||||
|
('spam(', None, ''),
|
||||||
|
('spam(', '.', ''),
|
||||||
|
('spam(', '(', 'spam'),
|
||||||
|
|
||||||
|
('spam.eggs', '.', 'spam'),
|
||||||
|
('spam.eggs.', '.', 'spam.eggs'),
|
||||||
|
('spam.eggs(', '(', 'spam.eggs'),
|
||||||
|
('spam.eggs.', '(', 'spam.eggs.'),
|
||||||
|
('spam.eggs(', '.', 'spam'),
|
||||||
|
|
||||||
|
('x = spam.', '.', 'spam'),
|
||||||
|
('x = spam.eggs', '.', 'spam'),
|
||||||
|
('x = spam.eggs.', '.', 'spam.eggs'),
|
||||||
|
('x = spam.eggs(', '(', 'spam.eggs'),
|
||||||
|
|
||||||
|
('for n in range(3):\n d.', '.', 'd'),
|
||||||
|
('for n in range(3):\n... d.', '.', 'd'),
|
||||||
|
)
|
||||||
|
for input, terminator, output in values:
|
||||||
|
self._checkRoot(input, terminator, output)
|
||||||
|
|
||||||
|
def test_getRoot_Advanced(self):
|
||||||
|
values = (
|
||||||
|
('spam_', '', 'spam_'),
|
||||||
|
('spam_', None, 'spam_'),
|
||||||
|
('spam_', '.', ''),
|
||||||
|
('spam_', '(', 'spam_'),
|
||||||
|
|
||||||
|
('_spam', '', '_spam'),
|
||||||
|
('_spam', None, '_spam'),
|
||||||
|
('_spam', '.', ''),
|
||||||
|
('_spam', '(', '_spam'),
|
||||||
|
|
||||||
|
('spam_eggs', '', 'spam_eggs'),
|
||||||
|
('spam_eggs', None, 'spam_eggs'),
|
||||||
|
('spam_eggs', '.', ''),
|
||||||
|
('spam_eggs', '(', 'spam_eggs'),
|
||||||
|
|
||||||
|
('spam123', '', 'spam123'),
|
||||||
|
('spam123', None, 'spam123'),
|
||||||
|
('spam123', '.', ''),
|
||||||
|
('spam123', '(', 'spam123'),
|
||||||
|
|
||||||
|
('spam_123', '', 'spam_123'),
|
||||||
|
('spam_123', None, 'spam_123'),
|
||||||
|
('spam_123', '.', ''),
|
||||||
|
('spam_123', '(', 'spam_123'),
|
||||||
|
)
|
||||||
|
for input, terminator, output in values:
|
||||||
|
self._checkRoot(input, terminator, output)
|
||||||
|
|
||||||
|
## The original intent was to detect when we were inside a string.
|
||||||
|
## That has proven to be very difficult, for little benefit.
|
||||||
|
## The fact that autocomplete or calltips might be triggered inside
|
||||||
|
## a string is not a big deal. Sometimes it is even helpful.
|
||||||
|
|
||||||
|
## def test_getRoot_InsideStrings(self):
|
||||||
|
## values = (
|
||||||
|
## ('x = ".', '.', ''),
|
||||||
|
## ("x = '.", '.', ''),
|
||||||
|
## ('x = """.', '.', ''),
|
||||||
|
## ("x = '''.", '.', ''),
|
||||||
|
##
|
||||||
|
## ('x = "(', '(', ''),
|
||||||
|
## ("x = '(", '(', ''),
|
||||||
|
## ('x = """(', '(', ''),
|
||||||
|
## ("x = '''(", '(', ''),
|
||||||
|
##
|
||||||
|
## ('x = "spam', '.', ''),
|
||||||
|
## ('x = "spam.', '.', ''),
|
||||||
|
## ("x = 'spam.", '.', ''),
|
||||||
|
## ('x = """spam.', '.', ''),
|
||||||
|
## ("x = '''spam.", '.', ''),
|
||||||
|
##
|
||||||
|
## ('x = "spam', '(', ''),
|
||||||
|
## ('x = "spam(', '(', ''),
|
||||||
|
## ("x = 'spam(", '(', ''),
|
||||||
|
## ('x = """spam(', '(', ''),
|
||||||
|
## ("x = '''spam(", '(', ''),
|
||||||
|
##
|
||||||
|
## ('x = "spam.eggs.', '.', ''),
|
||||||
|
## ("x = 'spam.eggs.", '.', ''),
|
||||||
|
## ('x = """spam.eggs.', '.', ''),
|
||||||
|
## ("x = '''spam.eggs.", '.', ''),
|
||||||
|
##
|
||||||
|
## ('x = "spam.eggs(', '(', ''),
|
||||||
|
## ("x = 'spam.eggs(", '(', ''),
|
||||||
|
## ('x = """spam.eggs(', '(', ''),
|
||||||
|
## ("x = '''spam.eggs(", '(', ''),
|
||||||
|
## )
|
||||||
|
## for input, terminator, output in values:
|
||||||
|
## self._checkRoot(input, terminator, output)
|
||||||
|
|
||||||
|
def test_getRoot_EmptyTypes(self):
|
||||||
|
values = (
|
||||||
|
("''.", '.', "''"),
|
||||||
|
('"".', '.', '""'),
|
||||||
|
('"""""".', '.', '""""""'),
|
||||||
|
("''''''.", '.', "''''''"),
|
||||||
|
|
||||||
|
('[].', '.', '[]'),
|
||||||
|
('().', '.', '()'),
|
||||||
|
('{}.', '.', '{}'),
|
||||||
|
|
||||||
|
('[](', '(', '[]'),
|
||||||
|
('()(', '(', '()'),
|
||||||
|
('{}(', '(', '{}'),
|
||||||
|
|
||||||
|
("x = ''.", '.', "''"),
|
||||||
|
('x = "".', '.', '""'),
|
||||||
|
('x = """""".', '.', '""""""'),
|
||||||
|
("x = ''''''.", '.', "''''''"),
|
||||||
|
|
||||||
|
('x = [].', '.', '[]'),
|
||||||
|
('x = ().', '.', '()'),
|
||||||
|
('x = {}.', '.', '{}'),
|
||||||
|
|
||||||
|
('x = [](', '(', '[]'),
|
||||||
|
('x = ()(', '(', '()'),
|
||||||
|
('x = {}(', '(', '{}'),
|
||||||
|
|
||||||
|
('print [].', '.', '[]'),
|
||||||
|
('print ().', '.', '()'),
|
||||||
|
('print {}.', '.', '{}'),
|
||||||
|
|
||||||
|
('print [](', '(', '[]'),
|
||||||
|
('print ()(', '(', '()'),
|
||||||
|
('print {}(', '(', '{}'),
|
||||||
|
|
||||||
|
("''.attr.", '.', "''.attr"),
|
||||||
|
('"".attr.', '.', '"".attr'),
|
||||||
|
('"""""".attr.', '.', '"""""".attr'),
|
||||||
|
("''''''.attr.", '.', "''''''.attr"),
|
||||||
|
|
||||||
|
('[].attr.', '.', '[].attr'),
|
||||||
|
('().attr.', '.', '().attr'),
|
||||||
|
('{}.attr.', '.', '{}.attr'),
|
||||||
|
|
||||||
|
('[].attr(', '(', '[].attr'),
|
||||||
|
('().attr(', '(', '().attr'),
|
||||||
|
('{}.attr(', '(', '{}.attr'),
|
||||||
|
|
||||||
|
('spam().', '.', ''),
|
||||||
|
('spam_().', '.', ''),
|
||||||
|
('spam5().', '.', ''),
|
||||||
|
('spam[]().', '.', ''),
|
||||||
|
('spam()[].', '.', ''),
|
||||||
|
('spam[]{}.', '.', ''),
|
||||||
|
|
||||||
|
("spam(''.", '.', "''"),
|
||||||
|
('spam("".', '.', '""'),
|
||||||
|
('spam("""""".', '.', '""""""'),
|
||||||
|
("spam(''''''.", '.', "''''''"),
|
||||||
|
|
||||||
|
('spam([].', '.', '[]'),
|
||||||
|
('spam(().', '.', '()'),
|
||||||
|
('spam({}.', '.', '{}'),
|
||||||
|
('spam[[].', '.', '[]'),
|
||||||
|
('spam[().', '.', '()'),
|
||||||
|
('spam[{}.', '.', '{}'),
|
||||||
|
('x = {[].', '.', '[]'),
|
||||||
|
('x = {().', '.', '()'),
|
||||||
|
('x = {{}.', '.', '{}'),
|
||||||
|
|
||||||
|
('spam,[].', '.', '[]'),
|
||||||
|
('spam+[].', '.', '[]'),
|
||||||
|
('spam-[].', '.', '[]'),
|
||||||
|
('spam*[].', '.', '[]'),
|
||||||
|
('spam/[].', '.', '[]'),
|
||||||
|
('spam=[].', '.', '[]'),
|
||||||
|
('spam%[].', '.', '[]'),
|
||||||
|
('spam<[].', '.', '[]'),
|
||||||
|
('spam>[].', '.', '[]'),
|
||||||
|
('spam&[].', '.', '[]'),
|
||||||
|
('spam|[].', '.', '[]'),
|
||||||
|
('spam^[].', '.', '[]'),
|
||||||
|
('spam~[].', '.', '[]'),
|
||||||
|
('spam:[].', '.', '[]'),
|
||||||
|
|
||||||
|
('spam,().', '.', '()'),
|
||||||
|
('spam+().', '.', '()'),
|
||||||
|
('spam-().', '.', '()'),
|
||||||
|
('spam*().', '.', '()'),
|
||||||
|
('spam/().', '.', '()'),
|
||||||
|
('spam=().', '.', '()'),
|
||||||
|
('spam%().', '.', '()'),
|
||||||
|
('spam<().', '.', '()'),
|
||||||
|
('spam>().', '.', '()'),
|
||||||
|
('spam&().', '.', '()'),
|
||||||
|
('spam|().', '.', '()'),
|
||||||
|
('spam^().', '.', '()'),
|
||||||
|
('spam~().', '.', '()'),
|
||||||
|
('spam:().', '.', '()'),
|
||||||
|
|
||||||
|
('spam,{}.', '.', '{}'),
|
||||||
|
('spam+{}.', '.', '{}'),
|
||||||
|
('spam-{}.', '.', '{}'),
|
||||||
|
('spam*{}.', '.', '{}'),
|
||||||
|
('spam/{}.', '.', '{}'),
|
||||||
|
('spam={}.', '.', '{}'),
|
||||||
|
('spam%{}.', '.', '{}'),
|
||||||
|
('spam<{}.', '.', '{}'),
|
||||||
|
('spam>{}.', '.', '{}'),
|
||||||
|
('spam&{}.', '.', '{}'),
|
||||||
|
('spam|{}.', '.', '{}'),
|
||||||
|
('spam^{}.', '.', '{}'),
|
||||||
|
('spam~{}.', '.', '{}'),
|
||||||
|
('spam:{}.', '.', '{}'),
|
||||||
|
)
|
||||||
|
for input, terminator, output in values:
|
||||||
|
self._checkRoot(input, terminator, output)
|
||||||
|
|
||||||
|
|
||||||
|
# Support for GetBaseObjectTestCase and GetAttributeNamesTestCase.
|
||||||
|
|
||||||
|
class Foo:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _private(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Bar:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Spam:
|
||||||
|
def __call__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def foo(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def bar(spam):
|
||||||
|
# It shouldn't matter what we call "self".
|
||||||
|
pass
|
||||||
|
|
||||||
|
def eggs(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def ham(eggs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class GetBaseObjectTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_getBaseObject(self):
|
||||||
|
spam = Spam()
|
||||||
|
eggs = Spam.eggs
|
||||||
|
listappend = [].append
|
||||||
|
spamda = lambda: None
|
||||||
|
values = (
|
||||||
|
('spam', 'spam', 0),
|
||||||
|
(123, 123, 0),
|
||||||
|
(12.3, 12.3, 0),
|
||||||
|
([], [], 0),
|
||||||
|
((), (), 0),
|
||||||
|
({}, {}, 0),
|
||||||
|
# Builtin function.
|
||||||
|
(len, len, 0),
|
||||||
|
# Builtin method.
|
||||||
|
(listappend, listappend, 0),
|
||||||
|
# User function.
|
||||||
|
(ham, ham, 0),
|
||||||
|
# Byte-compiled code.
|
||||||
|
(ham.func_code, ham.func_code, 0),
|
||||||
|
# Lambda.
|
||||||
|
(spamda, spamda, 0),
|
||||||
|
# Class with init.
|
||||||
|
(Foo, Foo.__init__.im_func, 1),
|
||||||
|
# Class with no init.
|
||||||
|
(Bar, Bar, 0),
|
||||||
|
# Bound method.
|
||||||
|
(spam.foo, spam.foo.im_func, 1),
|
||||||
|
# Bound method with self named something else (spam).
|
||||||
|
(spam.bar, spam.bar.im_func, 1),
|
||||||
|
# Unbound method. (Do not drop the self argument.)
|
||||||
|
(eggs, eggs.im_func, 0),
|
||||||
|
# Callable instance.
|
||||||
|
(spam, spam.__call__.im_func, 1),
|
||||||
|
)
|
||||||
|
for object, baseObject, dropSelf in values:
|
||||||
|
result = introspect.getBaseObject(object)
|
||||||
|
self.assertEqual(result, (baseObject, dropSelf))
|
||||||
|
|
||||||
|
|
||||||
|
class GetAttributeTestCase(unittest.TestCase):
|
||||||
|
"""Base class for other test case classes."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.values = (
|
||||||
|
'__abs__',
|
||||||
|
'__add__',
|
||||||
|
'__and__',
|
||||||
|
'__base__',
|
||||||
|
'__bases__',
|
||||||
|
'__basicsize__',
|
||||||
|
'__builtins__',
|
||||||
|
'__call__',
|
||||||
|
'__class__',
|
||||||
|
'__cmp__',
|
||||||
|
'__coerce__',
|
||||||
|
'__contains__',
|
||||||
|
'__del__',
|
||||||
|
'__delattr__',
|
||||||
|
'__delitem__',
|
||||||
|
'__delslice__',
|
||||||
|
'__dict__',
|
||||||
|
'__dictoffset__',
|
||||||
|
'__div__',
|
||||||
|
'__divmod__',
|
||||||
|
'__doc__',
|
||||||
|
'__eq__',
|
||||||
|
'__file__',
|
||||||
|
'__flags__',
|
||||||
|
'__float__',
|
||||||
|
'__floordiv__',
|
||||||
|
'__ge__',
|
||||||
|
'__get__',
|
||||||
|
'__getattr__',
|
||||||
|
'__getattribute__',
|
||||||
|
'__getitem__',
|
||||||
|
'__getslice__',
|
||||||
|
'__gt__',
|
||||||
|
'__hash__',
|
||||||
|
'__hex__',
|
||||||
|
'__iadd__',
|
||||||
|
'__imul__',
|
||||||
|
'__init__',
|
||||||
|
'__int__',
|
||||||
|
'__invert__',
|
||||||
|
'__itemsize__',
|
||||||
|
'__iter__',
|
||||||
|
'__le__',
|
||||||
|
'__len__',
|
||||||
|
'__long__',
|
||||||
|
'__lshift__',
|
||||||
|
'__lt__',
|
||||||
|
'__mod__',
|
||||||
|
'__module__',
|
||||||
|
'__mro__',
|
||||||
|
'__mul__',
|
||||||
|
'__name__',
|
||||||
|
'__ne__',
|
||||||
|
'__neg__',
|
||||||
|
'__new__',
|
||||||
|
'__nonzero__',
|
||||||
|
'__oct__',
|
||||||
|
'__or__',
|
||||||
|
'__path__',
|
||||||
|
'__pos__',
|
||||||
|
'__pow__',
|
||||||
|
'__radd__',
|
||||||
|
'__rand__',
|
||||||
|
'__rdiv__',
|
||||||
|
'__rdivmod__',
|
||||||
|
'__reduce__',
|
||||||
|
'__repr__',
|
||||||
|
'__rfloordiv__',
|
||||||
|
'__rlshift__',
|
||||||
|
'__rmod__',
|
||||||
|
'__rmul__',
|
||||||
|
'__ror__',
|
||||||
|
'__rpow__',
|
||||||
|
'__rrshift__',
|
||||||
|
'__rshift__',
|
||||||
|
'__rsub__',
|
||||||
|
'__rtruediv__',
|
||||||
|
'__rxor__',
|
||||||
|
'__self__',
|
||||||
|
'__setattr__',
|
||||||
|
'__setitem__',
|
||||||
|
'__setslice__',
|
||||||
|
'__str__',
|
||||||
|
'__sub__',
|
||||||
|
'__subclasses__',
|
||||||
|
'__truediv__',
|
||||||
|
'__warningregistry__',
|
||||||
|
'__weakrefoffset__',
|
||||||
|
'__xor__',
|
||||||
|
'append',
|
||||||
|
'capitalize',
|
||||||
|
'center',
|
||||||
|
'clear',
|
||||||
|
'close',
|
||||||
|
'closed',
|
||||||
|
'co_argcount',
|
||||||
|
'co_cellvars',
|
||||||
|
'co_code',
|
||||||
|
'co_consts',
|
||||||
|
'co_filename',
|
||||||
|
'co_firstlineno',
|
||||||
|
'co_flags',
|
||||||
|
'co_freevars',
|
||||||
|
'co_lnotab',
|
||||||
|
'co_name',
|
||||||
|
'co_names',
|
||||||
|
'co_nlocals',
|
||||||
|
'co_stacksize',
|
||||||
|
'co_varnames',
|
||||||
|
'conjugate',
|
||||||
|
'copy',
|
||||||
|
'count',
|
||||||
|
'decode',
|
||||||
|
'encode',
|
||||||
|
'endswith',
|
||||||
|
'expandtabs',
|
||||||
|
'extend',
|
||||||
|
'fileno',
|
||||||
|
'find',
|
||||||
|
'flush',
|
||||||
|
'func_closure',
|
||||||
|
'func_code',
|
||||||
|
'func_defaults',
|
||||||
|
'func_dict',
|
||||||
|
'func_doc',
|
||||||
|
'func_globals',
|
||||||
|
'func_name',
|
||||||
|
'get',
|
||||||
|
'has_key',
|
||||||
|
'im_class',
|
||||||
|
'im_func',
|
||||||
|
'im_self',
|
||||||
|
'imag',
|
||||||
|
'index',
|
||||||
|
'insert',
|
||||||
|
'isalnum',
|
||||||
|
'isalpha',
|
||||||
|
'isatty',
|
||||||
|
'isdigit',
|
||||||
|
'islower',
|
||||||
|
'isspace',
|
||||||
|
'istitle',
|
||||||
|
'isupper',
|
||||||
|
'items',
|
||||||
|
'iteritems',
|
||||||
|
'iterkeys',
|
||||||
|
'itervalues',
|
||||||
|
'join',
|
||||||
|
'keys',
|
||||||
|
'ljust',
|
||||||
|
'lower',
|
||||||
|
'lstrip',
|
||||||
|
'mode',
|
||||||
|
'mro',
|
||||||
|
'name',
|
||||||
|
'pop',
|
||||||
|
'popitem',
|
||||||
|
'real',
|
||||||
|
'read',
|
||||||
|
'readinto',
|
||||||
|
'readline',
|
||||||
|
'readlines',
|
||||||
|
'remove',
|
||||||
|
'replace',
|
||||||
|
'reverse',
|
||||||
|
'rfind',
|
||||||
|
'rindex',
|
||||||
|
'rjust',
|
||||||
|
'rstrip',
|
||||||
|
'seek',
|
||||||
|
'setdefault',
|
||||||
|
'softspace',
|
||||||
|
'sort',
|
||||||
|
'split',
|
||||||
|
'splitlines',
|
||||||
|
'start',
|
||||||
|
'startswith',
|
||||||
|
'step',
|
||||||
|
'stop',
|
||||||
|
'strip',
|
||||||
|
'swapcase',
|
||||||
|
'tell',
|
||||||
|
'title',
|
||||||
|
'tolist',
|
||||||
|
'translate',
|
||||||
|
'truncate',
|
||||||
|
'update',
|
||||||
|
'upper',
|
||||||
|
'values',
|
||||||
|
'write',
|
||||||
|
'writelines',
|
||||||
|
'xreadlines',
|
||||||
|
)
|
||||||
|
|
||||||
|
# Since getAllAttributeNames() calls str(object),
|
||||||
|
# we need to test for a broken __str__ method.
|
||||||
|
class BrokenStr:
|
||||||
|
def __str__(self):
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
brokenStr = BrokenStr()
|
||||||
|
|
||||||
|
class GetAttributeNamesTestCase(GetAttributeTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
GetAttributeTestCase.setUp(self)
|
||||||
|
import PyCrust
|
||||||
|
spam = Spam()
|
||||||
|
self.f = open('test_introspect.py')
|
||||||
|
self.items = (
|
||||||
|
None,
|
||||||
|
int(123),
|
||||||
|
long(123),
|
||||||
|
float(123),
|
||||||
|
complex(123),
|
||||||
|
"",
|
||||||
|
unicode(""),
|
||||||
|
[],
|
||||||
|
(),
|
||||||
|
xrange(0),
|
||||||
|
{},
|
||||||
|
# Builtin function.
|
||||||
|
len,
|
||||||
|
# Builtin method.
|
||||||
|
[].append,
|
||||||
|
# User function.
|
||||||
|
ham,
|
||||||
|
# Byte-compiled code.
|
||||||
|
ham.func_code,
|
||||||
|
# Lambda.
|
||||||
|
lambda: None,
|
||||||
|
# Class with no init.
|
||||||
|
Bar,
|
||||||
|
# Instance with no init.
|
||||||
|
Bar(),
|
||||||
|
# Class with init and del.
|
||||||
|
Foo,
|
||||||
|
# Instance with init and del.
|
||||||
|
Foo(),
|
||||||
|
# Bound method.
|
||||||
|
spam.foo,
|
||||||
|
# Unbound method.
|
||||||
|
Spam.eggs,
|
||||||
|
# Callable instance.
|
||||||
|
spam,
|
||||||
|
# Module.
|
||||||
|
introspect,
|
||||||
|
# Package.
|
||||||
|
PyCrust,
|
||||||
|
# Buffer.
|
||||||
|
buffer(''),
|
||||||
|
# File.
|
||||||
|
self.f,
|
||||||
|
# Slice.
|
||||||
|
slice(0),
|
||||||
|
# Ellipsis.
|
||||||
|
Ellipsis,
|
||||||
|
# BrokenStr class.
|
||||||
|
BrokenStr,
|
||||||
|
# BrokenStr instance.
|
||||||
|
brokenStr,
|
||||||
|
)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.items = None
|
||||||
|
self.f.close()
|
||||||
|
|
||||||
|
def test_getAttributeNames(self):
|
||||||
|
for item in self.items:
|
||||||
|
self._checkAttributeNames(item)
|
||||||
|
if __builtins__.has_key('object'):
|
||||||
|
self._checkAttributeNames(object)
|
||||||
|
|
||||||
|
def test_getAttributeNames_NoSingle(self):
|
||||||
|
for item in self.items:
|
||||||
|
result = introspect.getAttributeNames(item, includeSingle=0)
|
||||||
|
attributes = [attribute for attribute in result \
|
||||||
|
if attribute[0] != '_' or attribute[:2] == '__']
|
||||||
|
self.assertEqual(result, attributes,
|
||||||
|
':item: %r' % (item,))
|
||||||
|
|
||||||
|
def test_getAttributeNames_NoDouble(self):
|
||||||
|
for item in self.items:
|
||||||
|
result = introspect.getAttributeNames(item, includeDouble=0)
|
||||||
|
attributes = [attribute for attribute in result \
|
||||||
|
if attribute[:2] != '__']
|
||||||
|
self.assertEqual(result, attributes,
|
||||||
|
':item: %r' % (item,))
|
||||||
|
|
||||||
|
def test_getAttributeNames_NoSingleOrDouble(self):
|
||||||
|
for item in self.items:
|
||||||
|
result = introspect.getAttributeNames(item, includeSingle=0,
|
||||||
|
includeDouble=0)
|
||||||
|
attributes = [attribute for attribute in result \
|
||||||
|
if attribute[0] != '_']
|
||||||
|
self.assertEqual(result, attributes,
|
||||||
|
':item: %r' % (item,))
|
||||||
|
|
||||||
|
def _checkAttributeNames(self, item):
|
||||||
|
result = introspect.getAttributeNames(item)
|
||||||
|
attributes = [attribute for attribute in self.values \
|
||||||
|
if hasattr(item, attribute)]
|
||||||
|
for attribute in attributes:
|
||||||
|
self.assert_(attribute in result,
|
||||||
|
':item: %r :attribute: %r' % (item, attribute))
|
||||||
|
|
||||||
|
|
||||||
|
class GetAutoCompleteListTestCase(GetAttributeTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
GetAttributeTestCase.setUp(self)
|
||||||
|
self.items = (
|
||||||
|
'None.',
|
||||||
|
'123 .',
|
||||||
|
'"".',
|
||||||
|
'[].',
|
||||||
|
'().',
|
||||||
|
'{}.',
|
||||||
|
# Builtin function.
|
||||||
|
'len.',
|
||||||
|
# Builtin method.
|
||||||
|
'[].append.',
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_getAutoCompleteList(self):
|
||||||
|
for item in self.items:
|
||||||
|
result = introspect.getAutoCompleteList(item)
|
||||||
|
object = eval(item[:-1])
|
||||||
|
attributes = [attribute for attribute in self.values \
|
||||||
|
if hasattr(object, attribute)]
|
||||||
|
for attribute in attributes:
|
||||||
|
self.assert_(attribute in result,
|
||||||
|
':item: %r :attribute: %r' % (item, attribute))
|
||||||
|
|
||||||
|
def test_getAutoCompleteList_NoSingle(self):
|
||||||
|
for item in self.items:
|
||||||
|
result = introspect.getAutoCompleteList(item, includeSingle=0)
|
||||||
|
attributes = [attribute for attribute in result \
|
||||||
|
if attribute[0] != '_' or attribute[:2] == '__']
|
||||||
|
self.assertEqual(result, attributes,
|
||||||
|
':item: %r' % (item,))
|
||||||
|
|
||||||
|
def test_getAutoCompleteList_NoDouble(self):
|
||||||
|
for item in self.items:
|
||||||
|
result = introspect.getAutoCompleteList(item, includeDouble=0)
|
||||||
|
attributes = [attribute for attribute in result \
|
||||||
|
if attribute[:2] != '__']
|
||||||
|
self.assertEqual(result, attributes,
|
||||||
|
':item: %r' % (item,))
|
||||||
|
|
||||||
|
def test_getAutoCompleteList_NoSingleOrDouble(self):
|
||||||
|
for item in self.items:
|
||||||
|
result = introspect.getAutoCompleteList(item, includeSingle=0,
|
||||||
|
includeDouble=0)
|
||||||
|
attributes = [attribute for attribute in result \
|
||||||
|
if attribute[0] != '_']
|
||||||
|
self.assertEqual(result, attributes,
|
||||||
|
':item: %r' % (item,))
|
||||||
|
|
||||||
|
|
||||||
|
# Support for GetConstructorTestCase.
|
||||||
|
|
||||||
|
class A1:
|
||||||
|
def __init__(self, a):
|
||||||
|
self.a = a
|
||||||
|
|
||||||
|
class B1(A1):
|
||||||
|
def __init__(self, b):
|
||||||
|
self.b = b
|
||||||
|
|
||||||
|
class C1(A1):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class D1(C1, B1):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __builtins__.has_key('object'):
|
||||||
|
class A2(object):
|
||||||
|
def __init__(self, a):
|
||||||
|
self.a = a
|
||||||
|
|
||||||
|
class B2(A2):
|
||||||
|
def __init__(self, b):
|
||||||
|
self.b = b
|
||||||
|
|
||||||
|
class C2(A2):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class D2(C2, B2):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class N:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class O:
|
||||||
|
def __init__(self, a, b=2, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class P(O):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Q(P):
|
||||||
|
def __init__(self, c, d=4):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class GetConstructorTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_getConstructor(self):
|
||||||
|
args = ('self', 'a', 'b', 'args', 'kwargs')
|
||||||
|
varnames = introspect.getConstructor(O).func_code.co_varnames
|
||||||
|
self.assertEqual(varnames, args)
|
||||||
|
varnames = introspect.getConstructor(P).func_code.co_varnames
|
||||||
|
self.assertEqual(varnames, args)
|
||||||
|
args = ('self', 'c', 'd')
|
||||||
|
varnames = introspect.getConstructor(Q).func_code.co_varnames
|
||||||
|
self.assertEqual(varnames, args)
|
||||||
|
|
||||||
|
def test_getConstructor_None(self):
|
||||||
|
values = (N, 1, 'spam', {}, [], (), dir)
|
||||||
|
for value in values:
|
||||||
|
self.assertEqual(introspect.getConstructor(N), None)
|
||||||
|
|
||||||
|
def test_getConstructor_MultipleInheritance(self):
|
||||||
|
# Test old style inheritance rules.
|
||||||
|
args = ('self', 'a')
|
||||||
|
varnames = introspect.getConstructor(D1).func_code.co_varnames
|
||||||
|
self.assertEqual(varnames, args)
|
||||||
|
if __builtins__.has_key('object'):
|
||||||
|
# Test new style inheritance rules as well.
|
||||||
|
args = ('self', 'b')
|
||||||
|
varnames = introspect.getConstructor(D2).func_code.co_varnames
|
||||||
|
self.assertEqual(varnames, args)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
81
wxPython/wxPython/py/tests/test_pseudo.py
Normal file
81
wxPython/wxPython/py/tests/test_pseudo.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# Import from this module's parent directory.
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.pardir)
|
||||||
|
import pseudo
|
||||||
|
del sys.path[0]
|
||||||
|
del sys
|
||||||
|
del os
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
These unittest methods are preferred:
|
||||||
|
-------------------------------------
|
||||||
|
self.assert_(expr, msg=None)
|
||||||
|
self.assertEqual(first, second, msg=None)
|
||||||
|
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
||||||
|
self.fail(msg=None)
|
||||||
|
self.failIf(expr, msg=None)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_module(self):
|
||||||
|
module = pseudo
|
||||||
|
self.assert_(module.__author__)
|
||||||
|
self.assert_(module.__cvsid__)
|
||||||
|
self.assert_(module.__revision__)
|
||||||
|
self.assert_(module.PseudoFile)
|
||||||
|
self.assert_(module.PseudoFileErr)
|
||||||
|
self.assert_(module.PseudoFileIn)
|
||||||
|
self.assert_(module.PseudoFileOut)
|
||||||
|
self.assert_(module.PseudoKeyword)
|
||||||
|
|
||||||
|
|
||||||
|
class PseudoTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PseudoFileTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PseudoFileOutTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _write(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_PseudoFileOut_goodInit(self):
|
||||||
|
self.assert_(pseudo.PseudoFileOut(write=self._write))
|
||||||
|
|
||||||
|
def test_PseudoFileOut_badInit(self):
|
||||||
|
self.assertRaises(ValueError, pseudo.PseudoFileOut, write='bad')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
49
wxPython/wxPython/py/tests/test_version.py
Normal file
49
wxPython/wxPython/py/tests/test_version.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import types
|
||||||
|
|
||||||
|
# Import from this module's parent directory.
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.pardir)
|
||||||
|
import version
|
||||||
|
del sys.path[0]
|
||||||
|
del sys
|
||||||
|
del os
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
These unittest methods are preferred:
|
||||||
|
-------------------------------------
|
||||||
|
self.assert_(expr, msg=None)
|
||||||
|
self.assertEqual(first, second, msg=None)
|
||||||
|
self.assertRaises(excClass, callableObj, *args, **kwargs)
|
||||||
|
self.fail(msg=None)
|
||||||
|
self.failIf(expr, msg=None)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_module(self):
|
||||||
|
module = version
|
||||||
|
self.assert_(module.__author__)
|
||||||
|
self.assert_(module.__cvsid__)
|
||||||
|
self.assert_(module.__revision__)
|
||||||
|
self.assert_(module.VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
class VersionTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_VERSION(self):
|
||||||
|
self.assert_(type(version.VERSION) is types.StringType)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
25
wxPython/wxPython/py/tests/testall.py
Normal file
25
wxPython/wxPython/py/tests/testall.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
"""Return a test suite containing all test cases in all test modules.
|
||||||
|
Searches the current directory for any modules matching test_*.py."""
|
||||||
|
suite = unittest.TestSuite()
|
||||||
|
for filename in glob.glob('test_*.py'):
|
||||||
|
module = __import__(os.path.splitext(filename)[0])
|
||||||
|
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(module))
|
||||||
|
return suite
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
@@ -7,5 +7,5 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
VERSION = '0.9'
|
VERSION = '0.9.1'
|
||||||
|
|
@@ -1126,11 +1126,11 @@ class Notebook(Control):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def AddPage(self, pPage, strText, bSelect=False, imageId=-1):
|
def AddPage(self, page, text, select=False, imageId=-1):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def AdvanceSelection(self, bForward=True):
|
def AdvanceSelection(self, forward=True):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1147,7 +1147,7 @@ class Notebook(Control):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def DeletePage(self, nPage):
|
def DeletePage(self, page):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1155,7 +1155,7 @@ class Notebook(Control):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def GetPage(self, nPage):
|
def GetPage(self, page):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1163,11 +1163,11 @@ class Notebook(Control):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def GetPageImage(self, nPage):
|
def GetPageImage(self, page):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def GetPageText(self, nPage):
|
def GetPageText(self, page):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1179,11 +1179,11 @@ class Notebook(Control):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def InsertPage(self, nPage, pPage, strText, bSelect=False, imageId=-1):
|
def InsertPage(self, index, page, text, select=False, imageId=-1):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def RemovePage(self, nPage):
|
def RemovePage(self, page):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1199,7 +1199,7 @@ class Notebook(Control):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def SetPageImage(self, nPage, nImage):
|
def SetPageImage(self, page, image):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1207,11 +1207,11 @@ class Notebook(Control):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def SetPageText(self, nPage, strText):
|
def SetPageText(self, page, text):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def SetSelection(self, nPage):
|
def SetSelection(self, page):
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
@@ -37,9 +37,9 @@ class Frame(TopLevelWindow):
|
|||||||
name=wx.PyFrameNameStr):
|
name=wx.PyFrameNameStr):
|
||||||
"""Create a Frame instance.
|
"""Create a Frame instance.
|
||||||
|
|
||||||
parent - The window parent. This may be NULL. If it is
|
parent - The window parent. This may be None. If it is not
|
||||||
non-NULL, the frame will always be displayed on top of the
|
None, the frame will always be displayed on top of the parent
|
||||||
parent window on Windows.
|
window on Windows.
|
||||||
|
|
||||||
id - The window identifier. It may take a value of -1 to
|
id - The window identifier. It may take a value of -1 to
|
||||||
indicate a default value.
|
indicate a default value.
|
||||||
@@ -93,8 +93,8 @@ class Frame(TopLevelWindow):
|
|||||||
By default, the status bar is an instance of wx.StatusBar."""
|
By default, the status bar is an instance of wx.StatusBar."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def CreateToolBar(self, style=wx.NO_BORDER|wx.TB_HORIZONTAL, id=-1,
|
def CreateToolBar(self, style=wx.NO_BORDER | wx.TB_HORIZONTAL,
|
||||||
name=wx.PyToolBarNameStr):
|
id=-1, name=wx.PyToolBarNameStr):
|
||||||
"""Create a toolbar at the top or left of frame.
|
"""Create a toolbar at the top or left of frame.
|
||||||
|
|
||||||
style - The toolbar style. See wxToolBar for a list of valid
|
style - The toolbar style. See wxToolBar for a list of valid
|
||||||
@@ -141,8 +141,7 @@ class Frame(TopLevelWindow):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def GetStatusBarPane(self):
|
def GetStatusBarPane(self):
|
||||||
"""Return status bar pane used to display menu and toolbar
|
"""Return status bar pane used to display menu/toolbar help."""
|
||||||
help."""
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def GetToolBar(self):
|
def GetToolBar(self):
|
||||||
@@ -237,22 +236,102 @@ class Frame(TopLevelWindow):
|
|||||||
|
|
||||||
|
|
||||||
class LayoutAlgorithm(Object):
|
class LayoutAlgorithm(Object):
|
||||||
""""""
|
"""LayoutAlgorithm implements layout of subwindows in MDI or SDI
|
||||||
|
frames. It sends a wx.CalculateLayoutEvent event to children of
|
||||||
|
the frame, asking them for information about their size. For MDI
|
||||||
|
parent frames, the algorithm allocates the remaining space to the
|
||||||
|
MDI client window (which contains the MDI child frames). For SDI
|
||||||
|
(normal) frames, a 'main' window is specified as taking up the
|
||||||
|
remaining space.
|
||||||
|
|
||||||
|
Because the event system is used, this technique can be applied to
|
||||||
|
any windows, which are not necessarily 'aware' of the layout
|
||||||
|
classes. However, you may wish to use wx.SashLayoutWindow for
|
||||||
|
your subwindows since this class provides handlers for the
|
||||||
|
required events, and accessors to specify the desired size of the
|
||||||
|
window. The sash behaviour in the base class can be used,
|
||||||
|
optionally, to make the windows user-resizable.
|
||||||
|
|
||||||
|
LayoutAlgorithm is typically used in IDE (integrated development
|
||||||
|
environment) applications, where there are several resizable
|
||||||
|
windows in addition to the MDI client window, or other primary
|
||||||
|
editing window. Resizable windows might include toolbars, a
|
||||||
|
project window, and a window for displaying error and warning
|
||||||
|
messages.
|
||||||
|
|
||||||
|
When a window receives an OnCalculateLayout event, it should call
|
||||||
|
SetRect in the given event object, to be the old supplied
|
||||||
|
rectangle minus whatever space the window takes up. It should
|
||||||
|
also set its own size accordingly.
|
||||||
|
SashLayoutWindow.OnCalculateLayout generates an OnQueryLayoutInfo
|
||||||
|
event which it sends to itself to determine the orientation,
|
||||||
|
alignment and size of the window, which it gets from internal
|
||||||
|
member variables set by the application.
|
||||||
|
|
||||||
|
The algorithm works by starting off with a rectangle equal to the
|
||||||
|
whole frame client area. It iterates through the frame children,
|
||||||
|
generating OnCalculateLayout events which subtract the window size
|
||||||
|
and return the remaining rectangle for the next window to process.
|
||||||
|
It is assumed (by SashLayoutWindow.OnCalculateLayout) that a
|
||||||
|
window stretches the full dimension of the frame client, according
|
||||||
|
to the orientation it specifies. For example, a horizontal window
|
||||||
|
will stretch the full width of the remaining portion of the frame
|
||||||
|
client area. In the other orientation, the window will be fixed
|
||||||
|
to whatever size was specified by OnQueryLayoutInfo. An alignment
|
||||||
|
setting will make the window 'stick' to the left, top, right or
|
||||||
|
bottom of the remaining client area. This scheme implies that
|
||||||
|
order of window creation is important. Say you wish to have an
|
||||||
|
extra toolbar at the top of the frame, a project window to the
|
||||||
|
left of the MDI client window, and an output window above the
|
||||||
|
status bar. You should therefore create the windows in this
|
||||||
|
order: toolbar, output window, project window. This ensures that
|
||||||
|
the toolbar and output window take up space at the top and bottom,
|
||||||
|
and then the remaining height in-between is used for the project
|
||||||
|
window.
|
||||||
|
|
||||||
|
LayoutAlgorithm is quite independent of the way in which
|
||||||
|
OnCalculateLayout chooses to interpret a window's size and
|
||||||
|
alignment. Therefore you could implement a different window class
|
||||||
|
with a new OnCalculateLayout event handler, that has a more
|
||||||
|
sophisticated way of laying out the windows. It might allow
|
||||||
|
specification of whether stretching occurs in the specified
|
||||||
|
orientation, for example, rather than always assuming
|
||||||
|
stretching. (This could, and probably should, be added to the
|
||||||
|
existing implementation).
|
||||||
|
|
||||||
|
The algorithm object does not respond to events, but itself
|
||||||
|
generates the following events in order to calculate window sizes:
|
||||||
|
EVT_QUERY_LAYOUT_INFO(func), EVT_CALCULATE_LAYOUT(func)."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
""""""
|
"""Create a LayoutAlgorithm instance."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def LayoutFrame(self):
|
def LayoutFrame(self, frame, mainWindow=wx.NULL):
|
||||||
""""""
|
"""Lay out the children of a normal frame.
|
||||||
|
|
||||||
|
mainWindow is set to occupy the remaining space. This
|
||||||
|
function simply calls LayoutWindow()."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def LayoutMDIFrame(self):
|
def LayoutMDIFrame(self, frame, rect=wx.NULL):
|
||||||
""""""
|
"""Lay out the children of an MDI parent frame.
|
||||||
|
|
||||||
|
If rect is non-NULL, the given rectangle will be used as a
|
||||||
|
starting point instead of the frame's client area.
|
||||||
|
|
||||||
|
The MDI client window is set to occupy the remaining space."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def LayoutWindow(self):
|
def LayoutWindow(self, parent, mainWindow=wx.NULL):
|
||||||
""""""
|
"""Lay out the children of a normal frame or other window.
|
||||||
|
|
||||||
|
mainWindow is set to occupy the remaining space. If this is
|
||||||
|
not specified, then the last window that responds to a
|
||||||
|
calculate layout event in query mode will get the remaining
|
||||||
|
space (that is, a non-query OnCalculateLayout event will not
|
||||||
|
be sent to this window and the window will be set to the
|
||||||
|
remaining size)."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
60
wxPython/wxPython/py/wxd/LICENSE.txt
Normal file
60
wxPython/wxPython/py/wxd/LICENSE.txt
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
wxWindows Free Documentation Licence, Version 3
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
Copyright (c) 1998 Julian Smart, Robert Roebling et al
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this licence document, but changing it is not allowed.
|
||||||
|
|
||||||
|
WXWINDOWS FREE DOCUMENTATION LICENCE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
1. Permission is granted to make and distribute verbatim copies of this
|
||||||
|
manual or piece of documentation provided any copyright notice and this
|
||||||
|
permission notice are preserved on all copies.
|
||||||
|
|
||||||
|
2. Permission is granted to process this file or document through a
|
||||||
|
document processing system and, at your option and the option of any third
|
||||||
|
party, print the results, provided a printed document carries a copying
|
||||||
|
permission notice identical to this one.
|
||||||
|
|
||||||
|
3. Permission is granted to copy and distribute modified versions of this
|
||||||
|
manual or piece of documentation under the conditions for verbatim
|
||||||
|
copying, provided also that any sections describing licensing conditions
|
||||||
|
for this manual, such as, in particular, the GNU General Public Licence,
|
||||||
|
the GNU Library General Public Licence, and any wxWindows Licence are
|
||||||
|
included exactly as in the original, and provided that the entire
|
||||||
|
resulting derived work is distributed under the terms of a permission
|
||||||
|
notice identical to this one.
|
||||||
|
|
||||||
|
4. Permission is granted to copy and distribute translations of this
|
||||||
|
manual or piece of documentation into another language, under the above
|
||||||
|
conditions for modified versions, except that sections related to
|
||||||
|
licensing, including this paragraph, may also be included in translations
|
||||||
|
approved by the copyright holders of the respective licence documents in
|
||||||
|
addition to the original English.
|
||||||
|
|
||||||
|
WARRANTY DISCLAIMER
|
||||||
|
|
||||||
|
5. BECAUSE THIS MANUAL OR PIECE OF DOCUMENTATION IS LICENSED FREE OF CHARGE,
|
||||||
|
THERE IS NO WARRANTY FOR IT, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
|
||||||
|
PARTIES PROVIDE THIS MANUAL OR PIECE OF DOCUMENTATION "AS IS" WITHOUT
|
||||||
|
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF
|
||||||
|
THE MANUAL OR PIECE OF DOCUMENTATION IS WITH YOU. SHOULD THE MANUAL OR
|
||||||
|
PIECE OF DOCUMENTATION PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||||||
|
NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
6. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
||||||
|
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE MANUAL OR PIECE OF DOCUMENTATION AS PERMITTED ABOVE, BE
|
||||||
|
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
MANUAL OR PIECE OF DOCUMENTATION (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF A PROGRAM BASED ON THE MANUAL OR PIECE OF
|
||||||
|
DOCUMENTATION TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
|
||||||
|
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
@@ -36,6 +36,7 @@ _params = (
|
|||||||
'DefaultValidator',
|
'DefaultValidator',
|
||||||
'EmptyString',
|
'EmptyString',
|
||||||
'EVT_NULL',
|
'EVT_NULL',
|
||||||
|
'HORIZONTAL',
|
||||||
'HSCROLL',
|
'HSCROLL',
|
||||||
'NO_BORDER',
|
'NO_BORDER',
|
||||||
'NULL',
|
'NULL',
|
605
wxPython/wxPython/py/wxd/Sizers.py
Normal file
605
wxPython/wxPython/py/wxd/Sizers.py
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
"""Decorator classes for documentation and shell scripting.
|
||||||
|
|
||||||
|
Sizer is the abstract base class used for laying out subwindows in a
|
||||||
|
window. You cannot use Sizer directly; instead, you will have to use
|
||||||
|
one of the sizer classes derived from it. Currently there are
|
||||||
|
BoxSizer, StaticBoxSizer, NotebookSizer, GridSizer, and FlexGridSizer.
|
||||||
|
|
||||||
|
The layout algorithm used by sizers in wxPython is closely related to
|
||||||
|
layout in other GUI toolkits, such as Java's AWT, the GTK toolkit or
|
||||||
|
the Qt toolkit. It is based upon the idea of the individual
|
||||||
|
subwindows reporting their minimal required size and their ability to
|
||||||
|
get stretched if the size of the parent window has changed. This will
|
||||||
|
most often mean, that the programmer does not set the original size of
|
||||||
|
a dialog in the beginning, rather the dialog will assigned a sizer and
|
||||||
|
this sizer will be queried about the recommended size. The sizer in
|
||||||
|
turn will query its children, which can be normal windows, empty space
|
||||||
|
or other sizers, so that a hierarchy of sizers can be constructed.
|
||||||
|
Note that wxSizer does not derive from wxWindow and thus do not
|
||||||
|
interfere with tab ordering and requires very little resources
|
||||||
|
compared to a real window on screen.
|
||||||
|
|
||||||
|
What makes sizers so well fitted for use in wxPython is the fact that
|
||||||
|
every control reports its own minimal size and the algorithm can
|
||||||
|
handle differences in font sizes or different window (dialog item)
|
||||||
|
sizes on different platforms without problems. If e.g. the standard
|
||||||
|
font as well as the overall design of Motif widgets requires more
|
||||||
|
space than on Windows, the initial dialog size will automatically be
|
||||||
|
bigger on Motif than on Windows.
|
||||||
|
|
||||||
|
If you wish to create a sizer class in wxPython you should derive the
|
||||||
|
class from PySizer in order to get Python-aware capabilities for the
|
||||||
|
various virtual methods.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
|
||||||
|
# These are not the real wxPython classes. These are Python versions
|
||||||
|
# for documentation purposes. They are also used to apply docstrings
|
||||||
|
# to the real wxPython classes, which are SWIG-generated wrappers for
|
||||||
|
# C-language classes.
|
||||||
|
|
||||||
|
|
||||||
|
from Base import Object
|
||||||
|
import Parameters as wx
|
||||||
|
|
||||||
|
try:
|
||||||
|
True
|
||||||
|
except NameError:
|
||||||
|
True = 1==1
|
||||||
|
False = 1==0
|
||||||
|
|
||||||
|
|
||||||
|
class Sizer(Object):
|
||||||
|
"""Sizer is the abstract base class used for laying out subwindows
|
||||||
|
in a window. You shouldn't use Sizer directly; instead, you should
|
||||||
|
use one of the sizer classes derived from it.
|
||||||
|
|
||||||
|
If you wish to create a sizer class in wxPython you should derive
|
||||||
|
the class from PySizer in order to get Python-aware capabilities
|
||||||
|
for the various virtual methods.
|
||||||
|
|
||||||
|
Placing a child sizer in a sizer allows you to create hierarchies
|
||||||
|
of sizers (typically a vertical box as the top sizer and several
|
||||||
|
horizontal boxes on the level beneath).
|
||||||
|
|
||||||
|
When you place a window in a sizer the window's initial size
|
||||||
|
(either set explicitly by the user or calculated internally when
|
||||||
|
using wxDefaultSize) is interpreted as the minimal and in many
|
||||||
|
cases also the initial size. This is particularly useful in
|
||||||
|
connection with SetSizeHints.
|
||||||
|
|
||||||
|
Adding spacers to sizers gives more flexibility in the design of
|
||||||
|
dialogs. Imagine for example a horizontal box with two buttons at
|
||||||
|
the bottom of a dialog: you might want to insert a space between
|
||||||
|
the two buttons and make that space stretchable using the
|
||||||
|
proportion flag and the result will be that the left button will
|
||||||
|
be aligned with the left side of the dialog and the right button
|
||||||
|
with the right side - the space in between will shrink and grow
|
||||||
|
with the dialog.
|
||||||
|
|
||||||
|
Several methods (Add, Insert, Prepend) take the following
|
||||||
|
parameters:
|
||||||
|
|
||||||
|
proportion - Used only by BoxSizer to indicate if a child of a
|
||||||
|
sizer can change its size in the main orientation of the BoxSizer,
|
||||||
|
where 0 stands for not changeable and a value of more than zero is
|
||||||
|
interpreted relative to the value of other children of the same
|
||||||
|
BoxSizer. For example, you might have a horizontal BoxSizer with
|
||||||
|
three children, two of which are supposed to change their size
|
||||||
|
with the sizer. Then the two stretchable windows would each get a
|
||||||
|
value of 1 to make them grow and shrink equally with the sizer's
|
||||||
|
horizontal dimension.
|
||||||
|
|
||||||
|
flag - This parameter can be used to set a number of flags which
|
||||||
|
can be combined using the binary OR operator |. Two main
|
||||||
|
behaviours are defined using these flags. One is the border
|
||||||
|
around a window: the border parameter determines the border width
|
||||||
|
whereas the flags given here determine where the border may be
|
||||||
|
(wx.TOP, wx.BOTTOM, wx.LEFT, wx.RIGHT or wx.ALL). The other flags
|
||||||
|
determine the child window's behaviour if the size of the sizer
|
||||||
|
changes. However this is not - in contrast to the proportion flag
|
||||||
|
- in the main orientation, but in the respectively other
|
||||||
|
orientation. So if you created a BoxSizer with the wx.VERTICAL
|
||||||
|
option, these flags will be relevant if the sizer changes its
|
||||||
|
horizontal size. A child may get resized to completely fill out
|
||||||
|
the new size (using either wx.GROW or wx.EXPAND), it may get
|
||||||
|
proportionally resized (wx.SHAPED), it may get centered
|
||||||
|
(wx.ALIGN_CENTER or wx.ALIGN_CENTRE) or it may get aligned to
|
||||||
|
either side (wx.ALIGN_LEFT and wx.ALIGN_TOP are set to 0 and thus
|
||||||
|
represent the default, wx.ALIGN_RIGHT and wx.ALIGN_BOTTOM have
|
||||||
|
their obvious meaning). With proportional resize, a child may
|
||||||
|
also be centered in the main orientation using
|
||||||
|
wx.ALIGN_CENTER_VERTICAL (same as wx.ALIGN_CENTRE_VERTICAL) and
|
||||||
|
wx.ALIGN_CENTER_HORIZONTAL (same as wx.ALIGN_CENTRE_HORIZONTAL)
|
||||||
|
flags. Finally, you can also specify wx.ADJUST_MINSIZE flag to
|
||||||
|
make the minimal size of the control dynamically adjust to the
|
||||||
|
value returned by its GetAdjustedBestSize() method - this allows,
|
||||||
|
for example, for correct relayouting of a static text control even
|
||||||
|
if its text is changed during run-time.
|
||||||
|
|
||||||
|
border - Determines the border width, if the flag parameter is set
|
||||||
|
to any border. A border is not a visible element, but rather a
|
||||||
|
margin of empty space surrounding the item.
|
||||||
|
|
||||||
|
userData - Allows an extra object to be attached to the sizer
|
||||||
|
item, for use in derived classes when sizing information is more
|
||||||
|
complex than the option and flag parameters will allow."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Must be defined by subclasses."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Add(self, item, proportion=0, flag=0, border=0,
|
||||||
|
userData=wx.NULL):
|
||||||
|
"""Add item to sizer.
|
||||||
|
|
||||||
|
item - window, sizer, or spacer. Spacer is specified with a
|
||||||
|
(width, height) tuple or wx.Size representing the spacer size.
|
||||||
|
|
||||||
|
Call Layout() to update the layout on-screen after adding."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Clear(self, delete_windows=False):
|
||||||
|
"""Remove all items from this sizer.
|
||||||
|
|
||||||
|
If delete_windows is True, destroy any window items."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def DeleteWindows(self):
|
||||||
|
"""Destroy windows associated with this sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Destroy(self):
|
||||||
|
"""Destroy the sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Fit(self, window):
|
||||||
|
"""Resize window to match sizer's minimal size; return size.
|
||||||
|
|
||||||
|
This is commonly done in the constructor of the window itself."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def FitInside(self, window):
|
||||||
|
"""Resize window virtual size to match sizer's minimal size.
|
||||||
|
|
||||||
|
This will not alter the on screen size of the window, but may
|
||||||
|
cause the addition/removal/alteration of scrollbars required
|
||||||
|
to view the virtual area in windows which manage it."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetChildren(self):
|
||||||
|
"""Return list of SizerItem instances."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetMinSize(self):
|
||||||
|
"""Return the minimal size of the sizer.
|
||||||
|
|
||||||
|
This is either the combined minimal size of all the children
|
||||||
|
and their borders or the minimal size set by SetMinSize,
|
||||||
|
whichever is larger."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetMinSizeTuple(self):
|
||||||
|
"""Return the minimal size of the sizer as a tuple.
|
||||||
|
|
||||||
|
This is either the combined minimal size of all the children
|
||||||
|
and their borders or the minimal size set by SetMinSize,
|
||||||
|
whichever is larger."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetPosition(self):
|
||||||
|
"""Return the current position of the sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetPositionTuple(self):
|
||||||
|
"""Return the current position of the sizer as a tuple."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetSize(self):
|
||||||
|
"""Return the current size of the sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetSizeTuple(self):
|
||||||
|
"""Return the current size of the sizer as a tuple."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Hide(self, item):
|
||||||
|
"""Hide item (sizer or window). To make a sizer item
|
||||||
|
disappear on-screen, use Hide() followed by Layout()."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Insert(self, before, item, proportion=0, flag=0, border=0,
|
||||||
|
userData=wx.NULL):
|
||||||
|
"""Same as Add, but inserts item into list of items (windows,
|
||||||
|
subsizers or spacers) owned by this sizer.
|
||||||
|
|
||||||
|
Call Layout() to update the layout on-screen after inserting."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def IsShown(self, item):
|
||||||
|
"""Return True if item (sizer or window) is shown."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Layout(self):
|
||||||
|
"""Force layout of children anew.
|
||||||
|
|
||||||
|
Use after adding or removing a child (window, other sizer, or
|
||||||
|
spacer) from the sizer while keeping the current dimension."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Prepend(self, item, proportion=0, flag=0, border=0,
|
||||||
|
userData=wx.NULL):
|
||||||
|
"""Same as Add, but prepends item to beginning of list of
|
||||||
|
items (windows, subsizers or spacers) owned by this sizer.
|
||||||
|
|
||||||
|
Call Layout() to update the layout on-screen after prepending."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Remove(self, item):
|
||||||
|
"""Remove item from the sizer.
|
||||||
|
|
||||||
|
item - sizer, window, or index of item in the sizer, typically
|
||||||
|
0 for the first item.
|
||||||
|
|
||||||
|
Does not cause any layout or resizing to take place, and does
|
||||||
|
not delete the child itself. Call Layout() to update the
|
||||||
|
layout on-screen after removing child.
|
||||||
|
|
||||||
|
Return True if child found and removed, False otherwise."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetDimension(self, x, y, width, height):
|
||||||
|
"""Force sizer to take the given dimension and thus force
|
||||||
|
items owned by sizer to resize themselves according to the
|
||||||
|
rules defined by the parameter in the Add and Prepend methods."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetItemMinSize(self, item, width, height):
|
||||||
|
"""Set minimal size of item.
|
||||||
|
|
||||||
|
item - sizer, window, or index of item in the sizer, typically
|
||||||
|
0 for the first item.
|
||||||
|
|
||||||
|
The item will be found recursively in the sizer's descendants.
|
||||||
|
Enables application to set size of item after initialization."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetMinSize(self, size):
|
||||||
|
"""Set minimal size.
|
||||||
|
|
||||||
|
Normally, sizer will calculate minimal size based on how much
|
||||||
|
space its children need. After calling this method,
|
||||||
|
GetMinSize will return the minimal size as requested by its
|
||||||
|
children or the minimal size set here, whichever is larger."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetSizeHints(self, window):
|
||||||
|
"""Set (and Fit) minimal size of window to match sizer's
|
||||||
|
minimal size. Commonly called in the window's init."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetVirtualSizeHints(self, window):
|
||||||
|
"""Set minimal size of window virtual area to match sizer's
|
||||||
|
minimal size. For windows with managed scrollbars this will
|
||||||
|
set them appropriately."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Show(self, item, show=True):
|
||||||
|
"""Show or hide item (sizer or window). To make item
|
||||||
|
disappear or reappear on-screen, use Show() followed by
|
||||||
|
Layout()."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def ShowItems(self, show):
|
||||||
|
"""Recursively call Show() on all sizer items."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PySizer(Sizer):
|
||||||
|
"""If you wish to create a custom sizer class you should derive
|
||||||
|
the class from PySizer in order to get Python-aware capabilities
|
||||||
|
for the various virtual methods."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Create a PySizer instance. Override in subclass."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BoxSizer(Sizer):
|
||||||
|
"""A box sizer is used to lay out a rather simple geometry,
|
||||||
|
typically a row or column or several hierarchies of either."""
|
||||||
|
|
||||||
|
def __init__(self, orient=wx.HORIZONTAL):
|
||||||
|
"""Create BoxSizer instance.
|
||||||
|
|
||||||
|
orient is either wx.VERTICAL or wx.HORIZONTAL"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def CalcMin(self):
|
||||||
|
"""Calculate minimum size. Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetOrientation(self):
|
||||||
|
"""Return orientation: wx.VERTICAL or wx.HORIZONTAL."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def RecalcSizes(self):
|
||||||
|
"""Recalculate sizes, then set the size of its children
|
||||||
|
(calling SetSize if child is a window). Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetOrientation(self, orient):
|
||||||
|
"""Set orientation to either wx.VERTICAL or wx.HORIZONTAL."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class StaticBoxSizer(BoxSizer):
|
||||||
|
"""Like BoxSizer, but adds a static box around the sizer. Note
|
||||||
|
that the static box has to be created separately."""
|
||||||
|
|
||||||
|
def __init__(self, box, orient=wx.HORIZONTAL):
|
||||||
|
"""Create StaticBoxSizer instance.
|
||||||
|
|
||||||
|
box - instance of wx.StaticBox
|
||||||
|
|
||||||
|
orient - either wx.VERTICAL or wx.HORIZONTAL"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def CalcMin(self):
|
||||||
|
"""Calculate minimum size. Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetStaticBox(self):
|
||||||
|
"""Return the static box associated with the sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def RecalcSizes(self):
|
||||||
|
"""Recalculate sizes, then set the size of its children
|
||||||
|
(calling SetSize if child is a window). Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class GridSizer(Sizer):
|
||||||
|
"""A grid sizer lays out its children in a two-dimensional table
|
||||||
|
where all cells have the same size: the width of each cell is the
|
||||||
|
width of the widest child, the height of each cell is the height
|
||||||
|
of the tallest child. See also the FlexGridSizer."""
|
||||||
|
|
||||||
|
def __init__(self, rows=1, cols=0, vgap=0, hgap=0):
|
||||||
|
"""Create a GridSizer instance.
|
||||||
|
|
||||||
|
rows and cols - the number of rows and columns in the grid; if
|
||||||
|
either is zero, it will be calculated as the number of
|
||||||
|
children in the sizer, allowing the sizer grow dynamically.
|
||||||
|
|
||||||
|
vgap and hgap - extra space between all cells, in pixels."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def CalcMin(self):
|
||||||
|
"""Calculate minimum size. Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetCols(self):
|
||||||
|
"""Return the number of columns in the grid."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetHGap(self):
|
||||||
|
"""Return the horizontal gap (in pixels) between cells."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetRows(self):
|
||||||
|
"""Return the number of rows in the grid."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetVGap(self):
|
||||||
|
"""Return the vertical gap (in pixels) between cells."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def RecalcSizes(self):
|
||||||
|
"""Recalculate sizes, then set the size of its children
|
||||||
|
(calling SetSize if child is a window). Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetCols(self, cols):
|
||||||
|
"""Set the number of columns in the grid."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetHGap(self, gap):
|
||||||
|
"""Set the horizontal gap (in pixels) between cells."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetRows(self, rows):
|
||||||
|
"""Sets the number of rows in the grid."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetVGap(self, gap):
|
||||||
|
"""Set the vertical gap (in pixels) between cells."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FlexGridSizer(GridSizer):
|
||||||
|
"""A flex grid sizer lays out its children in a two-dimensional
|
||||||
|
table where all cells in one row have the same height and all
|
||||||
|
cells in one column have the same width, but all cells are not
|
||||||
|
necessarily the same height and width, as in the GridSizer."""
|
||||||
|
|
||||||
|
def __init__(self, rows=1, cols=0, vgap=0, hgap=0):
|
||||||
|
"""Create a GridSizer instance.
|
||||||
|
|
||||||
|
rows and cols - the number of rows and columns in the grid; if
|
||||||
|
either is zero, it will be calculated as the number of
|
||||||
|
children in the sizer, allowing the sizer grow dynamically.
|
||||||
|
|
||||||
|
vgap and hgap - extra space between all cells, in pixels."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def AddGrowableCol(self, idx):
|
||||||
|
"""Specify that column idx (starting from zero) should expand
|
||||||
|
if there is extra space available to the sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def AddGrowableRow(self, idx):
|
||||||
|
"""Specify that row idx (starting from zero) should expand if
|
||||||
|
there is extra space available to the sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def CalcMin(self):
|
||||||
|
"""Calculate minimum size. Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def RecalcSizes(self):
|
||||||
|
"""Recalculate sizes, then set the size of its children
|
||||||
|
(calling SetSize if child is a window). Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def RemoveGrowableCol(self, idx):
|
||||||
|
"""Specify that column idx is no longer growable."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def RemoveGrowableRow(self, idx):
|
||||||
|
"""Specify that row idx is no longer growable."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NotebookSizer(Sizer):
|
||||||
|
"""NotebookSizer works with a notebook to determine the size of
|
||||||
|
the biggest page and report an adjusted minimal size to a more
|
||||||
|
toplevel sizer. Do not add children to a NotebookSizer."""
|
||||||
|
|
||||||
|
def __init__(self, nb):
|
||||||
|
"""Create a NotebookSizer instance for notebook."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def CalcMin(self):
|
||||||
|
"""Calculate minimum size. Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetNotebook(self):
|
||||||
|
"""Return the notebook associated with the sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def RecalcSizes(self):
|
||||||
|
"""Recalculate size. Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SizerItem(Object):
|
||||||
|
"""SizerItem class. Wrapper for items managed by a sizer."""
|
||||||
|
|
||||||
|
def __init__(self, this):
|
||||||
|
"""Create a SizerItem instance. You don't normally create one
|
||||||
|
directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def CalcMin(self):
|
||||||
|
"""Calculate minimum size. Do not call directly."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def DeleteWindows(self):
|
||||||
|
"""Recursively destroy windows associated with this SizerItem."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetBorder(self):
|
||||||
|
"""Return border width."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetFlag(self):
|
||||||
|
"""Return flag value."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetOption(self):
|
||||||
|
"""Return option value."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetPosition(self):
|
||||||
|
"""Return wx.Point instance representing position relative to
|
||||||
|
the client area."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetRatio(self):
|
||||||
|
"""Return a floating point aspect ratio (width/height). If
|
||||||
|
wx.SHAPED flag is used item will maintain ratio when resized."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetSize(self):
|
||||||
|
"""Return wx.Size instance with size."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetSizer(self):
|
||||||
|
"""If IsSizer() return the sizer; otherwise return None."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetUserData(self):
|
||||||
|
"""Return a wx.PyUserData object."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def GetWindow(self):
|
||||||
|
"""If IsWindow() return the window; otherwise return None."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def IsShown(self):
|
||||||
|
"""Return True if item is shown."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def IsSizer(self):
|
||||||
|
"""Return True if SizerItem represents a sizer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def IsSpacer(self):
|
||||||
|
"""Return True if SizerItem represents a spacer."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def IsWindow(self):
|
||||||
|
"""Return True if SizerItem represents a window."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetBorder(self, border):
|
||||||
|
"""Set border width for item."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetDimension(self, pos, size):
|
||||||
|
"""Set position and size for item."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetFlag(self, flag):
|
||||||
|
"""Set flag for item."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetInitSize(self, x, y):
|
||||||
|
"""Set initial size of item."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetOption(self, option):
|
||||||
|
"""Set option for item."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetRatio(self, ratio):
|
||||||
|
"""Set a floating point aspect ratio (width/height). If
|
||||||
|
wx.SHAPED flag is used item will maintain ratio when resized."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetRatioSize(self, size):
|
||||||
|
"""Set a floating point aspect ratio (width/height). If
|
||||||
|
wx.SHAPED flag is used item will maintain ratio when resized."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetRatioWH(self, width, height):
|
||||||
|
"""Set a floating point aspect ratio (width/height). If
|
||||||
|
wx.SHAPED flag is used item will maintain ratio when resized."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetSizer(self, sizer):
|
||||||
|
"""Set sizer associated with SizerItem."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def SetWindow(self, window):
|
||||||
|
"""Set window associated with SizerItem."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def Show(self, show):
|
||||||
|
"""Is show is True, show item, otherwise hide item."""
|
||||||
|
pass
|
@@ -18,7 +18,10 @@ import Parameters as wx
|
|||||||
|
|
||||||
|
|
||||||
class TreeCtrl(Control):
|
class TreeCtrl(Control):
|
||||||
""""""
|
"""A tree control presents information as a hierarchy, with items
|
||||||
|
that may be expanded to show further items. Items in a tree
|
||||||
|
control are referenced by wx.TreeItemId handles, which may be
|
||||||
|
tested for validity by calling TreeItemId.IsOk()."""
|
||||||
|
|
||||||
def AddRoot(self):
|
def AddRoot(self):
|
||||||
""""""
|
""""""
|
||||||
@@ -354,49 +357,47 @@ class TreeItemAttr:
|
|||||||
|
|
||||||
|
|
||||||
class TreeItemData(Object):
|
class TreeItemData(Object):
|
||||||
""""""
|
"""TreeItemData is some (arbitrary) user class associated with
|
||||||
|
some item. The main advantage of having this class is that
|
||||||
|
TreeItemData objects are destroyed automatically by the tree and
|
||||||
|
the memory and any other resources associated with a tree item
|
||||||
|
will be automatically freed when it is deleted."""
|
||||||
|
|
||||||
|
def __init__(self, obj=wx.NULL):
|
||||||
|
"""Associate any Python object with tree item using
|
||||||
|
wxTreeItemData as container."""
|
||||||
|
pass
|
||||||
|
|
||||||
def GetData(self):
|
def GetData(self):
|
||||||
""""""
|
"""Return the Python object."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def GetId(self):
|
def GetId(self):
|
||||||
""""""
|
"""Return the item associated with this node."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def SetData(self):
|
def SetData(self, obj):
|
||||||
""""""
|
"""Associate Python object with tree item."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def SetId(self):
|
def SetId(self, id):
|
||||||
""""""
|
"""Set the item associated with this node."""
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TreeItemId:
|
class TreeItemId:
|
||||||
""""""
|
"""Item in a TreeCtrl."""
|
||||||
|
|
||||||
|
## You wouldn't create these directly.
|
||||||
|
|
||||||
|
## def __init__(self):
|
||||||
|
## """"""
|
||||||
|
## pass
|
||||||
|
|
||||||
def IsOk(self):
|
def IsOk(self):
|
||||||
""""""
|
"""Return True if item is valid."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def Ok(self):
|
def Ok(self):
|
||||||
""""""
|
"""Synonym for IsOk."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __cmp__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""""""
|
|
||||||
pass
|
|
||||||
|
|
208
wxPython/wxPython/py/wxd/default.css
Normal file
208
wxPython/wxPython/py/wxd/default.css
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
:Author: David Goodger
|
||||||
|
:Contact: goodger@users.sourceforge.net
|
||||||
|
:date: $Date$
|
||||||
|
:version: $Revision$
|
||||||
|
:copyright: This stylesheet has been placed in the public domain.
|
||||||
|
|
||||||
|
Default cascading style sheet for the HTML output of Docutils.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0 }
|
||||||
|
|
||||||
|
.last {
|
||||||
|
margin-bottom: 0 }
|
||||||
|
|
||||||
|
a.toc-backref {
|
||||||
|
text-decoration: none ;
|
||||||
|
color: black }
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-bottom: 0.5em }
|
||||||
|
|
||||||
|
div.abstract {
|
||||||
|
margin: 2em 5em }
|
||||||
|
|
||||||
|
div.abstract p.topic-title {
|
||||||
|
font-weight: bold ;
|
||||||
|
text-align: center }
|
||||||
|
|
||||||
|
div.attention, div.caution, div.danger, div.error, div.hint,
|
||||||
|
div.important, div.note, div.tip, div.warning {
|
||||||
|
margin: 2em ;
|
||||||
|
border: medium outset ;
|
||||||
|
padding: 1em }
|
||||||
|
|
||||||
|
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||||
|
div.danger p.admonition-title, div.error p.admonition-title,
|
||||||
|
div.warning p.admonition-title {
|
||||||
|
color: red ;
|
||||||
|
font-weight: bold ;
|
||||||
|
font-family: sans-serif }
|
||||||
|
|
||||||
|
div.hint p.admonition-title, div.important p.admonition-title,
|
||||||
|
div.note p.admonition-title, div.tip p.admonition-title {
|
||||||
|
font-weight: bold ;
|
||||||
|
font-family: sans-serif }
|
||||||
|
|
||||||
|
div.dedication {
|
||||||
|
margin: 2em 5em ;
|
||||||
|
text-align: center ;
|
||||||
|
font-style: italic }
|
||||||
|
|
||||||
|
div.dedication p.topic-title {
|
||||||
|
font-weight: bold ;
|
||||||
|
font-style: normal }
|
||||||
|
|
||||||
|
div.figure {
|
||||||
|
margin-left: 2em }
|
||||||
|
|
||||||
|
div.footer, div.header {
|
||||||
|
font-size: smaller }
|
||||||
|
|
||||||
|
div.sidebar {
|
||||||
|
margin-left: 1em ;
|
||||||
|
border: medium outset ;
|
||||||
|
padding: 0em 1em ;
|
||||||
|
background-color: #ffffee ;
|
||||||
|
width: 40% ;
|
||||||
|
float: right }
|
||||||
|
|
||||||
|
div.system-messages {
|
||||||
|
margin: 5em }
|
||||||
|
|
||||||
|
div.system-messages h1 {
|
||||||
|
color: red }
|
||||||
|
|
||||||
|
div.system-message {
|
||||||
|
border: medium outset ;
|
||||||
|
padding: 1em }
|
||||||
|
|
||||||
|
div.system-message p.system-message-title {
|
||||||
|
color: red ;
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
margin: 2em }
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
text-align: center }
|
||||||
|
|
||||||
|
h2.subtitle {
|
||||||
|
text-align: center }
|
||||||
|
|
||||||
|
hr {
|
||||||
|
width: 75% }
|
||||||
|
|
||||||
|
ol.simple, ul.simple {
|
||||||
|
margin-bottom: 1em }
|
||||||
|
|
||||||
|
ol.arabic {
|
||||||
|
list-style: decimal }
|
||||||
|
|
||||||
|
ol.loweralpha {
|
||||||
|
list-style: lower-alpha }
|
||||||
|
|
||||||
|
ol.upperalpha {
|
||||||
|
list-style: upper-alpha }
|
||||||
|
|
||||||
|
ol.lowerroman {
|
||||||
|
list-style: lower-roman }
|
||||||
|
|
||||||
|
ol.upperroman {
|
||||||
|
list-style: upper-roman }
|
||||||
|
|
||||||
|
p.caption {
|
||||||
|
font-style: italic }
|
||||||
|
|
||||||
|
p.credits {
|
||||||
|
font-style: italic ;
|
||||||
|
font-size: smaller }
|
||||||
|
|
||||||
|
p.label {
|
||||||
|
white-space: nowrap }
|
||||||
|
|
||||||
|
p.sidebar-title {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-weight: bold ;
|
||||||
|
font-size: larger }
|
||||||
|
|
||||||
|
p.sidebar-subtitle {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
p.topic-title {
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
pre.address {
|
||||||
|
margin-bottom: 0 ;
|
||||||
|
margin-top: 0 ;
|
||||||
|
font-family: serif ;
|
||||||
|
font-size: 100% }
|
||||||
|
|
||||||
|
pre.line-block {
|
||||||
|
font-family: serif ;
|
||||||
|
font-size: 100% }
|
||||||
|
|
||||||
|
pre.literal-block, pre.doctest-block {
|
||||||
|
margin-left: 2em ;
|
||||||
|
margin-right: 2em ;
|
||||||
|
background-color: #eeeeee }
|
||||||
|
|
||||||
|
span.classifier {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-style: oblique }
|
||||||
|
|
||||||
|
span.classifier-delimiter {
|
||||||
|
font-family: sans-serif ;
|
||||||
|
font-weight: bold }
|
||||||
|
|
||||||
|
span.interpreted {
|
||||||
|
font-family: sans-serif }
|
||||||
|
|
||||||
|
span.option {
|
||||||
|
white-space: nowrap }
|
||||||
|
|
||||||
|
span.option-argument {
|
||||||
|
font-style: italic }
|
||||||
|
|
||||||
|
span.pre {
|
||||||
|
white-space: pre }
|
||||||
|
|
||||||
|
span.problematic {
|
||||||
|
color: red }
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-top: 0.5em ;
|
||||||
|
margin-bottom: 0.5em }
|
||||||
|
|
||||||
|
table.citation {
|
||||||
|
border-left: solid thin gray ;
|
||||||
|
padding-left: 0.5ex }
|
||||||
|
|
||||||
|
table.docinfo {
|
||||||
|
margin: 2em 4em }
|
||||||
|
|
||||||
|
table.footnote {
|
||||||
|
border-left: solid thin black ;
|
||||||
|
padding-left: 0.5ex }
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
padding-left: 0.5em ;
|
||||||
|
padding-right: 0.5em ;
|
||||||
|
vertical-align: top }
|
||||||
|
|
||||||
|
th.docinfo-name, th.field-name {
|
||||||
|
font-weight: bold ;
|
||||||
|
text-align: left ;
|
||||||
|
white-space: nowrap }
|
||||||
|
|
||||||
|
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||||
|
font-size: 100% }
|
||||||
|
|
||||||
|
tt {
|
||||||
|
background-color: #eeeeee }
|
||||||
|
|
||||||
|
ul.auto-toc {
|
||||||
|
list-style-type: none }
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user