https://github.com/python/cpython/commit/71cbffde61449a224dffcae937f5f6be4f86ad09
commit: 71cbffde61449a224dffcae937f5f6be4f86ad09
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-01-20T09:16:36+02:00
summary:

gh-143754: Add Tkinter methods pack_content(), place_content() and 
grid_content() (GH-143845)

They use Tk commands with new name like "pack content instead of old
"pack slaves".

files:
A Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst
M Doc/whatsnew/3.15.rst
M Lib/test/test_tkinter/test_geometry_managers.py
M Lib/tkinter/__init__.py

diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index b7a27d5db63875..1dd66065b0f93d 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -792,6 +792,12 @@ tkinter
   using Tcl's ``-all`` and ``-overlap`` options.
   (Contributed by Rihaan Meher in :gh:`130848`)
 
+* Added new methods :meth:`!pack_content`, :meth:`!place_content` and
+  :meth:`!grid_content` which use Tk commands with new names (introduced
+  in Tk 8.6) instead of :meth:`!*_slaves` methods which use Tk commands
+  with outdated names.
+  (Contributed by Serhiy Storchaka in :gh:`143754`)
+
 types
 ------
 
diff --git a/Lib/test/test_tkinter/test_geometry_managers.py 
b/Lib/test/test_tkinter/test_geometry_managers.py
index b2ce143ff0948f..3dcdadd1aacf10 100644
--- a/Lib/test/test_tkinter/test_geometry_managers.py
+++ b/Lib/test/test_tkinter/test_geometry_managers.py
@@ -40,11 +40,11 @@ def test_pack_configure_after(self):
         b.pack_configure(side='top')
         c.pack_configure(side='top')
         d.pack_configure(side='top')
-        self.assertEqual(pack.pack_slaves(), [a, b, c, d])
+        self.assertEqual(pack.pack_content(), [a, b, c, d])
         a.pack_configure(after=b)
-        self.assertEqual(pack.pack_slaves(), [b, a, c, d])
+        self.assertEqual(pack.pack_content(), [b, a, c, d])
         a.pack_configure(after=a)
-        self.assertEqual(pack.pack_slaves(), [b, a, c, d])
+        self.assertEqual(pack.pack_content(), [b, a, c, d])
 
     def test_pack_configure_anchor(self):
         pack, a, b, c, d = self.create2()
@@ -73,11 +73,11 @@ def test_pack_configure_before(self):
         b.pack_configure(side='top')
         c.pack_configure(side='top')
         d.pack_configure(side='top')
-        self.assertEqual(pack.pack_slaves(), [a, b, c, d])
+        self.assertEqual(pack.pack_content(), [a, b, c, d])
         a.pack_configure(before=d)
-        self.assertEqual(pack.pack_slaves(), [b, c, a, d])
+        self.assertEqual(pack.pack_content(), [b, c, a, d])
         a.pack_configure(before=a)
-        self.assertEqual(pack.pack_slaves(), [b, c, a, d])
+        self.assertEqual(pack.pack_content(), [b, c, a, d])
 
     def test_pack_configure_expand(self):
         pack, a, b, c, d = self.create2()
@@ -110,10 +110,10 @@ def test_pack_configure_in(self):
         c.pack_configure(side='top')
         d.pack_configure(side='top')
         a.pack_configure(in_=pack)
-        self.assertEqual(pack.pack_slaves(), [b, c, d, a])
+        self.assertEqual(pack.pack_content(), [b, c, d, a])
         a.pack_configure(in_=c)
-        self.assertEqual(pack.pack_slaves(), [b, c, d])
-        self.assertEqual(c.pack_slaves(), [a])
+        self.assertEqual(pack.pack_content(), [b, c, d])
+        self.assertEqual(c.pack_content(), [a])
         with self.assertRaisesRegex(
                 TclError, """can't pack "?%s"? inside itself""" % (a,)):
             a.pack_configure(in_=a)
@@ -223,11 +223,11 @@ def test_pack_forget(self):
         a.pack_configure()
         b.pack_configure()
         c.pack_configure()
