Cocoa Python broken in Leopard??

  • Hi,

    with every Xcode project template involving Python it is enough to add
    an

    import Quartz

    to any python file to hang the application with the icon jumping in
    the dock.
    From logs on the console it seems that the application isn't able to
    connect to the window server

    [Session started at 2007-11-07 08:43:05 +0100.]
    _RegisterApplication(), FAILED TO establish the default connection to
    the WindowServer, _CGSDefaultConnection() is NULL.
    2007-11-07 08:43:06.785 prova[3484:10b] *** -[NSRecursiveLock unlock]:
    lock (<NSRecursiveLock: 0x1f89e80> '(null)') unlocked when not locked
    2007-11-07 08:43:06.786 prova[3484:10b] *** Break on _NSLockError() to
    debug.
    2007-11-07 08:43:06.787 prova[3484:10b] *** -[NSRecursiveLock unlock]:
    lock (<NSRecursiveLock: 0x1f89e80> '(null)') unlocked when not locked
    2007-11-07 08:43:06.788 prova[3484:10b] *** Break on _NSLockError() to
    debug.
    2007-11-07 08:43:06.793 prova[3484:10b] *** -[NSRecursiveLock unlock]:
    lock (<NSRecursiveLock: 0x1f89e80> '(null)') unlocked when not locked
    2007-11-07 08:43:06.793 prova[3484:10b] *** Break on _NSLockError() to
    debug.
    2007-11-07 08:43:06.797 prova[3484:10b]
    NSInternalInconsistencyException - Error (1002) creating CGSWindow
    2007-11-07 08:43:06.801 prova[3484:10b] *** -[NSRecursiveLock unlock]:
    lock (<NSRecursiveLock: 0x1f89e80> '(null)') unlocked when not locked
    2007-11-07 08:43:06.802 prova[3484:10b] *** Break on _NSLockError() to
    debug.
    2007-11-07 08:43:06.803 prova[3484:10b] *** -[NSRecursiveLock unlock]:
    lock (<NSRecursiveLock: 0x1f89e80> '(null)') unlocked when not locked
    2007-11-07 08:43:06.803 prova[3484:10b] *** Break on _NSLockError() to
    debug.
    2007-11-07 08:43:06.804 prova[3484:10b] *** -[NSRecursiveLock unlock]:
    lock (<NSRecursiveLock: 0x1f89e80> '(null)') unlocked when not locked
    2007-11-07 08:43:06.804 prova[3484:10b] *** Break on _NSLockError() to
    debug.
    2007-11-07 08:43:06.806 prova[3484:10b] *** -[NSRecursiveLock unlock]:
    lock (<NSRecursiveLock: 0x1f89e80> '(null)') unlocked when not locked
    2007-11-07 08:43:06.806 prova[3484:10b] *** Break on _NSLockError() to
    debug.

    exactly the same happens building with py2app and the -A (alias)
    option enabled, instead py2app without the -A option builds an
    application who can happily connect to the windowserver.

    Cheers,

    uliano
  • On Nov 6, 2007, at 11:49 PM, Uliano Guerrini wrote:
    > with every Xcode project template involving Python it is enough to
    > add an
    >
    > import Quartz
    >
    > to any python file to hang the application with the icon jumping in
    > the dock.
    > From logs on the console it seems that the application isn't able to
    > connect to the window server
    .... error messages deleted ....

    Python's "import" works quite a bit differently than Objective-C's
    #import.  Namely, it will execute any code found in the imported
    modules that appears within the module's scope.

    The Quartz module requires a viable window server connection to be set
    up.  If you import Quartz in main.py or at the top level of your
    application delegate source file (or anywhere that is imported as a
    part of the app launching process prior to control being passed to the
    appkit), it'll blow up as you have seen.

    Instead, import Quartz in response to application initialization.  I
    dropped "import Quartz" into the standard Cocoa Python Application's
    applicationDidFinishLaunching_() method and it no longer bombs (I
    didn't test much further than that):

    class FoobarAppDelegate(NSObject):
        def applicationDidFinishLaunching_(self, sender):
            import Quartz
            NSLog("Application did finish launching.")

    b.bum
  • Il giorno 07/nov/07, alle ore 08:58, Bill Bumgarner ha scritto:

    > On Nov 6, 2007, at 11:49 PM, Uliano Guerrini wrote:
    >> with every Xcode project template involving Python it is enough to
    >> add an
    >>
    >> import Quartz
    >>
    >> to any python file to hang the application with the icon jumping in
    >> the dock.
    >> From logs on the console it seems that the application isn't able
    >> to connect to the window server
    > .... error messages deleted ....
    >
    > Python's "import" works quite a bit differently than Objective-C's
    > #import.  Namely, it will execute any code found in the imported
    > modules that appears within the module's scope.
    >
    > The Quartz module requires a viable window server connection to be
    > set up.  If you import Quartz in main.py or at the top level of your
    > application delegate source file (or anywhere that is imported as a
    > part of the app launching process prior to control being passed to
    > the appkit), it'll blow up as you have seen.
    >
    > Instead, import Quartz in response to application initialization.
    > I dropped "import Quartz" into the standard Cocoa Python
    > Application's applicationDidFinishLaunching_() method and it no
    > longer bombs (I didn't test much further than that):
    >
    > class FoobarAppDelegate(NSObject):
    > def applicationDidFinishLaunching_(self, sender):
    > import Quartz
    > NSLog("Application did finish launching.")
    >
    > b.bum

    the problem arises when you want to use Quartz "somewhere" to do
    something useful and this "somewhere" is likely to be some subclass of
    NSView (or some file imported in that subclass), well, if I'm not
    wrong, that subclass in order to work should be imported in the
    main.py file before

      AppHelper.runEventLoop()

    which is the call that fires up the window server

    anyway, py2app without aliasing works, in pyobjc-dev they say that
    they'll find to fix what to them seems a problem to be fixed
  • On Nov 7, 2007, at 12:46 AM, Uliano Guerrini wrote:
    > the problem arises when you want to use Quartz "somewhere" to do
    > something useful and this "somewhere" is likely to be some subclass
    > of NSView (or some file imported in that subclass), well, if I'm not
    > wrong, that subclass in order to work should be imported in the
    > main.py file before
    >
    > AppHelper.runEventLoop()
    >
    > which is the call that fires up the window server

    If you import it there, you get the errors as indicated by the OP for
    exactly the reason I described -- the Quartz module must be imported
    *after* the AppKit has brought up the Cocoa stack, including the
    window server connection, because the act of importing the Quartz
    module tickles the window server connection (among other things).

    Whether or not this is a bug in the Quartz module is semi-debatable.
    It is certainly inconvenient, but it is not unheard of for Python
    modules to behave this way.

    > anyway, py2app without aliasing works, in pyobjc-dev they say that
    > they'll find to fix what to them seems a problem to be fixed

    Actually, if you read the pyobjc-dev thread, it states quite
    explicitly that importing Quartz before AppHelper.runEventLoop()
    causes the problem *and* that this isn't necessarily a bug.

    b.bum
  • Il giorno 07/nov/07, alle ore 09:57, Bill Bumgarner ha scritto:

    > Whether or not this is a bug in the Quartz module is semi-
    > debatable.  It is certainly inconvenient, but it is not unheard of
    > for Python modules to behave this way.

    ok, maybe I'm not enough confident with pyobjc, but I would like to
    know how to use Quartz in, say, the drawRect method of  a subclass of
    NSView say myView

    If I don't import myView in the main.py the view isn't drawn, so let
    it be there

    If I import Quartz in myView.py I got the problem... if I don't how
    can the methods in myView.py know about Quarz?

    uliano
  • On Nov 7, 2007, at 1:41 AM, Uliano Guerrini wrote:
    > Il giorno 07/nov/07, alle ore 09:57, Bill Bumgarner ha scritto:
    >> Whether or not this is a bug in the Quartz module is semi-
    >> debatable.  It is certainly inconvenient, but it is not unheard of
    >> for Python modules to behave this way.
    > ok, maybe I'm not enough confident with pyobjc, but I would like to
    > know how to use Quartz in, say, the drawRect method of  a subclass
    > of NSView say myView
    >
    > If I don't import myView in the main.py the view isn't drawn, so let
    > it be there
    >
    > If I import Quartz in myView.py I got the problem... if I don't how
    > can the methods in myView.py know about Quarz?

    Import Quartz *after* the application's main event loop has been
    started, either in applicationDidFinishLaunching_() as I demonstrated
    in my first message:

    > class FoobarAppDelegate(NSObject):
    > def applicationDidFinishLaunching_(self, sender):
    > import Quartz

    Or import it as the first line of the drawRect_() method of your view.

    Unless you are explicitly subclassing something from the Quartz
    module, there is no need to import Quartz until you actually need it.
    Importing it in drawRect_() is inefficient, but not grossly so as
    Python short circuits the import of an already imported module.

    b.bum
  • Il giorno 07/nov/07, alle ore 17:48, Bill Bumgarner ha scritto:
    >
    > Import Quartz *after* the application's main event loop has been
    > started, either in applicationDidFinishLaunching_() as I
    > demonstrated in my first message:
    >
    >> class FoobarAppDelegate(NSObject):
    >> def applicationDidFinishLaunching_(self, sender):
    >> import Quartz

    this is useless as the scope of that import is limited to that
    function in that file

    >>
    >
    > Or import it as the first line of the drawRect_() method of your view.

    I found a better (much efficient, I hope) workaround:

    Quartz = None

    class MyView(NSView):
        def awakeFromNib(self):
            global Quartz
            Quartz = __import__('Quartz')

        def drawRect_(self, rect):
            context = NSGraphicsContext.currentContext().graphicsPort()
            Quartz.whatever()

    here the import happens to be called only once per class and Quartz is
    global to the whole file. Still it is not elegant but I can live with it

    cheers,

    uliano
  • On Nov 7, 2007, at 9:04 AM, Uliano Guerrini wrote:
    > Il giorno 07/nov/07, alle ore 17:48, Bill Bumgarner ha scritto:
    >> Import Quartz *after* the application's main event loop has been
    >> started, either in applicationDidFinishLaunching_() as I
    >> demonstrated in my first message:
    >>
    >>> class FoobarAppDelegate(NSObject):
    >>> def applicationDidFinishLaunching_(self, sender):
    >>> import Quartz
    >
    > this is useless as the scope of that import is limited to that
    > function in that file

    The overhead for re-importing is not much.

    >>> Or import it as the first line of the drawRect_() method of your
    >>> view.
    >
    > I found a better (much efficient, I hope) workaround:
    >
    > Quartz = None
    >
    > class MyView(NSView):
    > def awakeFromNib(self):
    > global Quartz
    > Quartz = __import__('Quartz')
    >
    > def drawRect_(self, rect):
    > context = NSGraphicsContext.currentContext().graphicsPort()
    > Quartz.whatever()
    >
    > here the import happens to be called only once per class and Quartz
    > is global to the whole file. Still it is not elegant but I can live
    > with it

    That isn't a workaround. That is one solution.  There isn't really a
    bug here.  This is just the way Python works -- some modules are
    designed such that their import has dependencies on certain other
    state pre-existing.  Quartz is one of them.

    Alternatively, if MyView exists as a part of an NSDocument, you could
    import MyView as a part of the NSDocument document loading mechanism.
    Since the class will be created in the ObjC runtime and instantiated
    by the loading of the NSDocument's NIB, no need to jump through the
    global/__import__hoops as per above (which, btw, are just fine and
    I'll add 'em to my recipes).

    b.bum
  • On 7 nov. 07, at 17:48, Bill Bumgarner wrote:

    > Import Quartz *after* the application's main event loop has been
    > started, either in applicationDidFinishLaunching_() as I
    > demonstrated in my first message:

    Actually, this should probably be "import Quartz *after* the
    application is connected to the window server", which is slightly
    different. In my different tests to find a workaround to this issue
    (which I still call a problem since this was working perfectly using
    PyObjC 1.4 on OS X 10.4, but maybe PyObjC 2 is actually fixing
    something which should never have worked to begin with ? :)), it
    looked like calling NSApplication.sharedApplication() early, and more
    importantly *before* importing Quartz, was allowing my alias builds
    to launch correctly.

    --
    Luc Heinrich
  • Il giorno 08/nov/07, alle ore 09:32, Luc Heinrich ha scritto:

    > it looked like calling NSApplication.sharedApplication() early, and
    > more importantly *before* importing Quartz, was allowing my alias
    > builds to launch correctly.

    can you give a simple skeleton example of that?

    uliano
  • On 8 nov. 07, at 13:00, Uliano Guerrini wrote:

    > can you give a simple skeleton example of that?

    Well, instead of doing:

    import SomeFrameworkWhichWantsToConnectToTheWindowServer
    ...
    appHelper.runEventLoop()

    I did:

    import AppKit
    AppKit.NSApplication.sharedApplication()
    ...
    import SomeFrameworkWhichWantsToConnectToTheWindowServer
    ...
    appHelper.runEventLoop()

    And I was able to launch my alias build correctly. In your case and
    in the case of the Quartz examples of the developer tools,
    'SomeFrameworkWhichWantsToConnectToTheWindowServer' is 'Quartz', in
    my case it's something else I haven't really identified yet.

    --
    Luc Heinrich
  • Il giorno 08/nov/07, alle ore 14:10, Luc Heinrich ha scritto:

    > I did:
    >
    > import AppKit
    > AppKit.NSApplication.sharedApplication()
    > ...
    > import SomeFrameworkWhichWantsToConnectToTheWindowServer
    > ...
    > appHelper.runEventLoop()

    I did try this stuff yesterday but unfortunately it doesn't do the trick

    I have no errors but the application window doesn't shows itself

    > And I was able to launch my alias build correctly. In your case and
    > in the case of the Quartz examples of the developer tools,
    > 'SomeFrameworkWhichWantsToConnectToTheWindowServer' is 'Quartz', in
    > my case it's something else I haven't really identified yet.

    so there is some difference in the problem (yes I agree it is) as seen
    from py2app or xcode vantage point

    (or maybe from Quartz and the something else causing your troubles)

    uliano
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today