~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to wxPython/src/_core_ex.py

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#----------------------------------------------------------------------------
 
2
 
 
3
# Use Python's bool constants if available, make some if not
 
4
try:
 
5
    True
 
6
except NameError:
 
7
    __builtins__.True = 1==1
 
8
    __builtins__.False = 1==0
 
9
    def bool(value): return not not value
 
10
    __builtins__.bool = bool
 
11
 
 
12
 
 
13
 
 
14
# workarounds for bad wxRTTI names
 
15
__wxPyPtrTypeMap['wxGauge95']    = 'wxGauge'
 
16
__wxPyPtrTypeMap['wxSlider95']   = 'wxSlider'
 
17
__wxPyPtrTypeMap['wxStatusBar95']   = 'wxStatusBar'
 
18
 
 
19
 
 
20
#----------------------------------------------------------------------------
 
21
# Load version numbers from __version__...  Ensure that major and minor
 
22
# versions are the same for both wxPython and wxWidgets.
 
23
 
 
24
from __version__ import *
 
25
__version__ = VERSION_STRING
 
26
 
 
27
assert MAJOR_VERSION == _core_.MAJOR_VERSION, "wxPython/wxWidgets version mismatch"
 
28
assert MINOR_VERSION == _core_.MINOR_VERSION, "wxPython/wxWidgets version mismatch"
 
29
if RELEASE_VERSION != _core_.RELEASE_VERSION:
 
30
    import warnings
 
31
    warnings.warn("wxPython/wxWidgets release number mismatch")
 
32
 
 
33
 
 
34
def version():
 
35
    """Returns a string containing version and port info"""
 
36
    if wx.Platform == '__WXMSW__':
 
37
        port = 'msw'
 
38
    elif wx.Platform == '__WXMAC__':
 
39
        if 'wxOSX-carbon' in wx.PlatformInfo:
 
40
            port = 'osx-carbon'
 
41
        else:
 
42
            port = 'osx-cocoa'
 
43
    elif wx.Platform == '__WXGTK__':
 
44
        port = 'gtk'
 
45
        if 'gtk2' in wx.PlatformInfo:
 
46
            port = 'gtk2'
 
47
    else:
 
48
        port = '?'
 
49
 
 
50
    return "%s %s (classic)" % (wx.VERSION_STRING, port)
 
51
                      
 
52
    
 
53
#----------------------------------------------------------------------------
 
54
 
 
55
# Set wxPython's default string<-->unicode conversion encoding from
 
56
# the locale, but only if Python's default hasn't been changed.  (We
 
57
# assume that if the user has customized it already then that is the
 
58
# encoding we need to use as well.)
 
59
#
 
60
# The encoding selected here is used when string or unicode objects
 
61
# need to be converted in order to pass them to wxWidgets.  Please be
 
62
# aware that the default encoding within the same locale may be
 
63
# slightly different on different platforms.  For example, please see
 
64
# http://www.alanwood.net/demos/charsetdiffs.html for differences
 
65
# between the common latin/roman encodings.
 
66
 
 
67
default = _sys.getdefaultencoding()
 
68
if default == 'ascii':
 
69
    import locale
 
70
    import codecs
 
71
    try:
 
72
        if hasattr(locale, 'getpreferredencoding'):
 
73
            default = locale.getpreferredencoding()
 
74
        else:
 
75
            default = locale.getdefaultlocale()[1]
 
76
        codecs.lookup(default)
 
77
    except (ValueError, LookupError, TypeError):
 
78
        default = _sys.getdefaultencoding()
 
79
    del locale
 
80
    del codecs
 
81
if default:
 
82
    wx.SetDefaultPyEncoding(default)
 
83
del default
 
84
 
 
85
#----------------------------------------------------------------------------
 
86
 
 
87
class PyDeadObjectError(AttributeError):
 
88
    pass
 
89
 
 
90
class _wxPyDeadObject(object):
 
91
    """
 
92
    Instances of wx objects that are OOR capable will have their __class__
 
93
    changed to this class when the C++ object is deleted.  This should help
 
94
    prevent crashes due to referencing a bogus C++ pointer.
 
95
    """
 
96
    reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
 
97
    attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
 
98
 
 
99
    def __repr__(self):
 
100
        if not hasattr(self, "_name"):
 
