mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +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`.)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,8 +76,8 @@ def create_widgets(self):
 | 
			
		|||
                       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 @@ def create_widgets(self):
 | 
			
		|||
                      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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 @@ def test_huge_string_builtins2(self, size):
 | 
			
		|||
def setUpModule():
 | 
			
		||||
    if support.verbose:
 | 
			
		||||
        tcl = Tcl()
 | 
			
		||||
        print('patchlevel =', tcl.call('info', 'patchlevel'))
 | 
			
		||||
        print('patchlevel =', tcl.call('info', 'patchlevel'), flush=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@
 | 
			
		|||
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 @@ def tkraise(self, aboveThis=None):
 | 
			
		|||
 | 
			
		||||
    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,)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -341,6 +341,35 @@ def callback():
 | 
			
		|||
        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):
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -517,4 +517,4 @@ def test(self, option=option):
 | 
			
		|||
def setUpModule():
 | 
			
		||||
    if test.support.verbose:
 | 
			
		||||
        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