(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
-----------
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)
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)
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
def setUpModule():
if support.verbose:
tcl = Tcl()
- print('patchlevel =', tcl.call('info', 'patchlevel'))
+ print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True)
if __name__ == "__main__":
tk.mainloop()
"""
+import collections
import enum
import sys
import types
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:
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,)
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 = {
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):
def setUpModule():
if test.support.verbose:
tcl = tkinter.Tcl()
- print('patchlevel =', tcl.call('info', 'patchlevel'))
+ print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True)
--- /dev/null
+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`.