101
            self._name = "[unknown]"
 
102
        return self.reprStr % self._name
 
103
 
 
104
    def __getattr__(self, *args):
 
105
        if not hasattr(self, "_name"):
 
106
            self._name = "[unknown]"
 
107
        raise PyDeadObjectError(self.attrStr % self._name)
 
108
 
 
109
    def __nonzero__(self):
 
110
        return 0
 
111
 
 
112
 
 
113
 
 
114
class PyUnbornObjectError(AttributeError):
 
115
    pass
 
116
 
 
117
class _wxPyUnbornObject(object):
 
118
    """
 
119
    Some stock objects are created when the wx._core module is
 
120
    imported, but their C++ instance is not created until the wx.App
 
121
    object is created and initialized.  These object instances will
 
122
    temporarily have their __class__ changed to this class so an
 
123
    exception will be raised if they are used before the C++ instance
 
124
    is ready.
 
125
    """
 
126
 
 
127
    reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)"
 
128
    attrStr = "The C++ part of this object has not been initialized, attribute access not allowed."
 
129
 
 
130
    def __repr__(self):
 
131
        #if not hasattr(self, "_name"):
 
132
        #    self._name = "[unknown]"
 
133
        return self.reprStr #% self._name
 
134
 
 
135
    def __getattr__(self, *args):
 
136
        #if not hasattr(self, "_name"):
 
137
        #    self._name = "[unknown]"
 
138
        raise PyUnbornObjectError(self.attrStr) # % self._name )
 
139
 
 
140
    def __nonzero__(self):
 
141
        return 0
 
142
 
 
143
 
 
144
#----------------------------------------------------------------------------
 
145
 
 
146
def CallAfter(callableObj, *args, **kw):
 
147
    """
 
148
    Call the specified function after the current and pending event
 
149
    handlers have been completed.  This is also good for making GUI
 
150
    method calls from non-GUI threads.  Any extra positional or
 
151
    keyword args are passed on to the callable when it is called.
 
152
 
 
153
    :see: `wx.CallLater`
 
154
    """
 
155
    assert callable(callableObj), "callableObj is not callable"
 
156
    app = wx.GetApp()
 
157
    assert app is not None, 'No wx.App created yet'
 
158
 
 
159
    if not hasattr(app, "_CallAfterId"):
 
160
        app._CallAfterId = wx.NewEventType()
 
161
        app.Connect(-1, -1, app._CallAfterId,
 
162
                    lambda event: event.callable(*event.args, **event.kw) )
 
163
    evt = wx.PyEvent()
 
164
    evt.SetEventType(app._CallAfterId)
 
165
    evt.callable = callableObj
 
166
    evt.args = args
 
167
    evt.kw = kw
 
168
    wx.PostEvent(app, evt)
 
169
 
 
170
#----------------------------------------------------------------------------
 
171
 
 
172
 
 
173
class CallLater:
 
174
    """
 
175
    A convenience class for `wx.Timer`, that calls the given callable
 
176
    object once after the given amount of milliseconds, passing any
 
177
    positional or keyword args.  The return value of the callable is
 
178
    availbale after it has been run with the `GetResult` method.
 
179
 
 
180
    If you don't need to get the return value or restart the timer
 
181
    then there is no need to hold a reference to this object.  It will
 
182
    hold a reference to itself while the timer is running (the timer
 
183
    has a reference to self.Notify) but the cycle will be broken when
 
184
    the timer completes, automatically cleaning up the wx.CallLater
 
185
    object.
 
186
 
 
187
    :see: `wx.CallAfter`
 
188
    """
 
189
    def __init__(self, millis, callableObj, *args, **kwargs):
 
190
        assert callable(callableObj), "callableObj is not callable"
 
191
        self.millis = millis
 
192
        self.callable = callableObj
 
193
        self.SetArgs(*args, **kwargs)
 
194
        self.runCount = 0
 
195
        self.running = False
 
196
        self.hasRun = False
 
197
        self.result = None
 
198
        self.timer = None
 
199
        self.Start()
 
200
 
 
201
    def __del__(self):
 
202
        self.Stop()
 
203
 
 
204
 
 
205
    def Start(self, millis=None, *args, **kwargs):
 