-        self.assertEqual(pack.pack_slaves(), [a, b, c])
+        self.assertEqual(pack.pack_content(), [a, b, c])
         b.pack_forget()
-        self.assertEqual(pack.pack_slaves(), [a, c])
+        self.assertEqual(pack.pack_content(), [a, c])
         b.pack_forget()
-        self.assertEqual(pack.pack_slaves(), [a, c])
+        self.assertEqual(pack.pack_content(), [a, c])
         d.pack_forget()
 
     def test_pack_info(self):
@@ -273,6 +273,14 @@ def test_pack_propagate(self):
         self.assertEqual(pack.winfo_reqwidth(), 20)
         self.assertEqual(pack.winfo_reqheight(), 40)
 
+    def test_pack_content(self):
+        pack, a, b, c, d = self.create2()
+        self.assertEqual(pack.pack_content(), [])
+        a.pack_configure()
+        self.assertEqual(pack.pack_content(), [a])
+        b.pack_configure()
+        self.assertEqual(pack.pack_content(), [a, b])
+
     def test_pack_slaves(self):
         pack, a, b, c, d = self.create2()
         self.assertEqual(pack.pack_slaves(), [])
@@ -477,6 +485,15 @@ def test_place_info(self):
         with self.assertRaises(TypeError):
             f2.place_info(0)
 
+    def test_place_content(self):
+        foo = tkinter.Frame(self.root)
+        bar = tkinter.Frame(self.root)
+        self.assertEqual(foo.place_content(), [])
+        bar.place_configure(in_=foo)
+        self.assertEqual(foo.place_content(), [bar])
+        with self.assertRaises(TypeError):
+            foo.place_content(0)
+
     def test_place_slaves(self):
         foo = tkinter.Frame(self.root)
         bar = tkinter.Frame(self.root)
@@ -729,10 +746,10 @@ def test_grid_forget(self):
         c = tkinter.Button(self.root)
         b.grid_configure(row=2, column=2, rowspan=2, columnspan=2,
                          padx=3, pady=4, sticky='ns')
-        self.assertEqual(self.root.grid_slaves(), [b])
+        self.assertEqual(self.root.grid_content(), [b])
         b.grid_forget()
         c.grid_forget()
-        self.assertEqual(self.root.grid_slaves(), [])
+        self.assertEqual(self.root.grid_content(), [])
         self.assertEqual(b.grid_info(), {})
         b.grid_configure(row=0, column=0)
         info = b.grid_info()
@@ -749,10 +766,10 @@ def test_grid_remove(self):
         c = tkinter.Button(self.root)
         b.grid_configure(row=2, column=2, rowspan=2, columnspan=2,
                          padx=3, pady=4, sticky='ns')
-        self.assertEqual(self.root.grid_slaves(), [b])
+        self.assertEqual(self.root.grid_content(), [b])
         b.grid_remove()
         c.grid_remove()
-        self.assertEqual(self.root.grid_slaves(), [])
+        self.assertEqual(self.root.grid_content(), [])
         self.assertEqual(b.grid_info(), {})
         b.grid_configure(row=0, column=0)
         info = b.grid_info()
@@ -887,6 +904,23 @@ def test_grid_size(self):
         f.grid_configure(row=4, column=5)
         self.assertEqual(self.root.grid_size(), (6, 5))
 
+    def test_grid_content(self):
+        self.assertEqual(self.root.grid_content(), [])
+        a = tkinter.Label(self.root)
+        a.grid_configure(row=0, column=1)
+        b = tkinter.Label(self.root)
+        b.grid_configure(row=1, column=0)
+        c = tkinter.Label(self.root)
+        c.grid_configure(row=1, column=1)
+        d = tkinter.Label(self.root)
+        d.grid_configure(row=1, column=1)
+        self.assertEqual(self.root.grid_content(), [d, c, b, a])
+        self.assertEqual(self.root.grid_content(row=0), [a])
+        self.assertEqual(self.root.grid_content(row=1), [d, c, b])
+        self.assertEqual(self.root.grid_content(column=0), [b])
+        self.assertEqual(self.root.grid_content(column=1), [d, c, a])
+        self.assertEqual(self.root.grid_content(row=1, column=1), [d, c])
+
     def test_grid_slaves(self):
         self.assertEqual(self.root.grid_slaves(), [])
         a = tkinter.Label(self.root)
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index be150e2b892e4b..d695e3ec9cb1b4 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -1885,9 +1885,21 @@ def pack_propagate(self, flag=_noarg_):
 
     propagate = pack_propagate
 
