Commits

Ronald Oussoren  committed 1af4964

PyObjCTools.Debugging doesn't work with Python 3.x (issue #14)

This checking ensures that PyObjCTools.Debugging can work with python 3.x,
by removing "u" prefixes before unicode literals, adding "b" prefixes before
bytes literals and moving to print-as-a-function.

Also adds a minimal testsuite for the Debugging module, which is far from
perfect right now (it doesn't actually test that exception logging works)

  • Participants
  • Parent commits 33373e3

Comments (0)

Files changed (2)

File pyobjc-framework-ExceptionHandling/Lib/PyObjCTools/Debugging.py

   and AppKit will swallow most of them.  This means that you should never
   use this module in a release build.
 
-- Typical use involves only calling installDebuggingHandler or
-  installVerboseDebuggingHandler.  It may be removed at any time by calling
+- Typical use involves only calling installExceptionHandler or
+  installVerboseExceptionHandler.  It may be removed at any time by calling
   removeDebuggingHandler.
 """
+from __future__ import print_function
 
 from Foundation import NSObject, NSLog
 import objc
 
 __all__ = [
     'LOGSTACKTRACE', 'DEFAULTVERBOSITY', 'DEFAULTMASK', 'EVERYTHINGMASK',
-    'installDebuggingHandler', 'installVerboseDebuggingHandler',
-    'installPythonExceptionHandler', 'removeDebuggingHandler',
+    'installExceptionHandler', 'installVerboseExceptionHandler',
+    'installPythonExceptionHandler', 'removeExceptionHandler',
     'handlerInstalled',
 ]
 
 def isPythonException(exception):
-    return (exception.userInfo() or {}).get(u'__pyobjc_exc_type__') is not None
+    return (exception.userInfo() or {}).get('__pyobjc_exc_type__') is not None
 
 def nsLogPythonException(exception):
     userInfo = exception.userInfo()
-    NSLog(u'*** Python exception discarded!\n' +
+    NSLog('%@', '*** Python exception discarded!\n' +
         ''.join(traceback.format_exception(
-        userInfo[u'__pyobjc_exc_type__'],
-        userInfo[u'__pyobjc_exc_value__'],
-        userInfo[u'__pyobjc_exc_traceback__'],
+        userInfo['__pyobjc_exc_type__'],
+        userInfo['__pyobjc_exc_value__'],
+        userInfo['__pyobjc_exc_traceback__'],
     )).decode('utf8'))
     # we logged it, so don't log it for us
     return False
     pipe = os.popen('/usr/bin/atos -p %d %s' % (os.getpid(), stack))
     stacktrace = pipe.readlines()
     stacktrace.reverse()
-    NSLog(u"%@", u"*** ObjC exception '%s' (reason: '%s') discarded\n" % (
+    NSLog("%@", "*** ObjC exception '%s' (reason: '%s') discarded\n" % (
             exception.name(), exception.reason(),
         ) +
-        u'Stack trace (most recent call last):\n' +
+        'Stack trace (most recent call last):\n' +
         ''.join([('  '+line) for line in stacktrace]).decode('utf8')
     )
     return False
 DEFAULTVERBOSITY = 0
 
 class PyObjCDebuggingDelegate(NSObject):
-    verbosity = objc.ivar('verbosity', 'i')
+    verbosity = objc.ivar('verbosity', b'i')
     
     def initWithVerbosity_(self, verbosity):
         self = self.init()
         self.verbosity = verbosity
         return self
 
+    @objc.typedSelector(b'c@:@@I')
     def exceptionHandler_shouldLogException_mask_(self, sender, exception, aMask):
         try:
             if isPythonException(exception):
             else:
                 return False
         except:
-            print >>sys.stderr, "*** Exception occurred during exception handler ***"
+            print("*** Exception occurred during exception handler ***",
+                    file=sys.stderr)
             traceback.print_exc(sys.stderr)
             return True
-    exceptionHandler_shouldLogException_mask_ = objc.selector(exceptionHandler_shouldLogException_mask_, signature='c@:@@I')
 
+    @objc.typedSelector(b'c@:@@I')
     def exceptionHandler_shouldHandleException_mask_(self, sender, exception, aMask):
         return False
-    exceptionHandler_shouldHandleException_mask_ = objc.selector(exceptionHandler_shouldHandleException_mask_, signature='c@:@@I')
 
 def installExceptionHandler(verbosity=DEFAULTVERBOSITY, mask=DEFAULTMASK):
     """

File pyobjc-framework-ExceptionHandling/PyObjCTest/test_debugging.py

+'''
+Some simple tests to check that the framework is properly wrapped.
+'''
+import objc
+from PyObjCTools.TestSupport import *
+from PyObjCTools import Debugging
+
+try:
+    long
+except NameError:
+    long = int
+
+class TestDebugging (TestCase):
+    def testConstants(self):
+        for nm in (
+                'LOGSTACKTRACE', 'DEFAULTVERBOSITY', 
+                'DEFAULTMASK', 'EVERYTHINGMASK'):
+            self.assertTrue(hasattr(Debugging, nm))
+            self.assertTrue(isinstance(getattr(Debugging, nm), (int, long)))
+
+    def testHandlerBasic(self):
+        self.assertFalse(Debugging.handlerInstalled())
+
+        Debugging.installExceptionHandler()
+        self.assertTrue(Debugging.handlerInstalled())
+
+        Debugging.removeExceptionHandler()
+        self.assertFalse(Debugging.handlerInstalled())
+
+        Debugging.installVerboseExceptionHandler()
+        self.assertTrue(Debugging.handlerInstalled())
+
+        Debugging.removeExceptionHandler()
+        self.assertFalse(Debugging.handlerInstalled())
+
+        Debugging.installPythonExceptionHandler()
+        self.assertTrue(Debugging.handlerInstalled())
+
+        Debugging.removeExceptionHandler()
+        self.assertFalse(Debugging.handlerInstalled())
+
+
+    @expectedFailure
+    def testMisc(self):
+        self.fail("Actually test this module")
+        # - isPythonException
+        # - nsLogPythonException
+        # - nsLogObjCException
+        #
+        # - Actually trigger handler in various modes
+
+if __name__ == "__main__":
+    main()
+
+