diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst
index 177be9ff4bad25..aa3f9ba70c6fa4 100644
--- a/Doc/library/xml.etree.elementtree.rst
+++ b/Doc/library/xml.etree.elementtree.rst
@@ -693,7 +693,7 @@ Functions
.. versionadded:: 3.2
-.. function:: SubElement(parent, tag, attrib={}, **extra)
+.. function:: SubElement(parent, tag, /, attrib={}, **extra)
Subelement factory. This function creates an element instance, and appends
it to an existing element.
@@ -704,6 +704,9 @@ Functions
attributes. *extra* contains additional attributes, given as keyword
arguments. Returns an element instance.
+ .. versionchanged:: next
+ *parent* and *tag* are now positional-only parameters.
+
.. function:: tostring(element, encoding="us-ascii", method="xml", *, \
xml_declaration=None, default_namespace=None, \
@@ -879,7 +882,7 @@ Element Objects
:noindex:
:no-index:
-.. class:: Element(tag, attrib={}, **extra)
+.. class:: Element(tag, /, attrib={}, **extra)
Element class. This class defines the Element interface, and provides a
reference implementation of this interface.
@@ -889,6 +892,9 @@ Element Objects
an optional dictionary, containing element attributes. *extra* contains
additional attributes, given as keyword arguments.
+ .. versionchanged:: next
+ *tag* is now a positional-only parameter.
+
.. attribute:: tag
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 93162f52ba0344..ccd803186b5135 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -381,6 +381,19 @@ def test_simpleops(self):
self.serialize_check(element,
'')
+ def test_positional_only_parameter(self):
+ # Test Element positional-only parameters (gh-144846).
+
+ # 'tag' is positional-only
+ with self.assertRaises(TypeError):
+ ET.Element(tag='fail')
+
+ # 'tag' and 'attrib' as kwarg/attribute names
+ e = ET.Element('e', attrib={'attrib': 'foo'}, tag='bar')
+ self.assertEqual(e.tag, 'e')
+ self.assertEqual(e.get('attrib'), 'foo')
+ self.assertEqual(e.get('tag'), 'bar')
+
def test_cdata(self):
# Test CDATA handling (etc).
@@ -484,6 +497,28 @@ def test_attrib(self):
self.assertEqual(ET.tostring(elem),
b'')
+ def test_subelement_positional_only_parameter(self):
+ # Test SubElement positional-only parameters (gh-144270).
+ parent = ET.Element('parent')
+
+ # 'parent' and 'tag' are positional-only
+ with self.assertRaises(TypeError):
+ ET.SubElement(parent=parent, tag='fail')
+ with self.assertRaises(TypeError):
+ ET.SubElement(parent, tag='fail')
+
+ # 'attrib' can be passed as keyword
+ sub1 = ET.SubElement(parent, 'sub1', attrib={'key': 'value'})
+ self.assertEqual(sub1.get('key'), 'value')
+
+ # 'tag' and 'parent' as kwargs become XML attributes, not func params
+ sub2 = ET.SubElement(parent, 'sub2', attrib={'attrib': 'foo'},
+ tag='bar', parent='baz')
+ self.assertEqual(sub2.tag, 'sub2')
+ self.assertEqual(sub2.get('attrib'), 'foo')
+ self.assertEqual(sub2.get('tag'), 'bar')
+ self.assertEqual(sub2.get('parent'), 'baz')
+
def test_makeelement(self):
# Test makeelement handling.
diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py
index e3d81a2c4560d9..11dfb8d9c1d59f 100644
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -164,7 +164,7 @@ class Element:
"""
- def __init__(self, tag, attrib={}, **extra):
+ def __init__(self, tag, /, attrib={}, **extra):
if not isinstance(attrib, dict):
raise TypeError("attrib must be dict, not %s" % (
attrib.__class__.__name__,))
@@ -416,7 +416,7 @@ def itertext(self):
yield t
-def SubElement(parent, tag, attrib={}, **extra):
+def SubElement(parent, tag, /, attrib={}, **extra):
"""Subelement factory which creates an element instance, and appends it
to an existing parent.
diff --git a/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst b/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst
new file mode 100644
index 00000000000000..b8a4374bc2d3ca
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-02-19-16-34-18.gh-issue-144270.wJRtSr.rst
@@ -0,0 +1,3 @@
+Made the *tag* parameter of :class:`xml.etree.ElementTree.Element` and the
+*parent* and *tag* parameters of :func:`xml.etree.ElementTree.SubElement`
+positional-only, matching the behavior of the C accelerator.