-    def pack_slaves(self):
+    def pack_content(self):
         """Returns a list of all of the content widgets in the packing order
         for this container."""
+        try:
+            res = self.tk.call('pack', 'content', self._w)
+        except TclError:
+            if self.info_patchlevel() >= (8, 6):
+                raise
+            res = self.tk.call('pack', 'slaves', self._w)
+        return [self._nametowidget(x) for x in self.tk.splitlist(res)]
+
+    content = pack_content
+
+    def pack_slaves(self):
+        """Synonym for pack_content()."""
         return [self._nametowidget(x) for x in
                 self.tk.splitlist(
                    self.tk.call('pack', 'slaves', self._w))]
@@ -1895,9 +1907,19 @@ def pack_slaves(self):
     slaves = pack_slaves
 
     # Place method that applies to the container widget
-    def place_slaves(self):
+    def place_content(self):
         """Returns a list of all the content widgets for which this widget is
         the container."""
+        try:
+            res = self.tk.call('place', 'content', self._w)
+        except TclError:
+            if self.info_patchlevel() >= (8, 6):
+                raise
+            res = self.tk.call('place', 'slaves', self._w)
+        return [self._nametowidget(x) for x in self.tk.splitlist(res)]
+
+    def place_slaves(self):
+        """Synonym for place_content()."""
         return [self._nametowidget(x) for x in
                 self.tk.splitlist(
                    self.tk.call(
@@ -2018,7 +2040,7 @@ def grid_size(self):
 
     size = grid_size
 
-    def grid_slaves(self, row=None, column=None):
+    def grid_content(self, row=None, column=None):
         """Returns a list of the content widgets.
 
         If no arguments are supplied, a list of all of the content in this
@@ -2027,6 +2049,21 @@ def grid_slaves(self, row=None, column=None):
         column is returned.
         """
         args = ()
+        if row is not None:
+            args = args + ('-row', row)
+        if column is not None:
+            args = args + ('-column', column)
+        try:
+            res = self.tk.call('grid', 'content', self._w, *args)
+        except TclError:
+            if self.info_patchlevel() >= (8, 6):
+                raise
+            res = self.tk.call('grid', 'slaves', self._w, *args)
+        return [self._nametowidget(x) for x in self.tk.splitlist(res)]
+
+    def grid_slaves(self, row=None, column=None):
+        """Synonym for grid_content()."""
+        args = ()
         if row is not None:
             args = args + ('-row', row)
         if column is not None:
@@ -2641,6 +2678,7 @@ def pack_info(self):
 
     info = pack_info
     propagate = pack_propagate = Misc.pack_propagate
+    content = pack_content = Misc.pack_content
     slaves = pack_slaves = Misc.pack_slaves
 
 
@@ -2698,6 +2736,7 @@ def place_info(self):
         return d
 
     info = place_info
+    content = place_content = Misc.place_content
     slaves = place_slaves = Misc.place_slaves
 
 
@@ -2753,6 +2792,7 @@ def grid_info(self):
     propagate = grid_propagate = Misc.grid_propagate
     rowconfigure = grid_rowconfigure = Misc.grid_rowconfigure
     size = grid_size = Misc.grid_size
+    content = grid_content = Misc.grid_content
     slaves = grid_slaves = Misc.grid_slaves
 
 
diff --git 
a/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst 
b/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst
new file mode 100644
index 00000000000000..edfdd109400d08
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-01-14-20-35-40.gh-issue-143754.m2NQXA.rst
@@ -0,0 +1,3 @@
+Add new :mod:`tkinter` widget methods :meth:`!pack_content`,
+:meth:`!place_content` and :meth:`!grid_content` which are alternative
+spelling of old :meth:`!*_slaves` methods.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to