236 lines
8.2 KiB
Python
236 lines
8.2 KiB
Python
"""
|
|
Define a category on NSObject with some useful methods.
|
|
"""
|
|
import sys
|
|
|
|
import objc
|
|
|
|
if sys.version_info[0] == 2:
|
|
|
|
def _str(v):
|
|
return v
|
|
|
|
exec(
|
|
"""\
|
|
def _raise(exc_type, exc_value, exc_trace):
|
|
raise exc_type, exc_value, exc_trace
|
|
"""
|
|
)
|
|
else:
|
|
|
|
def _str(v):
|
|
if isinstance(v, str):
|
|
return v
|
|
return v.decode("ascii")
|
|
|
|
def _raise(exc_type, exc_value, exc_trace):
|
|
raise exc_type(exc_value).with_traceback(exc_trace)
|
|
|
|
|
|
NSObject = objc.lookUpClass("NSObject")
|
|
|
|
|
|
class NSObject(objc.Category(NSObject)):
|
|
@objc.namedSelector(b"_pyobjc_performOnThread:")
|
|
def _pyobjc_performOnThread_(self, callinfo):
|
|
try:
|
|
sel, arg = callinfo
|
|
m = getattr(self, _str(sel))
|
|
m(arg)
|
|
except: # noqa: E722, B001
|
|
import traceback
|
|
|
|
traceback.print_exc(file=sys.stderr)
|
|
|
|
@objc.namedSelector(b"_pyobjc_performOnThreadWithResult:")
|
|
def _pyobjc_performOnThreadWithResult_(self, callinfo):
|
|
try:
|
|
sel, arg, result = callinfo
|
|
m = getattr(self, _str(sel))
|
|
r = m(arg)
|
|
result.append((True, r))
|
|
except: # noqa: E722, B001
|
|
result.append((False, sys.exc_info()))
|
|
|
|
if hasattr(NSObject, "performSelector_onThread_withObject_waitUntilDone_"):
|
|
|
|
@objc.namedSelector(
|
|
b"pyobjc_performSelector:onThread:withObject:waitUntilDone:"
|
|
)
|
|
def pyobjc_performSelector_onThread_withObject_waitUntilDone_(
|
|
self, aSelector, thread, arg, wait
|
|
):
|
|
"""
|
|
A version of performSelector:onThread:withObject:waitUntilDone: that
|
|
will log exceptions in the called method (instead of aborting the
|
|
NSRunLoop on the other thread).
|
|
"""
|
|
self.performSelector_onThread_withObject_waitUntilDone_(
|
|
b"_pyobjc_performOnThread:", thread, (aSelector, arg), wait
|
|
)
|
|
|
|
@objc.namedSelector(
|
|
b"pyobjc_performSelector:onThread:withObject:waitUntilDone:modes:"
|
|
)
|
|
def pyobjc_performSelector_onThread_withObject_waitUntilDone_modes_(
|
|
self, aSelector, thread, arg, wait, modes
|
|
):
|
|
"""
|
|
A version of performSelector:onThread:withObject:waitUntilDone:modes:
|
|
that will log exceptions in the called method (instead of aborting the
|
|
NSRunLoop on the other thread).
|
|
"""
|
|
self.performSelector_onThread_withObject_waitUntilDone_modes_(
|
|
b"_pyobjc_performOnThread:", thread, (aSelector, arg), wait, modes
|
|
)
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelector:withObject:afterDelay:")
|
|
def pyobjc_performSelector_withObject_afterDelay_(self, aSelector, arg, delay):
|
|
"""
|
|
A version of performSelector:withObject:afterDelay:
|
|
that will log exceptions in the called method (instead of aborting the
|
|
NSRunLoop).
|
|
"""
|
|
self.performSelector_withObject_afterDelay_(
|
|
b"_pyobjc_performOnThread:", (aSelector, arg), delay
|
|
)
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelector:withObject:afterDelay:inModes:")
|
|
def pyobjc_performSelector_withObject_afterDelay_inModes_(
|
|
self, aSelector, arg, delay, modes
|
|
):
|
|
"""
|
|
A version of performSelector:withObject:afterDelay:inModes:
|
|
that will log exceptions in the called method (instead of aborting the
|
|
NSRunLoop).
|
|
"""
|
|
self.performSelector_withObject_afterDelay_inModes_(
|
|
b"_pyobjc_performOnThread:", (aSelector, arg), delay, modes
|
|
)
|
|
|
|
if hasattr(NSObject, "performSelectorInBackground_withObject_"):
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelectorInBackground:withObject:")
|
|
def pyobjc_performSelectorInBackground_withObject_(self, aSelector, arg):
|
|
"""
|
|
A version of performSelectorInBackground:withObject:
|
|
that will log exceptions in the called method (instead of aborting the
|
|
NSRunLoop).
|
|
"""
|
|
self.performSelectorInBackground_withObject_(
|
|
b"_pyobjc_performOnThread:", (aSelector, arg)
|
|
)
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelectorOnMainThread:withObject:waitUntilDone:")
|
|
def pyobjc_performSelectorOnMainThread_withObject_waitUntilDone_(
|
|
self, aSelector, arg, wait
|
|
):
|
|
"""
|
|
A version of performSelectorOnMainThread:withObject:waitUntilDone:
|
|
that will log exceptions in the called method (instead of aborting the
|
|
NSRunLoop in the main thread).
|
|
"""
|
|
self.performSelectorOnMainThread_withObject_waitUntilDone_(
|
|
b"_pyobjc_performOnThread:", (aSelector, arg), wait
|
|
)
|
|
|
|
@objc.namedSelector(
|
|
b"pyobjc_performSelectorOnMainThread:withObject:waitUntilDone:modes:"
|
|
)
|
|
def pyobjc_performSelectorOnMainThread_withObject_waitUntilDone_modes_(
|
|
self, aSelector, arg, wait, modes
|
|
):
|
|
"""
|
|
A version of performSelectorOnMainThread:withObject:waitUntilDone:modes:
|
|
that will log exceptions in the called method (instead of aborting the
|
|
NSRunLoop in the main thread).
|
|
"""
|
|
self.performSelectorOnMainThread_withObject_waitUntilDone_modes_(
|
|
b"_pyobjc_performOnThread:", (aSelector, arg), wait, modes
|
|
)
|
|
|
|
# And some a some versions that return results
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelectorOnMainThread:withObject:modes:")
|
|
def pyobjc_performSelectorOnMainThread_withObject_modes_(
|
|
self, aSelector, arg, modes
|
|
):
|
|
"""
|
|
Simular to performSelectorOnMainThread:withObject:waitUntilDone:modes:,
|
|
but:
|
|
|
|
- always waits until done
|
|
- returns the return value of the called method
|
|
- if the called method raises an exception, this will raise the same
|
|
exception
|
|
"""
|
|
result = []
|
|
self.performSelectorOnMainThread_withObject_waitUntilDone_modes_(
|
|
b"_pyobjc_performOnThreadWithResult:", (aSelector, arg, result), True, modes
|
|
)
|
|
isOK, result = result[0]
|
|
|
|
if isOK:
|
|
return result
|
|
else:
|
|
exc_type, exc_value, exc_trace = result
|
|
_raise(exc_type, exc_value, exc_trace)
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelectorOnMainThread:withObject:")
|
|
def pyobjc_performSelectorOnMainThread_withObject_(self, aSelector, arg):
|
|
result = []
|
|
self.performSelectorOnMainThread_withObject_waitUntilDone_(
|
|
b"_pyobjc_performOnThreadWithResult:", (aSelector, arg, result), True
|
|
)
|
|
isOK, result = result[0]
|
|
|
|
if isOK:
|
|
return result
|
|
else:
|
|
exc_type, exc_value, exc_trace = result
|
|
_raise(exc_type, exc_value, exc_trace)
|
|
|
|
if hasattr(NSObject, "performSelector_onThread_withObject_waitUntilDone_"):
|
|
# These methods require Leopard, don't define them if the
|
|
# platform functionality isn't present.
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelector:onThread:withObject:modes:")
|
|
def pyobjc_performSelector_onThread_withObject_modes_(
|
|
self, aSelector, thread, arg, modes
|
|
):
|
|
result = []
|
|
self.performSelector_onThread_withObject_waitUntilDone_modes_(
|
|
b"_pyobjc_performOnThreadWithResult:",
|
|
thread,
|
|
(aSelector, arg, result),
|
|
True,
|
|
modes,
|
|
)
|
|
isOK, result = result[0]
|
|
|
|
if isOK:
|
|
return result
|
|
else:
|
|
exc_type, exc_value, exc_trace = result
|
|
_raise(exc_type, exc_value, exc_trace)
|
|
|
|
@objc.namedSelector(b"pyobjc_performSelector:onThread:withObject:")
|
|
def pyobjc_performSelector_onThread_withObject_(self, aSelector, thread, arg):
|
|
result = []
|
|
self.performSelector_onThread_withObject_waitUntilDone_(
|
|
b"_pyobjc_performOnThreadWithResult:",
|
|
thread,
|
|
(aSelector, arg, result),
|
|
True,
|
|
)
|
|
isOK, result = result[0]
|
|
|
|
if isOK:
|
|
return result
|
|
else:
|
|
exc_type, exc_value, exc_trace = result
|
|
_raise(exc_type, exc_value, exc_trace)
|
|
|
|
|
|
del NSObject
|