206
        """
 
207
        (Re)start the timer
 
208
        """
 
209
        self.hasRun = False
 
210
        if millis is not None:
 
211
            self.millis = millis
 
212
        if args or kwargs:
 
213
            self.SetArgs(*args, **kwargs)
 
214
        self.Stop()
 
215
        self.timer = wx.PyTimer(self.Notify)
 
216
        self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
 
217
        self.running = True
 
218
    Restart = Start
 
219
 
 
220
 
 
221
    def Stop(self):
 
222
        """
 
223
        Stop and destroy the timer.
 
224
        """
 
225
        if self.timer is not None:
 
226
            self.timer.Stop()
 
227
            self.timer = None
 
228
 
 
229
 
 
230
    def GetInterval(self):
 
231
        if self.timer is not None:
 
232
            return self.timer.GetInterval()
 
233
        else:
 
234
            return 0
 
235
 
 
236
 
 
237
    def IsRunning(self):
 
238
        return self.timer is not None and self.timer.IsRunning()
 
239
 
 
240
 
 
241
    def SetArgs(self, *args, **kwargs):
 
242
        """
 
243
        (Re)set the args passed to the callable object.  This is
 
244
        useful in conjunction with Restart if you want to schedule a
 
245
        new call to the same callable object but with different
 
246
        parameters.
 
247
        """
 
248
        self.args = args
 
249
        self.kwargs = kwargs
 
250
 
 
251
 
 
252
    def HasRun(self):
 
253
        return self.hasRun
 
254
 
 
255
    def GetResult(self):
 
256
        return self.result
 
257
 
 
258
    def Notify(self):
 
259
        """
 
260
        The timer has expired so call the callable.
 
261
        """
 
262
        if self.callable and getattr(self.callable, 'im_self', True):
 
263
            self.runCount += 1
 
264
            self.running = False
 
265
            self.result = self.callable(*self.args, **self.kwargs)
 
266
        self.hasRun = True
 
267
        if not self.running:
 
268
            # if it wasn't restarted, then cleanup
 
269
            wx.CallAfter(self.Stop)
 
270
 
 
271
    Interval = property(GetInterval)
 
272
    Result = property(GetResult)
 
273
 
 
274
 
 
275
class FutureCall(CallLater):
 
276
    """A compatibility alias for `CallLater`."""
 
277
 
 
278
#----------------------------------------------------------------------------
 
279
# Control which items in this module should be documented by epydoc.
 
280
# We allow only classes and functions, which will help reduce the size
 
281
# of the docs by filtering out the zillions of constants, EVT objects,
 
282
# and etc that don't make much sense by themselves, but are instead
 
283
# documented (or will be) as part of the classes/functions/methods
 
284
# where they should be used.
 
285
 
 
286
class __DocFilter:
 
287
    """
 
288
    A filter for epydoc that only allows non-Ptr classes and
 
289
    functions, in order to reduce the clutter in the API docs.
 
290
    """
 
291
    def __init__(self, globals):
 
292
        self._globals = globals
 
293
        
 
294
    def __call__(self, name):
 
295
        import types
 
296
        obj = self._globals.get(name, None)
 
297
 
 
298
        # only document classes and function
 
299
        if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]:
 
300
            return False
 
301
 
 
302
        # skip other things that are private or will be documented as part of somethign else
 
303
        if name.startswith('_') or name.startswith('EVT') or name.endswith('_swigregister')  or name.endswith('Ptr') :
 
304
            return False
 
305
 
 
306
        # skip functions that are duplicates of static functions in a class
 
307
        if name.find('_') != -1:
 
308
            cls = self._globals.get(name.split('_')[0], None)
 
309
            methname = name.split('_')[1]
 
310
            if hasattr(cls, methname) and type(getattr(cls, methname)) is types.FunctionType:
 
311
                return False
 
312
            
 
313
        return True
 
314
 
 
315
#----------------------------------------------------------------------------
 
316
#----------------------------------------------------------------------------
 
317
 
 
318
# Import other modules in this package that should show up in the
 
319
# "core" wx namespace
 
320
from _gdi import *
 
321
from _windows import *
 
322
from _controls import *
 
323
from _misc import *
 
324
 
 
325
#----------------------------------------------------------------------------
 
326
#----------------------------------------------------------------------------