Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rudimentary support for _tkinter in GraalPy #381

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add rudimentary support for _tkinter in GraalPy
This commit adds the _tkinter module to the list of built-in modules to allow use of tkinter.
Before use, the bindings need to be built using tklib_build.py.
The code was modified from existing code in PyPy's main branch.

Right now, opening a window under Linux works, but still crashes on interacting with UI elements such as buttons.
It seems like there is a bug in the `cffi` module causing a SegFault.
macOS complains about other threads accessing the main window and the build script has some trouble finding the correct library for Tcl and Tk, as macOS comes with an older version preinstalled.
Windows was not tested.

Co-authored-by: Margarete Dippel <margarete.dippel@student.hpi.de>
Co-authored-by: Tim Felgentreff <tim.felgentreff@oracle.com>
  • Loading branch information
3 people committed Feb 9, 2024
commit cd60e90351777881958e2489339a7308398876a8
55 changes: 55 additions & 0 deletions graalpython/lib-python/3/_tkinter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# _tkinter package -- low-level interface to libtk and libtcl.
#
# This is an internal module, applications should "import tkinter" instead.
#
# This version is based PyPy which itself is based on cffi, and is a translation of _tkinter.c
# from CPython, version 2.7.4.

import sys

class TclError(Exception):
pass

from .tklib_cffi import ffi as tkffi, lib as tklib

from .app import TkApp
from .tclobj import TclObject as Tcl_Obj
from .app import FromTclString, ToTCLString

TK_VERSION = FromTclString(tkffi.string(tklib.get_tk_version()))
TCL_VERSION = FromTclString(tkffi.string(tklib.get_tcl_version()))

READABLE = tklib.TCL_READABLE
WRITABLE = tklib.TCL_WRITABLE
EXCEPTION = tklib.TCL_EXCEPTION
DONT_WAIT = tklib.TCL_DONT_WAIT

def create(screenName=None, baseName=None, className=None,
interactive=False, wantobjects=False, wantTk=True,
sync=False, use=None):
return TkApp(screenName, baseName, className,
interactive, wantobjects, wantTk, sync, use)

def dooneevent(flags=0):
return tklib.Tcl_DoOneEvent(flags)


def _flatten(item):
def _flatten1(output, item, depth):
if depth > 1000:
raise ValueError("nesting too deep in _flatten")
if not isinstance(item, (list, tuple)):
raise TypeError("argument must be sequence")
# copy items to output tuple
for o in item:
if isinstance(o, (list, tuple)):
_flatten1(output, o, depth + 1)
elif o is not None:
output.append(o)

result = []
_flatten1(result, item, 0)
return tuple(result)

# Encoding is not specified explicitly, but "must be passed argv[0]" sounds like a simple conversion to raw bytes.
tklib.Tcl_FindExecutable(ToTCLString(sys.executable))
Loading