Running Tk unit tests on Mac

I’m running on an M1 MacBook Pro, beta MacOS 14.3. I’m trying to get as many unit tests to run as possible (main branch, so the most current 3.13… version). When the test runner encounters a Tk-related test, it skips it with output like this:

0:00:00 load avg: 2.09 [1/1] test_ttk skipped (resource denied)
test_ttk skipped -- cannot run without OS X gui process

What is this OS X gui process it’s referring to? I don’t think it’s talking about XQuartz. I tried running make test ... in an xterm (or whatever XQuartz opens as a terminal window), but got the same output. I saw nothing in the dev guide testing section about Tk other than how to build tkinter on older versions of Python (pre-3.11). I’ve successfully built tkinter and ttk.

If someone can explain to me how to get past this, I’ll submit a devguide PR for it…

This is discussed in the Mac/README.rst file in the repo but it would be great to have this documented in the devguide.

The easiest way is to do a framework build of Python which will create a Python.app bundle within the framework and a launcher executable in the framework bin directory that will cause macOS to promote the Python interpreter process to a GUI process when needed, as in when running Tk via tkinter. For testing purposes, use the --enable-frameworks=<path_to>/Library/Frameworks as described there and doing a make install which will install everything within the <path_to> directory. When so installed, you can launch that python from <path_to>/bin/python3.x.

Beware of not specifying a non-default path, i.e. just specifying --enable-framework, because the make install will then default to installing in the system-wide /Library/Frameworks, /Applications, and /usr/local/bin directories which may override other user Python installations like those from python.org installers.

I tracked the source of the error down to a SetFrontProcess call in .Lib/test/support/__init__.py:

            if (  (app_services.GetCurrentProcess(psn_p) < 0) or
                  (app_services.SetFrontProcess(psn_p) < 0) ):
                reason = "cannot run without OS X gui process"

When called, it returns -606. Hunting around for that, I came across a GitHub comment by Jack Jansen in which he stated:

this is a known issue. On MacOSX you can only run GUI programs
if they are embedded in a ".app" bundle. If you do a framework
build of Python (see instructions in Mac/OSX/README) then in
addition to the "python" executable you will also get "pythonw"
which runs your script in such a .app bundle.

It seems I need to do a framework build, then presumably use the resulting .app bundle as $(PYTHON).

It seems I need to do a framework build, then presumably use the resulting .app bundle as $(PYTHON).

You do need to use a framework build but, somewhat counterintuitively, you don’t need to do anything with the resulting app bundle, that’s why it’s hidden away. Just use the bin/python3.x from the command line as you normally would.

And that pythonw comment is very out-of-date. There is no longer a separate pythonw.

The gui tests themselves are guarded with test.support.requires('gui'). ‘gui’ is the ‘resource denied’ in the skip message. On my MacBook Catalina, -ugui is required on the test command line, as with other systems.