diff options
-rw-r--r-- | Doc/whatsnew/3.11.rst | 8 | ||||
-rw-r--r-- | Lib/idlelib/help_about.py | 6 | ||||
-rw-r--r-- | Lib/test/test_tcl.py | 12 | ||||
-rw-r--r-- | Lib/tkinter/__init__.py | 28 | ||||
-rw-r--r-- | Lib/tkinter/test/support.py | 10 | ||||
-rw-r--r-- | Lib/tkinter/test/test_tkinter/test_misc.py | 29 | ||||
-rw-r--r-- | Lib/tkinter/test/widget_tests.py | 2 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2022-04-22-19-11-31.gh-issue-91827.6P3gOI.rst | 3 |
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`. |