summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/whatsnew/3.11.rst8
-rw-r--r--Lib/idlelib/help_about.py6
-rw-r--r--Lib/test/test_tcl.py12
-rw-r--r--Lib/tkinter/__init__.py28
-rw-r--r--Lib/tkinter/test/support.py10
-rw-r--r--Lib/tkinter/test/test_tkinter/test_misc.py29
-rw-r--r--Lib/tkinter/test/widget_tests.py2
-rw-r--r--Misc/NEWS.d/next/Library/2022-04-22-19-11-31.gh-issue-91827.6P3gOI.rst3
8 files changed, 75 insertions, 23 deletions
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index f679100..07e8332 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -744,6 +744,14 @@ For major changes, see :ref:`new-feat-related-type-hints-311`.
(Contributed by Serhiy Storchaka in :issue:`43923`.)
+tkinter
+-------
+
+* Added method ``info_patchlevel()`` which returns the exact version of
+ the Tcl library as a named tuple similar to :data:`sys.version_info`.
+ (Contributed by Serhiy Storchaka in :issue:`91827`.)
+
+
unicodedata
-----------
diff --git a/Lib/idlelib/help_about.py b/Lib/idlelib/help_about.py
index c59f494..9cb3ba7 100644
--- a/Lib/idlelib/help_about.py
+++ b/Lib/idlelib/help_about.py
@@ -76,8 +76,8 @@ class AboutDialog(Toplevel):
bg=self.bg, font=('courier', 24, 'bold'))
header.grid(row=0, column=0, sticky=E, padx=10, pady=10)
- tk_patchlevel = self.tk.call('info', 'patchlevel')
- ext = '.png' if tk_patchlevel >= '8.6' else '.gif'
+ tk_patchlevel = self.info_patchlevel()
+ ext = '.png' if tk_patchlevel >= (8, 6) else '.gif'
icon = os.path.join(os.path.abspath(os.path.dirname(__file__)),
'Icons', f'idle_48{ext}')
self.icon_image = PhotoImage(master=self._root(), file=icon)
@@ -105,7 +105,7 @@ class AboutDialog(Toplevel):
text='Python version: ' + version,
fg=self.fg, bg=self.bg)
pyver.grid(row=9, column=0, sticky=W, padx=10, pady=0)
- tkver = Label(frame_background, text='Tk version: ' + tk_patchlevel,
+ tkver = Label(frame_background, text=f'Tk version: {tk_patchlevel}',
fg=self.fg, bg=self.bg)
tkver.grid(row=9, column=1, sticky=W, padx=2, pady=0)
py_buttons = Frame(frame_background, bg=self.bg)
diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py
index e73ad59..5489147 100644
--- a/Lib/test/test_tcl.py
+++ b/Lib/test/test_tcl.py
@@ -28,15 +28,7 @@ def get_tk_patchlevel():
global _tk_patchlevel
if _tk_patchlevel is None:
tcl = Tcl()
- patchlevel = tcl.call('info', 'patchlevel')
- m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
- major, minor, releaselevel, serial = m.groups()
- major, minor, serial = int(major), int(minor), int(serial)
- releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
- if releaselevel == 'final':
- _tk_patchlevel = major, minor, serial, releaselevel, 0
- else:
- _tk_patchlevel = major, minor, 0, releaselevel, serial
+ _tk_patchlevel = tcl.info_patchlevel()
return _tk_patchlevel
@@ -723,7 +715,7 @@ class BigmemTclTest(unittest.TestCase):
def setUpModule():
if support.verbose:
tcl = Tcl()
- print('patchlevel =', tcl.call('info', 'patchlevel'))
+ print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True)
if __name__ == "__main__":
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 2e7e21c..3d23889 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -30,6 +30,7 @@ button.pack(side=BOTTOM)
tk.mainloop()
"""
+import collections
import enum
import sys
import types
@@ -143,6 +144,28 @@ def _splitdict(tk, v, cut_minus=True, conv=None):
dict[key] = value
return dict
+class _VersionInfoType(collections.namedtuple('_VersionInfoType',
+ ('major', 'minor', 'micro', 'releaselevel', 'serial'))):
+ def __str__(self):
+ if self.releaselevel == 'final':
+ return f'{self.major}.{self.minor}.{self.micro}'
+ else:
+ return f'{self.major}.{self.minor}{self.releaselevel[0]}{self.serial}'
+
+def _parse_version(version):
+ import re
+ m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', version)
+ major, minor, releaselevel, serial = m.groups()
+ major, minor, serial = int(major), int(minor), int(serial)
+ if releaselevel == '.':
+ micro = serial
+ serial = 0
+ releaselevel = 'final'
+ else:
+ micro = 0
+ releaselevel = {'a': 'alpha', 'b': 'beta'}[releaselevel]
+ return _VersionInfoType(major, minor, micro, releaselevel, serial)
+
@enum._simple_enum(enum.StrEnum)
class EventType:
@@ -1055,6 +1078,11 @@ class Misc:
lift = tkraise
+ def info_patchlevel(self):
+ """Returns the exact version of the Tcl library."""
+ patchlevel = self.tk.call('info', 'patchlevel')
+ return _parse_version(patchlevel)
+
def winfo_atom(self, name, displayof=0):
"""Return integer which represents atom NAME."""
args = ('winfo', 'atom') + self._displayof(displayof) + (name,)
diff --git a/Lib/tkinter/test/support.py b/Lib/tkinter/test/support.py
index dbc47a8..9e26d04 100644
--- a/Lib/tkinter/test/support.py
+++ b/Lib/tkinter/test/support.py
@@ -101,15 +101,7 @@ def get_tk_patchlevel():
global _tk_patchlevel
if _tk_patchlevel is None:
tcl = tkinter.Tcl()
- patchlevel = tcl.call('info', 'patchlevel')
- m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
- major, minor, releaselevel, serial = m.groups()
- major, minor, serial = int(major), int(minor), int(serial)
- releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
- if releaselevel == 'final':
- _tk_patchlevel = major, minor, serial, releaselevel, 0
- else:
- _tk_patchlevel = major, minor, 0, releaselevel, serial
+ _tk_patchlevel = tcl.info_patchlevel()
return _tk_patchlevel
units = {
diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py
index 044eb10..620b6ed 100644
--- a/Lib/tkinter/test/test_tkinter/test_misc.py
+++ b/Lib/tkinter/test/test_tkinter/test_misc.py
@@ -341,6 +341,35 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
self.assertEqual(log, [1])
self.assertTrue(self.root.winfo_exists())
+ def test_info_patchlevel(self):
+ 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.assertTrue(str(vi).startswith(f'{vi.major}.{vi.minor}'))
+
class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
diff --git a/Lib/tkinter/test/widget_tests.py b/Lib/tkinter/test/widget_tests.py
index 37d1979..a450544 100644
--- a/Lib/tkinter/test/widget_tests.py
+++ b/Lib/tkinter/test/widget_tests.py
@@ -517,4 +517,4 @@ def add_standard_options(*source_classes):
def setUpModule():
if test.support.verbose:
tcl = tkinter.Tcl()
- print('patchlevel =', tcl.call('info', 'patchlevel'))
+ print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True)
diff --git a/Misc/NEWS.d/next/Library/2022-04-22-19-11-31.gh-issue-91827.6P3gOI.rst b/Misc/NEWS.d/next/Library/2022-04-22-19-11-31.gh-issue-91827.6P3gOI.rst
new file mode 100644
index 0000000..83b7522
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-22-19-11-31.gh-issue-91827.6P3gOI.rst
@@ -0,0 +1,3 @@
+In the :mod:`tkinter` module add method ``info_patchlevel()`` which returns
+the exact version of the Tcl library as a named tuple similar to
+:data:`sys.version_info`.