mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	gh-91827: Add method info_pathlevel() in tkinter (GH-91829)
This commit is contained in:
		
							parent
							
								
									d707d073be
								
							
						
					
					
						commit
						15dbe8570f
					
				
					 8 changed files with 75 additions and 23 deletions
				
			
		|  | @ -744,6 +744,14 @@ For major changes, see :ref:`new-feat-related-type-hints-311`. | ||||||
|   (Contributed by Serhiy Storchaka in :issue:`43923`.) |   (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 | unicodedata | ||||||
| ----------- | ----------- | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,8 +76,8 @@ def create_widgets(self): | ||||||
|                        bg=self.bg, font=('courier', 24, 'bold')) |                        bg=self.bg, font=('courier', 24, 'bold')) | ||||||
|         header.grid(row=0, column=0, sticky=E, padx=10, pady=10) |         header.grid(row=0, column=0, sticky=E, padx=10, pady=10) | ||||||
| 
 | 
 | ||||||
|         tk_patchlevel = self.tk.call('info', 'patchlevel') |         tk_patchlevel = self.info_patchlevel() | ||||||
|         ext = '.png' if tk_patchlevel >= '8.6' else '.gif' |         ext = '.png' if tk_patchlevel >= (8, 6) else '.gif' | ||||||
|         icon = os.path.join(os.path.abspath(os.path.dirname(__file__)), |         icon = os.path.join(os.path.abspath(os.path.dirname(__file__)), | ||||||
|                             'Icons', f'idle_48{ext}') |                             'Icons', f'idle_48{ext}') | ||||||
|         self.icon_image = PhotoImage(master=self._root(), file=icon) |         self.icon_image = PhotoImage(master=self._root(), file=icon) | ||||||
|  | @ -105,7 +105,7 @@ def create_widgets(self): | ||||||
|                       text='Python version:  ' + version, |                       text='Python version:  ' + version, | ||||||
|                       fg=self.fg, bg=self.bg) |                       fg=self.fg, bg=self.bg) | ||||||
|         pyver.grid(row=9, column=0, sticky=W, padx=10, pady=0) |         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) |                       fg=self.fg, bg=self.bg) | ||||||
|         tkver.grid(row=9, column=1, sticky=W, padx=2, pady=0) |         tkver.grid(row=9, column=1, sticky=W, padx=2, pady=0) | ||||||
|         py_buttons = Frame(frame_background, bg=self.bg) |         py_buttons = Frame(frame_background, bg=self.bg) | ||||||
|  |  | ||||||
|  | @ -28,15 +28,7 @@ def get_tk_patchlevel(): | ||||||
|     global _tk_patchlevel |     global _tk_patchlevel | ||||||
|     if _tk_patchlevel is None: |     if _tk_patchlevel is None: | ||||||
|         tcl = Tcl() |         tcl = Tcl() | ||||||
|         patchlevel = tcl.call('info', 'patchlevel') |         _tk_patchlevel = tcl.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 |  | ||||||
|     return _tk_patchlevel |     return _tk_patchlevel | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -723,7 +715,7 @@ def test_huge_string_builtins2(self, size): | ||||||
| def setUpModule(): | def setUpModule(): | ||||||
|     if support.verbose: |     if support.verbose: | ||||||
|         tcl = Tcl() |         tcl = Tcl() | ||||||
|         print('patchlevel =', tcl.call('info', 'patchlevel')) |         print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ | ||||||
| tk.mainloop() | tk.mainloop() | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
|  | import collections | ||||||
| import enum | import enum | ||||||
| import sys | import sys | ||||||
| import types | import types | ||||||
|  | @ -143,6 +144,28 @@ def _splitdict(tk, v, cut_minus=True, conv=None): | ||||||
|         dict[key] = value |         dict[key] = value | ||||||
|     return dict |     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) | @enum._simple_enum(enum.StrEnum) | ||||||
| class EventType: | class EventType: | ||||||
|  | @ -1055,6 +1078,11 @@ def tkraise(self, aboveThis=None): | ||||||
| 
 | 
 | ||||||
|     lift = tkraise |     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): |     def winfo_atom(self, name, displayof=0): | ||||||
|         """Return integer which represents atom NAME.""" |         """Return integer which represents atom NAME.""" | ||||||
|         args = ('winfo', 'atom') + self._displayof(displayof) + (name,) |         args = ('winfo', 'atom') + self._displayof(displayof) + (name,) | ||||||
|  |  | ||||||
|  | @ -101,15 +101,7 @@ def get_tk_patchlevel(): | ||||||
|     global _tk_patchlevel |     global _tk_patchlevel | ||||||
|     if _tk_patchlevel is None: |     if _tk_patchlevel is None: | ||||||
|         tcl = tkinter.Tcl() |         tcl = tkinter.Tcl() | ||||||
|         patchlevel = tcl.call('info', 'patchlevel') |         _tk_patchlevel = tcl.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 |  | ||||||
|     return _tk_patchlevel |     return _tk_patchlevel | ||||||
| 
 | 
 | ||||||
| units = { | units = { | ||||||
|  |  | ||||||
|  | @ -341,6 +341,35 @@ def callback(): | ||||||
|         self.assertEqual(log, [1]) |         self.assertEqual(log, [1]) | ||||||
|         self.assertTrue(self.root.winfo_exists()) |         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): | class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase): | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -517,4 +517,4 @@ def test(self, option=option): | ||||||
| def setUpModule(): | def setUpModule(): | ||||||
|     if test.support.verbose: |     if test.support.verbose: | ||||||
|         tcl = tkinter.Tcl() |         tcl = tkinter.Tcl() | ||||||
|         print('patchlevel =', tcl.call('info', 'patchlevel')) |         print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True) | ||||||
|  |  | ||||||
|  | @ -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`. | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Serhiy Storchaka
						Serhiy Storchaka