1 #----------------------------------------------------------------------------
2 # Name: PythonEditor.py
3 # Purpose: PythonEditor for wx.lib.pydocview tbat uses the Styled Text Control
9 # Copyright: (c) 2004-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
16 import wx
.lib
.pydocview
18 import keyword
# So it knows what to hilite
19 import wx
.py
# For the Python interpreter
20 import wx
.stc
# For the Python interpreter
21 import cStringIO
# For indent
24 import keyword
# for GetAutoCompleteKeywordList
25 import sys
# for GetAutoCompleteKeywordList
26 import MessageService
# for OnCheckCode
28 from UICommon
import CaseInsensitiveCompare
30 import checker
# for pychecker
31 _CHECKER_INSTALLED
= True
33 _CHECKER_INSTALLED
= False
34 import os
.path
# for pychecker
37 if wx
.Platform
== '__WXMSW__':
43 VIEW_PYTHON_INTERPRETER_ID
= wx
.NewId()
46 class PythonDocument(CodeEditor
.CodeDocument
):
50 class PythonView(CodeEditor
.CodeView
):
53 def GetCtrlClass(self
):
54 """ Used in split window to instantiate new instances """
58 def ProcessUpdateUIEvent(self
, event
):
59 if not self
.GetCtrl():
63 if id == CodeEditor
.CHECK_CODE_ID
:
64 hasText
= self
.GetCtrl().GetTextLength() > 0
68 return CodeEditor
.CodeView
.ProcessUpdateUIEvent(self
, event
)
71 def OnActivateView(self
, activate
, activeView
, deactiveView
):
72 STCTextEditor
.TextView
.OnActivateView(self
, activate
, activeView
, deactiveView
)
73 if activate
and self
.GetCtrl():
74 if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
77 wx
.CallAfter(self
.LoadOutline
) # need CallAfter because document isn't loaded yet
80 def OnClose(self
, deleteWindow
= True):
81 status
= STCTextEditor
.TextView
.OnClose(self
, deleteWindow
)
82 wx
.CallAfter(self
.ClearOutline
) # need CallAfter because when closing the document, it is Activated and then Close, so need to match OnActivateView's CallAfter
86 def GetAutoCompleteKeywordList(self
, context
, hint
):
89 if context
and len(context
):
90 obj
= eval(context
, globals(), locals())
92 if not hint
or len(hint
) == 0: # context isn't valid, maybe it was the hint
96 kw
= keyword
.kwlist
[:]
99 kw
= filter(lambda item
: item
[0] != '_', symTbl
) # remove local variables and methods
101 if hint
and len(hint
):
102 lowerHint
= hint
.lower()
103 filterkw
= filter(lambda item
: item
.lower().startswith(lowerHint
), kw
) # remove variables and methods that don't match hint
106 kw
.sort(CaseInsensitiveCompare
)
109 replaceLen
= len(hint
)
113 return " ".join(kw
), replaceLen
116 def OnCheckCode(self
):
117 if not _CHECKER_INSTALLED
:
118 wx
.MessageBox(_("pychecker not found. Please install pychecker."), _("Check Code"))
121 filename
= os
.path
.basename(self
.GetDocument().GetFilename())
123 # pychecker only works on files, doesn't take a stream or string input
124 if self
.GetDocument().IsModified():
125 dlg
= wx
.MessageDialog(self
.GetFrame(), _("'%s' has been modfied and must be saved first. Save file and check code?") % filename
, _("Check Code"))
127 val
= dlg
.ShowModal()
130 self
.GetDocument().Save()
134 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
135 messageService
.ShowWindow()
136 view
= messageService
.GetView()
141 view
.SetCallback(self
.OnJumpToFoundLine
)
143 # Set cursor to Wait cursor
144 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
))
146 # This takes a while for involved code
147 checker
.checkSyntax(self
.GetDocument().GetFilename(), view
)
149 # Set cursor to Default cursor
150 wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
))
153 def OnJumpToFoundLine(self
, event
):
154 messageService
= wx
.GetApp().GetService(MessageService
.MessageService
)
155 lineText
, pos
= messageService
.GetView().GetCurrLine()
157 lineEnd
= lineText
.find(".py:")
161 lineStart
= lineEnd
+ len(".py:")
162 lineEnd
= lineText
.find(":", lineStart
)
163 lineNum
= int(lineText
[lineStart
:lineEnd
])
165 filename
= lineText
[0:lineStart
- 1]
168 openDocs
= wx
.GetApp().GetDocumentManager().GetDocuments()
169 for openDoc
in openDocs
:
170 if openDoc
.GetFilename() == filename
:
171 foundView
= openDoc
.GetFirstView()
175 doc
= wx
.GetApp().GetDocumentManager().CreateDocument(filename
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
)
176 foundView
= doc
.GetFirstView()
179 foundView
.GetFrame().SetFocus()
181 foundView
.GotoLine(lineNum
)
182 startPos
= foundView
.PositionFromLine(lineNum
)
183 endPos
= foundView
.GetLineEndPosition(lineNum
)
184 # wxBug: Need to select in reverse order, (end, start) to put cursor at head of line so positioning is correct
185 # Also, if we use the correct positioning order (start, end), somehow, when we open a edit window for the first
186 # time, we don't see the selection, it is scrolled off screen
187 foundView
.SetSelection(endPos
, startPos
)
188 wx
.GetApp().GetService(OutlineService
.OutlineService
).LoadOutline(foundView
, position
=startPos
)
192 class PythonInterpreterView(wx
.lib
.docview
.View
):
195 def OnCreate(self
, doc
, flags
):
196 frame
= wx
.GetApp().CreateDocumentFrame(self
, doc
, flags
)
197 sizer
= wx
.BoxSizer()
198 self
._pyCrust
= wx
.py
.crust
.Crust(frame
)
199 sizer
.Add(self
._pyCrust
, 1, wx
.EXPAND
, 0)
200 frame
.SetSizer(sizer
)
207 def ProcessEvent(self
, event
):
208 if not hasattr(self
, "_pyCrust") or not self
._pyCrust
:
209 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
210 stcControl
= wx
.Window_FindFocus()
211 if not isinstance(stcControl
, wx
.stc
.StyledTextCtrl
):
212 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
217 elif id == wx
.ID_REDO
:
220 elif id == wx
.ID_CUT
:
223 elif id == wx
.ID_COPY
:
226 elif id == wx
.ID_PASTE
:
229 elif id == wx
.ID_CLEAR
:
232 elif id == wx
.ID_SELECTALL
:
233 stcControl
.SetSelection(0, -1)
236 return wx
.lib
.docview
.View
.ProcessEvent(self
, event
)
239 def ProcessUpdateUIEvent(self
, event
):
240 if not hasattr(self
, "_pyCrust") or not self
._pyCrust
:
241 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
242 stcControl
= wx
.Window_FindFocus()
243 if not isinstance(stcControl
, wx
.stc
.StyledTextCtrl
):
244 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
247 event
.Enable(stcControl
.CanUndo())
249 elif id == wx
.ID_REDO
:
250 event
.Enable(stcControl
.CanRedo())
252 elif id == wx
.ID_CUT
:
253 event
.Enable(stcControl
.CanCut())
255 elif id == wx
.ID_COPY
:
256 event
.Enable(stcControl
.CanCopy())
258 elif id == wx
.ID_PASTE
:
259 event
.Enable(stcControl
.CanPaste())
261 elif id == wx
.ID_CLEAR
:
262 event
.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected
264 elif id == wx
.ID_SELECTALL
:
265 event
.Enable(stcControl
.GetTextLength() > 0)
268 return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
)
271 def OnClose(self
, deleteWindow
=True):
272 if deleteWindow
and self
.GetFrame():
273 self
.GetFrame().Destroy()
277 class PythonInterpreterDocument(wx
.lib
.docview
.Document
):
278 """ Generate Unique Doc Type """
282 class PythonService(CodeEditor
.CodeService
):
286 CodeEditor
.CodeService
.__init
__(self
)
287 docManager
= wx
.GetApp().GetDocumentManager()
288 pythonInterpreterTemplate
= wx
.lib
.docview
.DocTemplate(docManager
,
289 _("Python Interpreter"),
293 _("Python Interpreter Document"),
294 _("Python Interpreter View"),
295 PythonInterpreterDocument
,
296 PythonInterpreterView
,
297 flags
= wx
.lib
.docview
.TEMPLATE_INVISIBLE
,
298 icon
= getPythonIcon())
299 docManager
.AssociateTemplate(pythonInterpreterTemplate
)
302 def InstallControls(self
, frame
, menuBar
= None, toolBar
= None, statusBar
= None, document
= None):
303 CodeEditor
.CodeService
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
)
305 if document
and document
.GetDocumentTemplate().GetDocumentType() != PythonDocument
:
307 if not document
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
:
310 viewMenu
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View")))
312 viewStatusBarItemPos
= self
.GetMenuItemPos(viewMenu
, wx
.lib
.pydocview
.VIEW_STATUSBAR_ID
)
313 viewMenu
.InsertCheckItem(viewStatusBarItemPos
+ 1, VIEW_PYTHON_INTERPRETER_ID
, _("Python &Interpreter"), _("Shows or hides the Python interactive window"))
314 wx
.EVT_MENU(frame
, VIEW_PYTHON_INTERPRETER_ID
, frame
.ProcessEvent
)
315 wx
.EVT_UPDATE_UI(frame
, VIEW_PYTHON_INTERPRETER_ID
, frame
.ProcessUpdateUIEvent
)
318 def ProcessEvent(self
, event
):
320 if id == VIEW_PYTHON_INTERPRETER_ID
:
321 self
.OnViewPythonInterpreter(event
)
324 return CodeEditor
.CodeService
.ProcessEvent(self
, event
)
327 def ProcessUpdateUIEvent(self
, event
):
329 if id == VIEW_PYTHON_INTERPRETER_ID
:
331 docManager
= wx
.GetApp().GetDocumentManager()
333 for doc
in docManager
.GetDocuments():
334 if isinstance(doc
, PythonInterpreterDocument
):
339 return CodeEditor
.CodeService
.ProcessUpdateUIEvent(self
, event
)
342 def OnViewPythonInterpreter(self
, event
):
343 for doc
in wx
.GetApp().GetDocumentManager().GetDocuments():
344 if isinstance(doc
, PythonInterpreterDocument
):
348 for template
in self
.GetDocumentManager().GetTemplates():
349 if template
.GetDocumentType() == PythonInterpreterDocument
:
350 newDoc
= template
.CreateDocument('', wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
)
352 newDoc
.SetDocumentName(template
.GetDocumentName())
353 newDoc
.SetDocumentTemplate(template
)
354 newDoc
.OnNewDocument()
355 newDoc
.SetWriteable(False)
356 newDoc
.GetFirstView().GetFrame().SetTitle(_("Python Interpreter"))
360 class PythonCtrl(CodeEditor
.CodeCtrl
):
363 def __init__(self
, parent
, id=-1, style
=wx
.NO_FULL_REPAINT_ON_RESIZE
):
364 CodeEditor
.CodeCtrl
.__init
__(self
, parent
, id, style
)
365 self
.SetProperty("tab.timmy.whinge.level", "1")
366 self
.SetProperty("fold.comment.python", "1")
367 self
.SetProperty("fold.quotes.python", "1")
368 self
.SetLexer(wx
.stc
.STC_LEX_PYTHON
)
369 self
.SetKeyWords(0, string
.join(keyword
.kwlist
))
372 def SetViewDefaults(self
):
373 CodeEditor
.CodeCtrl
.SetViewDefaults(self
, configPrefix
= "Python", hasWordWrap
= True, hasTabs
= True)
376 def GetFontAndColorFromConfig(self
):
377 return CodeEditor
.CodeCtrl
.GetFontAndColorFromConfig(self
, configPrefix
= "Python")
380 def UpdateStyles(self
):
381 CodeEditor
.CodeCtrl
.UpdateStyles(self
)
383 if not self
.GetFont():
386 faces
= { 'font' : self
.GetFont().GetFaceName(),
387 'size' : self
.GetFont().GetPointSize(),
388 'size2': self
.GetFont().GetPointSize() - 2,
389 'color' : "%02x%02x%02x" % (self
.GetFontColor().Red(), self
.GetFontColor().Green(), self
.GetFontColor().Blue())
394 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, "face:%(font)s,fore:#000000,face:%(font)s,size:%(size)d" % faces
)
396 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, "face:%(font)s,fore:#007F00,italic,face:%(font)s,size:%(size)d" % faces
)
398 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, "face:%(font)s,fore:#007F7F,size:%(size)d" % faces
)
400 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces
)
401 # Single quoted string
402 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces
)
404 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces
)
406 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces
)
407 # Triple double quotes
408 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces
)
409 # Class name definition
410 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, "face:%(font)s,fore:#0000FF,bold,size:%(size)d" % faces
)
411 # Function or method name definition
412 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, "face:%(font)s,fore:#007F7F,bold,size:%(size)d" % faces
)
414 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, "face:%(font)s,size:%(size)d" % faces
)
416 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, "face:%(font)s,fore:#%(color)s,face:%(font)s,size:%(size)d" % faces
)
418 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, "face:%(font)s,fore:#7F7F7F,size:%(size)d" % faces
)
419 # End of line where string is not closed
420 self
.StyleSetSpec(wx
.stc
.STC_P_STRINGEOL
, "face:%(font)s,fore:#000000,face:%(font)s,back:#E0C0E0,eol,size:%(size)d" % faces
)
423 def OnUpdateUI(self
, evt
):
424 braces
= self
.GetMatchingBraces()
426 # check for matching braces
430 caretPos
= self
.GetCurrentPos()
432 charBefore
= self
.GetCharAt(caretPos
- 1)
433 styleBefore
= self
.GetStyleAt(caretPos
- 1)
436 if charBefore
and chr(charBefore
) in braces
and styleBefore
== wx
.stc
.STC_P_OPERATOR
:
437 braceAtCaret
= caretPos
- 1
441 charAfter
= self
.GetCharAt(caretPos
)
442 styleAfter
= self
.GetStyleAt(caretPos
)
443 if charAfter
and chr(charAfter
) in braces
and styleAfter
== wx
.stc
.STC_P_OPERATOR
:
444 braceAtCaret
= caretPos
446 if braceAtCaret
>= 0:
447 braceOpposite
= self
.BraceMatch(braceAtCaret
)
449 if braceAtCaret
!= -1 and braceOpposite
== -1:
450 self
.BraceBadLight(braceAtCaret
)
452 self
.BraceHighlight(braceAtCaret
, braceOpposite
)
458 (text
, caretPos
) = self
.GetCurLine()
460 self
._tokenizerChars
= {} # This is really too much, need to find something more like a C array
461 for i
in range(len(text
)):
462 self
._tokenizerChars
[i
] = 0
464 ctext
= cStringIO
.StringIO(text
)
466 tokenize
.tokenize(ctext
.readline
, self
)
470 # Left in for debugging purposes:
471 #for i in range(len(text)):
472 # print i, text[i], self._tokenizerChars[i]
474 if caretPos
== 0 or len(string
.strip(text
)) == 0: # At beginning of line or within an empty line
477 doExtraIndent
= False
483 startSquareBracketCount
= 0
484 endSquareBracketCount
= 0
485 startCurlyBracketCount
= 0
486 endCurlyBracketCount
= 0
489 for i
in range(caretPos
- 1, -1, -1): # Go through each character before the caret
490 if i
>= len(text
): # Sometimes the caret is at the end of the text if there is no LF
492 if self
._tokenizerChars
[i
] == 1:
494 elif self
._tokenizerChars
[i
] == 2:
495 startQuoteCount
= startQuoteCount
+ 1
496 elif self
._tokenizerChars
[i
] == 3:
497 endQuoteCount
= endQuoteCount
+ 1
498 elif text
[i
] == '(': # Would be nice to use a dict for this, but the code is much more readable this way
499 startParenCount
= startParenCount
+ 1
501 endParenCount
= endParenCount
+ 1
503 startSquareBracketCount
= startSquareBracketCount
+ 1
505 endSquareBracketCount
= endSquareBracketCount
+ 1
507 startCurlyBracketCount
= startCurlyBracketCount
+ 1
509 endCurlyBracketCount
= endCurlyBracketCount
+ 1
513 if startQuoteCount
> endQuoteCount
or startParenCount
> endParenCount
or startSquareBracketCount
> endSquareBracketCount
or startCurlyBracketCount
> endCurlyBracketCount
:
514 if i
+ 1 >= caretPos
: # Caret is right at the open paren, so just do indent as if colon was there
518 spaces
= " " * (i
+ 1)
522 spaces
= text
[0:len(text
) - len(string
.lstrip(text
))]
523 if caretPos
< len(spaces
): # If within the opening spaces of a line
524 spaces
= spaces
[:caretPos
]
527 if commentStart
!= -1:
528 text
= text
[0:commentStart
]
530 textNoTrailingSpaces
= text
[0:caretPos
].rstrip()
531 if doExtraIndent
or len(textNoTrailingSpaces
) and textNoTrailingSpaces
[-1] == ':':
532 spaces
= spaces
+ ' ' * self
.GetIndent()
533 self
.AddText('\n' + spaces
)
534 self
.EnsureCaretVisible()
537 # Callback for tokenizer in self.DoIndent
538 def __call__(self
, toktype
, toktext
, (srow
,scol
), (erow
,ecol
), line
):
539 if toktype
== tokenize
.COMMENT
:
540 for i
in range(scol
, ecol
+ 1):
541 self
._validChars
[i
] = False
542 elif toktype
== token
.STRING
:
543 self
._tokenizerChars
[scol
] = 2 # Open quote
544 self
._tokenizerChars
[ecol
- 1] = 3 # Close quote
545 for i
in range(scol
+ 1, ecol
- 2):
546 self
._tokenizerChars
[i
] = 1 # Part of string, 1 == ignore the char
549 class PythonOptionsPanel(wx
.Panel
):
551 def __init__(self
, parent
, id):
552 wx
.Panel
.__init
__(self
, parent
, id)
553 pathLabel
= wx
.StaticText(self
, -1, _("python.exe Path:"))
554 config
= wx
.ConfigBase_Get()
555 path
= config
.Read("ActiveGridPythonLocation")
556 self
._pathTextCtrl
= wx
.TextCtrl(self
, -1, path
, size
= (150, -1))
557 self
._pathTextCtrl
.SetToolTipString(self
._pathTextCtrl
.GetValue())
558 self
._pathTextCtrl
.SetInsertionPointEnd()
559 choosePathButton
= wx
.Button(self
, -1, _("Browse..."))
560 pathSizer
= wx
.BoxSizer(wx
.HORIZONTAL
)
563 pathSizer
.Add(pathLabel
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.LEFT|wx
.TOP
, HALF_SPACE
)
564 pathSizer
.Add(self
._pathTextCtrl
, 1, wx
.EXPAND|wx
.LEFT|wx
.TOP
, HALF_SPACE
)
565 pathSizer
.Add(choosePathButton
, 0, wx
.ALIGN_RIGHT|wx
.LEFT|wx
.RIGHT|wx
.TOP
, HALF_SPACE
)
566 wx
.EVT_BUTTON(self
, choosePathButton
.GetId(), self
.OnChoosePath
)
567 mainSizer
= wx
.BoxSizer(wx
.VERTICAL
)
568 mainSizer
.Add(pathSizer
, 0, wx
.EXPAND|wx
.LEFT|wx
.RIGHT|wx
.TOP
, SPACE
)
570 self
._otherOptions
= STCTextEditor
.TextOptionsPanel(self
, -1, configPrefix
= "Python", label
= "Python", hasWordWrap
= True, hasTabs
= True, addPage
=False)
571 mainSizer
.Add(self
._otherOptions
, 0, wx
.EXPAND|wx
.BOTTOM
, SPACE
)
572 self
.SetSizer(mainSizer
)
573 parent
.AddPage(self
, _("Python"))
576 def OnChoosePath(self
, event
):
577 defaultDir
= os
.path
.dirname(self
._pathTextCtrl
.GetValue().strip())
578 defaultFile
= os
.path
.basename(self
._pathTextCtrl
.GetValue().strip())
580 wildcard
= _("Executable (*.exe)|*.exe|All (*.*)|*.*")
582 defaultFile
= "python.exe"
585 dlg
= wx
.FileDialog(wx
.GetApp().GetTopWindow(),
587 defaultDir
=defaultDir
,
588 defaultFile
=defaultFile
,
590 style
=wx
.OPEN|wx
.FILE_MUST_EXIST|wx
.HIDE_READONLY
)
591 # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog
592 if dlg
.ShowModal() == wx
.ID_OK
:
595 self
._pathTextCtrl
.SetValue(path
)
596 self
._pathTextCtrl
.SetToolTipString(self
._pathTextCtrl
.GetValue())
597 self
._pathTextCtrl
.SetInsertionPointEnd()
601 def OnOK(self
, optionsDialog
):
602 config
= wx
.ConfigBase_Get()
603 config
.Write("ActiveGridPythonLocation", self
._pathTextCtrl
.GetValue().strip())
605 self
._otherOptions
.OnOK(optionsDialog
)
609 return getPythonIcon()
612 #----------------------------------------------------------------------------
613 # Icon Bitmaps - generated by encode_bitmaps.py
614 #----------------------------------------------------------------------------
615 from wx
import ImageFromStream
, BitmapFromImage
621 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
622 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
623 \x00\x01\xe7IDAT8\x8d}\x921h\x13Q\x18\xc7\x7fw\xb9\x0ei\x9d*\xbd\xeb\x10\x8f\
624 ,\x99\x1c*A[\xaa\x19B\xe8\xd0\xb1\x0e%K\x87\x88T2\x88Cqp\tD\x14i\xe9\xe0V\
625 \xdaQ\xb7\xe0P\xa1\x8b\xa0(\x95$z\xd5Q1\x90\xa2\xd7\x9a4^\x87\xa0`\x92!w9\
626 \x87\xf8.\xb9\xa6\xc97\xbd\xef{\xef\xfb\xbd\xff\xfb\xbfO*~;v\xf9\x1f\xad\xba\
627 \x05@\xf9\xd4\x06\xc0::$\xbb\x96\x92\x18\x11\n@(4\xdd\xcdB\xd3\xd4\x1d\x85\
628 \x8b\x97\xe1\xe3;\x83\x99\xe5\x15\xb2\xe0\x8e\x82\xc8\xa3\xe8\x003\xcb+\xac\
629 \xaee\xdda\xfb\xb2\x90\rPw\x14\x00\x9a\xb5\n\xbf\xfflSz\x9d\xa2Y\xdc"zca\xe8\
630 \x05\xb2h\x14\xcd\xd0\xf3B\x9f\x98\xe5\xf9\xde\x13"\xaaB\xc7\xb1\xcfU!\x0b\
631 \xc3D4k\x15\xac\x93\x03\xf4\x89Y\xaf\x96\xffT\x028\x17\xa2\xf4\'\xcdZ\x85\
632 \xf7F\x06{\xaa\x80ev\xc1\x91\xb91>\x18\x0f\xb8\xb7\x95a\xe9\xca\x0b:\x8e\xed\
633 \xca\x01E\x1a\x00\x98\r\x89\x92\x91\xa1\xda\xd8\x87\x06ha\x1f\x1b\x80\xcd\
634 \x9d%\xe0\xa5\x0f"[G\x87\x98\x8d\xde/ia\x05-\xac`\x996\xf9\\\x0b\xcb\xb4)\
635 \x1bmOMn\xf7\xd5\xf0\'\\\x8b\xdces\xe7\x8d\xef\x80h\xd6\xc2\n\xf9\\\x0b]\xf5\
636 \xab\xf2\xcdApR#\xf1kp4b\xc9 \xf9\\\x0b\x80\xe4\xcdE\xaf\xdeqlW\xaeVL\xaf`~\
637 \xd9\x03@W\xd3\x00\xc4\x13\x0b\xc4\x92A\xcf\xd0\xf9\xe8:\x89\xebW\x01(|\xfd\
638 \xe1\xbe-~F\xbas\xff\x91\xf75\x82n\x9d\x1c\xf0}\xfciw\xdd\xe7A<\xd1\x1b\xa8j\
639 c\x9f\xb2\xd1F\x92\xe4\x80O\x12\xc0\xc6\xb3\x14\xf6Ta\xe0)g\x81\xba\x9a\xf6\
640 \x9b(\x07\x14I@\x84lq\xb8?\xe6\xa3\xeb\x00\xdc\xba\x9d\xf4+\x10*~\xfem\xf3\
641 \xf8\xe1\x06\xc7\xa7\xdb\xe8j\x9a\xf8\xdc\xa4\xb7\x1f[\\\xe5\xd2\x851/\xff\
642 \x07\xac\x9b\xd1e\x12\x96\x0f\xfd\x00\x00\x00\x00IEND\xaeB`\x82'
645 def getPythonBitmap():
646 return BitmapFromImage(getPythonImage())
648 def getPythonImage():
649 stream
= cStringIO
.StringIO(getPythonData())
650 return ImageFromStream(stream
)
653 return wx
.IconFromBitmap(getPythonBitmap())