mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
gh-157514: Add structured version info for tkinter (GH-157516)
Add constants tkinter.TCL_VERSION_INFO and tkinter.TK_VERSION_INFO, named tuples with the versions of the Tcl and Tk libraries that were used for building the module, and _tkinter.TCL_PATCH_LEVEL and _tkinter.TK_PATCH_LEVEL strings. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
cbecd5edd9
commit
4a5a7b9f6d
7 files changed
+98
-25
No files matched your search
@@ -6898,3 +6898,32 @@ and :mod:`!tkinter.constants` namespaces.
|
||||
DOTBOX
|
||||
|
||||
Other option values: ``'underline'``, ``'numeric'`` and ``'dotbox'``.
|
||||
|
||||
|
||||
Version information
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. data:: TCL_VERSION_INFO
|
||||
TK_VERSION_INFO
|
||||
|
||||
The versions of the Tcl and Tk libraries that were used for building
|
||||
the :mod:`!_tkinter` module, as named tuples with the same five fields
|
||||
as :data:`sys.version_info`: *major*, *minor*, *micro*, *releaselevel*
|
||||
and *serial*.
|
||||
*releaselevel* is ``'alpha'``, ``'beta'`` or ``'final'``.
|
||||
Converting them to a string gives the version in the usual Tcl/Tk notation,
|
||||
for example ``'9.0.3'`` for a final release or ``'9.1b2'`` for a
|
||||
pre-release.
|
||||
These may be different from the libraries actually used at runtime,
|
||||
which are available as :meth:`Misc.info_patchlevel` (the Tcl version)
|
||||
and the ``tk_patchLevel`` Tcl variable.
|
||||
|
||||
.. versionadded:: next
|
||||
|
||||
.. data:: TkVersion
|
||||
TclVersion
|
||||
|
||||
The major and minor version of the Tk and Tcl libraries that were used
|
||||
for building the :mod:`!_tkinter` module, as floats, for example ``8.6``.
|
||||
Prefer :data:`TK_VERSION_INFO` and :data:`TCL_VERSION_INFO`, which are
|
||||
more precise and compare correctly.
|
||||
@@ -632,6 +632,11 @@ tkinter
|
||||
methods (without recursion) also work on Tk older than 9.1.
|
||||
(Contributed by Serhiy Storchaka in :gh:`151910`.)
|
||||
|
||||
* Added constants :const:`~tkinter.TCL_VERSION_INFO` and
|
||||
:const:`~tkinter.TK_VERSION_INFO`, named tuples with the versions of
|
||||
the Tcl and Tk libraries that were used for building the module.
|
||||
(Contributed by Serhiy Storchaka in :gh:`157514`.)
|
||||
|
||||
* Added new :class:`!tkinter.Text` methods :meth:`~tkinter.Text.edit_canundo`
|
||||
and :meth:`~tkinter.Text.edit_canredo` which return whether an undo or redo
|
||||
is possible.
|
||||
|
||||
@@ -491,7 +491,7 @@ def collect_tkinter(info_add):
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
attributes = ('TK_VERSION', 'TCL_VERSION')
|
||||
attributes = ('TK_PATCH_LEVEL', 'TCL_PATCH_LEVEL')
|
||||
copy_attributes(info_add, _tkinter, 'tkinter.%s', attributes)
|
||||
|
||||
try:
|
||||
|
||||
@@ -9,6 +9,7 @@ import textwrap
|
||||
import time
|
||||
import unittest
|
||||
import weakref
|
||||
import _tkinter
|
||||
import tkinter
|
||||
from tkinter import TclError, ttk
|
||||
import enum
|
||||
@@ -24,6 +25,49 @@ from test.test_tkinter.support import (AbstractTkTest, AbstractDefaultRootTest,
|
||||
|
||||
support.requires('gui')
|
||||
|
||||
def check_version_info(test, vi):
|
||||
# The following is almost a copy of tests for sys.version_info.
|
||||
test.assertIsInstance(vi[:], tuple)
|
||||
test.assertEqual(len(vi), 5)
|
||||
test.assertIsInstance(vi[0], int)
|
||||
test.assertIsInstance(vi[1], int)
|
||||
test.assertIsInstance(vi[2], int)
|
||||
test.assertIn(vi[3], ("alpha", "beta", "candidate", "final"))
|
||||
test.assertIsInstance(vi[4], int)
|
||||
test.assertIsInstance(vi.major, int)
|
||||
test.assertIsInstance(vi.minor, int)
|
||||
test.assertIsInstance(vi.micro, int)
|
||||
test.assertIn(vi.releaselevel, ("alpha", "beta", "final"))
|
||||
test.assertIsInstance(vi.serial, int)
|
||||
test.assertEqual(vi[0], vi.major)
|
||||
test.assertEqual(vi[1], vi.minor)
|
||||
test.assertEqual(vi[2], vi.micro)
|
||||
test.assertEqual(vi[3], vi.releaselevel)
|
||||
test.assertEqual(vi[4], vi.serial)
|
||||
test.assertTrue(vi > (1,0,0))
|
||||
if vi.releaselevel == 'final':
|
||||
test.assertEqual(vi.serial, 0)
|
||||
else:
|
||||
test.assertEqual(vi.micro, 0)
|
||||
test.assertStartsWith(str(vi), f'{vi.major}.{vi.minor}')
|
||||
|
||||
|
||||
class VersionTest(unittest.TestCase):
|
||||
|
||||
def test_version_info(self):
|
||||
for vi, version, patchlevel in (
|
||||
(tkinter.TCL_VERSION_INFO, _tkinter.TCL_VERSION, _tkinter.TCL_PATCH_LEVEL),
|
||||
(tkinter.TK_VERSION_INFO, _tkinter.TK_VERSION, _tkinter.TK_PATCH_LEVEL),
|
||||
):
|
||||
with self.subTest(patchlevel=patchlevel):
|
||||
check_version_info(self, vi)
|
||||
self.assertEqual(str(vi), patchlevel)
|
||||
self.assertEqual(f'{vi.major}.{vi.minor}', version)
|
||||
self.assertEqual(tkinter.TclVersion,
|
||||
float(f'{tkinter.TCL_VERSION_INFO.major}.'
|
||||
f'{tkinter.TCL_VERSION_INFO.minor}'))
|
||||
|
||||
|
||||
class MiscTest(AbstractTkTest, unittest.TestCase):
|
||||
|
||||
def test_all(self):
|
||||
@@ -830,30 +874,10 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
|
||||
vi = self.root.info_patchlevel()
|
||||
f = tkinter.Frame(self.root)
|
||||
self.assertEqual(f.info_patchlevel(), vi)
|
||||
# The following is almost a copy of tests for sys.version_info.
|
||||
self.assertIsInstance(vi[:], tuple)
|
||||
self.assertEqual(len(vi), 5)
|
||||
self.assertIsInstance(vi[0], int)
|
||||
self.assertIsInstance(vi[1], int)
|
||||
self.assertIsInstance(vi[2], int)
|
||||
self.assertIn(vi[3], ("alpha", "beta", "candidate", "final"))
|
||||
self.assertIsInstance(vi[4], int)
|
||||
self.assertIsInstance(vi.major, int)
|
||||
self.assertIsInstance(vi.minor, int)
|
||||
self.assertIsInstance(vi.micro, int)
|
||||
self.assertIn(vi.releaselevel, ("alpha", "beta", "final"))
|
||||
self.assertIsInstance(vi.serial, int)
|
||||
self.assertEqual(vi[0], vi.major)
|
||||
self.assertEqual(vi[1], vi.minor)
|
||||
self.assertEqual(vi[2], vi.micro)
|
||||
self.assertEqual(vi[3], vi.releaselevel)
|
||||
self.assertEqual(vi[4], vi.serial)
|
||||
self.assertTrue(vi > (1,0,0))
|
||||
if vi.releaselevel == 'final':
|
||||
self.assertEqual(vi.serial, 0)
|
||||
else:
|
||||
self.assertEqual(vi.micro, 0)
|
||||
self.assertStartsWith(str(vi), f'{vi.major}.{vi.minor}')
|
||||
check_version_info(self, vi)
|
||||
# The Tcl library loaded at runtime should be compatible with
|
||||
# the one used for building the module.
|
||||
self.assertEqual(vi[:2], tkinter.TCL_VERSION_INFO[:2])
|
||||
|
||||
def test_embedded_null(self):
|
||||
widget = tkinter.Entry(self.root)
|
||||
|
||||
@@ -170,6 +170,9 @@ def _parse_version(version):
|
||||
releaselevel = {'a': 'alpha', 'b': 'beta'}[releaselevel]
|
||||
return _VersionInfoType(major, minor, micro, releaselevel, serial)
|
||||
|
||||
TCL_VERSION_INFO = _parse_version(_tkinter.TCL_PATCH_LEVEL)
|
||||
TK_VERSION_INFO = _parse_version(_tkinter.TK_PATCH_LEVEL)
|
||||
|
||||
|
||||
@enum._simple_enum(enum.StrEnum)
|
||||
class EventType:
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Add constants :const:`tkinter.TCL_VERSION_INFO` and
|
||||
:const:`tkinter.TK_VERSION_INFO`, named tuples with the versions of the Tcl
|
||||
and Tk libraries that were used for building the module, and
|
||||
``_tkinter.TCL_PATCH_LEVEL`` and ``_tkinter.TK_PATCH_LEVEL`` strings.
|
||||
@@ -3880,6 +3880,14 @@ PyInit__tkinter(void)
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
if (PyModule_AddStringConstant(m, "TK_PATCH_LEVEL", TK_PATCH_LEVEL)) {
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
if (PyModule_AddStringConstant(m, "TCL_PATCH_LEVEL", TCL_PATCH_LEVEL)) {
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Tkapp_Type = PyType_FromSpec(&Tkapp_Type_spec);
|
||||
if (PyModule_AddObjectRef(m, "TkappType", Tkapp_Type)) {
|
||||
|
||||
Reference in new issue
Block a user