mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 00:06:44 -04:00
dist: Add support for tkinter
Requires adding `tkinter` to `requirements.txt`. For now, wheels are only provided for Python 3.6 and up. Fixes #780
This commit is contained in:
parent
210f7aecfb
commit
6935d2badc
8
direct/src/dist/FreezeTool.py
vendored
8
direct/src/dist/FreezeTool.py
vendored
@ -2332,7 +2332,13 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fp = zip.open(fn.replace(os.path.sep, '/'), 'r')
|
zip_fn = fn.replace(os.path.sep, '/')
|
||||||
|
if zip_fn.startswith('deploy_libs/_tkinter.'):
|
||||||
|
# If we have a tkinter wheel on the path, ignore the
|
||||||
|
# _tkinter extension in deploy-libs.
|
||||||
|
if any(entry.endswith(".whl") and os.path.basename(entry).startswith("tkinter-") for entry in self.path):
|
||||||
|
return None
|
||||||
|
fp = zip.open(zip_fn, 'r')
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
57
direct/src/dist/commands.py
vendored
57
direct/src/dist/commands.py
vendored
@ -114,6 +114,7 @@ PACKAGE_DATA_DIRS = {
|
|||||||
],
|
],
|
||||||
'pytz': [('pytz/zoneinfo/*', 'zoneinfo', ())],
|
'pytz': [('pytz/zoneinfo/*', 'zoneinfo', ())],
|
||||||
'certifi': [('certifi/cacert.pem', '', {})],
|
'certifi': [('certifi/cacert.pem', '', {})],
|
||||||
|
'_tkinter_ext': [('_tkinter_ext/tcl/**', 'tcl', {})],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Some dependencies have extra directories that need to be scanned for DLLs.
|
# Some dependencies have extra directories that need to be scanned for DLLs.
|
||||||
@ -147,21 +148,6 @@ import __builtin__
|
|||||||
__builtin__.__import__ = __import__
|
__builtin__.__import__ = __import__
|
||||||
__builtin__.__file__ = sys.executable
|
__builtin__.__file__ = sys.executable
|
||||||
del __builtin__
|
del __builtin__
|
||||||
|
|
||||||
# Set the TCL_LIBRARY directory to the location of the Tcl/Tk/Tix files.
|
|
||||||
import os
|
|
||||||
tcl_dir = os.path.join(os.path.dirname(sys.executable), 'tcl')
|
|
||||||
if os.path.isdir(tcl_dir):
|
|
||||||
for dir in os.listdir(tcl_dir):
|
|
||||||
sub_dir = os.path.join(tcl_dir, dir)
|
|
||||||
if os.path.isdir(sub_dir):
|
|
||||||
if dir.startswith('tcl'):
|
|
||||||
os.environ['TCL_LIBRARY'] = sub_dir
|
|
||||||
if dir.startswith('tk'):
|
|
||||||
os.environ['TK_LIBRARY'] = sub_dir
|
|
||||||
if dir.startswith('tix'):
|
|
||||||
os.environ['TIX_LIBRARY'] = sub_dir
|
|
||||||
del os
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# site.py for Python 3.
|
# site.py for Python 3.
|
||||||
@ -196,7 +182,11 @@ def get_data(path):
|
|||||||
|
|
||||||
FrozenImporter.find_spec = find_spec
|
FrozenImporter.find_spec = find_spec
|
||||||
FrozenImporter.get_data = get_data
|
FrozenImporter.get_data = get_data
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This addendum is only needed for legacy tkinter handling, since the new
|
||||||
|
# tkinter package already contains this logic.
|
||||||
|
SITE_PY_TKINTER_ADDENDUM = """
|
||||||
# Set the TCL_LIBRARY directory to the location of the Tcl/Tk/Tix files.
|
# Set the TCL_LIBRARY directory to the location of the Tcl/Tk/Tix files.
|
||||||
import os
|
import os
|
||||||
tcl_dir = os.path.join(os.path.dirname(sys.executable), 'tcl')
|
tcl_dir = os.path.join(os.path.dirname(sys.executable), 'tcl')
|
||||||
@ -204,7 +194,7 @@ if os.path.isdir(tcl_dir):
|
|||||||
for dir in os.listdir(tcl_dir):
|
for dir in os.listdir(tcl_dir):
|
||||||
sub_dir = os.path.join(tcl_dir, dir)
|
sub_dir = os.path.join(tcl_dir, dir)
|
||||||
if os.path.isdir(sub_dir):
|
if os.path.isdir(sub_dir):
|
||||||
if dir.startswith('tcl'):
|
if dir.startswith('tcl') and os.path.isfile(os.path.join(sub_dir, 'init.tcl')):
|
||||||
os.environ['TCL_LIBRARY'] = sub_dir
|
os.environ['TCL_LIBRARY'] = sub_dir
|
||||||
if dir.startswith('tk'):
|
if dir.startswith('tk'):
|
||||||
os.environ['TK_LIBRARY'] = sub_dir
|
os.environ['TK_LIBRARY'] = sub_dir
|
||||||
@ -592,6 +582,7 @@ class build_apps(setuptools.Command):
|
|||||||
path = sys.path[:]
|
path = sys.path[:]
|
||||||
p3dwhl = None
|
p3dwhl = None
|
||||||
wheelpaths = []
|
wheelpaths = []
|
||||||
|
has_tkinter_wheel = False
|
||||||
|
|
||||||
if use_wheels:
|
if use_wheels:
|
||||||
wheelpaths = self.download_wheels(platform)
|
wheelpaths = self.download_wheels(platform)
|
||||||
@ -601,6 +592,8 @@ class build_apps(setuptools.Command):
|
|||||||
p3dwhlfn = whl
|
p3dwhlfn = whl
|
||||||
p3dwhl = self._get_zip_file(p3dwhlfn)
|
p3dwhl = self._get_zip_file(p3dwhlfn)
|
||||||
break
|
break
|
||||||
|
elif os.path.basename(whl).startswith('tkinter-'):
|
||||||
|
has_tkinter_wheel = True
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Missing panda3d wheel for platform: {}".format(platform))
|
raise RuntimeError("Missing panda3d wheel for platform: {}".format(platform))
|
||||||
|
|
||||||
@ -613,6 +606,11 @@ class build_apps(setuptools.Command):
|
|||||||
distutils.log.WARN
|
distutils.log.WARN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for whl in wheelpaths:
|
||||||
|
if os.path.basename(whl).startswith('tkinter-'):
|
||||||
|
has_tkinter_wheel = True
|
||||||
|
break
|
||||||
|
|
||||||
#whlfiles = {whl: self._get_zip_file(whl) for whl in wheelpaths}
|
#whlfiles = {whl: self._get_zip_file(whl) for whl in wheelpaths}
|
||||||
|
|
||||||
# Add whl files to the path so they are picked up by modulefinder
|
# Add whl files to the path so they are picked up by modulefinder
|
||||||
@ -756,9 +754,14 @@ class build_apps(setuptools.Command):
|
|||||||
return search_path
|
return search_path
|
||||||
|
|
||||||
def create_runtime(appname, mainscript, use_console):
|
def create_runtime(appname, mainscript, use_console):
|
||||||
|
site_py = SITE_PY
|
||||||
|
if not has_tkinter_wheel:
|
||||||
|
# Legacy handling for Tcl data files
|
||||||
|
site_py += SITE_PY_TKINTER_ADDENDUM
|
||||||
|
|
||||||
freezer = FreezeTool.Freezer(platform=platform, path=path)
|
freezer = FreezeTool.Freezer(platform=platform, path=path)
|
||||||
freezer.addModule('__main__', filename=mainscript)
|
freezer.addModule('__main__', filename=mainscript)
|
||||||
freezer.addModule('site', filename='site.py', text=SITE_PY)
|
freezer.addModule('site', filename='site.py', text=site_py)
|
||||||
for incmod in self.include_modules.get(appname, []) + self.include_modules.get('*', []):
|
for incmod in self.include_modules.get(appname, []) + self.include_modules.get('*', []):
|
||||||
freezer.addModule(incmod)
|
freezer.addModule(incmod)
|
||||||
for exmod in self.exclude_modules.get(appname, []) + self.exclude_modules.get('*', []):
|
for exmod in self.exclude_modules.get(appname, []) + self.exclude_modules.get('*', []):
|
||||||
@ -835,6 +838,12 @@ class build_apps(setuptools.Command):
|
|||||||
for appname, scriptname in self.console_apps.items():
|
for appname, scriptname in self.console_apps.items():
|
||||||
create_runtime(appname, scriptname, True)
|
create_runtime(appname, scriptname, True)
|
||||||
|
|
||||||
|
# Warn if tkinter is used but hasn't been added to requirements.txt
|
||||||
|
if not has_tkinter_wheel and '_tkinter' in freezer_modules:
|
||||||
|
# The on-windows-for-windows case is handled as legacy below
|
||||||
|
if sys.platform != "win32" or not platform.startswith('win'):
|
||||||
|
self.warn("Detected use of tkinter, but tkinter is not specified in requirements.txt!")
|
||||||
|
|
||||||
# Copy extension modules
|
# Copy extension modules
|
||||||
whl_modules = []
|
whl_modules = []
|
||||||
whl_modules_ext = ''
|
whl_modules_ext = ''
|
||||||
@ -849,6 +858,11 @@ class build_apps(setuptools.Command):
|
|||||||
if not any(i.endswith(suffix) for suffix in ext_suffixes):
|
if not any(i.endswith(suffix) for suffix in ext_suffixes):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if has_tkinter_wheel and i.startswith('deploy_libs/_tkinter.'):
|
||||||
|
# Ignore this one, we have a separate tkinter package
|
||||||
|
# nowadays that contains all the dependencies.
|
||||||
|
continue
|
||||||
|
|
||||||
base = os.path.basename(i)
|
base = os.path.basename(i)
|
||||||
module, _, ext = base.partition('.')
|
module, _, ext = base.partition('.')
|
||||||
whl_modules.append(module)
|
whl_modules.append(module)
|
||||||
@ -917,8 +931,8 @@ class build_apps(setuptools.Command):
|
|||||||
self.copy_with_dependencies(source_path, target_path, search_path)
|
self.copy_with_dependencies(source_path, target_path, search_path)
|
||||||
|
|
||||||
# Copy over the tcl directory.
|
# Copy over the tcl directory.
|
||||||
#TODO: get this to work on non-Windows platforms.
|
# This is legacy, we nowadays recommend the separate tkinter wheel.
|
||||||
if sys.platform == "win32" and platform.startswith('win'):
|
if sys.platform == "win32" and platform.startswith('win') and not has_tkinter_wheel:
|
||||||
tcl_dir = os.path.join(sys.prefix, 'tcl')
|
tcl_dir = os.path.join(sys.prefix, 'tcl')
|
||||||
tkinter_name = 'tkinter' if sys.version_info >= (3, 0) else 'Tkinter'
|
tkinter_name = 'tkinter' if sys.version_info >= (3, 0) else 'Tkinter'
|
||||||
|
|
||||||
@ -952,9 +966,14 @@ class build_apps(setuptools.Command):
|
|||||||
target_dir = os.path.join(builddir, target_dir)
|
target_dir = os.path.join(builddir, target_dir)
|
||||||
|
|
||||||
for wf in filenames:
|
for wf in filenames:
|
||||||
|
if wf.endswith('/'):
|
||||||
|
# Skip directories.
|
||||||
|
continue
|
||||||
|
|
||||||
if wf.lower().startswith(source_dir.lower() + '/'):
|
if wf.lower().startswith(source_dir.lower() + '/'):
|
||||||
if not srcglob.matches(wf.lower()):
|
if not srcglob.matches(wf.lower()):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
wf = wf.replace('/', os.sep)
|
wf = wf.replace('/', os.sep)
|
||||||
relpath = wf[len(source_dir) + 1:]
|
relpath = wf[len(source_dir) + 1:]
|
||||||
source_path = os.path.join(whl, wf)
|
source_path = os.path.join(whl, wf)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user