diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py
index 5a5404d10..c6b52ce33 100644
--- a/Lib/test/test_minidom.py
+++ b/Lib/test/test_minidom.py
@@ -553,7 +553,6 @@ class MinidomTest(unittest.TestCase):
self.assertEqual(str(node), repr(node))
dom.unlink()
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testWriteXML(self):
str = ''
dom = parseString(str)
@@ -601,7 +600,6 @@ class MinidomTest(unittest.TestCase):
'lflf="
" '
'ws="
"/>')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testAltNewline(self):
str = '\n\n'
dom = parseString(str)
@@ -705,7 +703,6 @@ class MinidomTest(unittest.TestCase):
def testAttrListKeysNS(self): pass
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testRemoveNamedItem(self):
doc = parseString("")
e = doc.documentElement
@@ -715,7 +712,6 @@ class MinidomTest(unittest.TestCase):
self.assertTrue(a1.isSameNode(a2))
self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testRemoveNamedItemNS(self):
doc = parseString("")
e = doc.documentElement
@@ -788,7 +784,6 @@ class MinidomTest(unittest.TestCase):
root.setAttribute("added", "VALUE")
return dom, clone
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testCloneElementShallow(self):
dom, clone = self._setupCloneElement(0)
self.assertEqual(len(clone.childNodes), 0)
@@ -940,11 +935,9 @@ class MinidomTest(unittest.TestCase):
self.confirm(clone.specified,
testName + ": cloned attribute must have specified == True")
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testCloneAttributeShallow(self):
self.check_clone_attribute(0, "testCloneAttributeShallow")
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testCloneAttributeDeep(self):
self.check_clone_attribute(1, "testCloneAttributeDeep")
@@ -1336,7 +1329,6 @@ class MinidomTest(unittest.TestCase):
self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
xml.dom.EMPTY_NAMESPACE, "foo")
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testRenameAttribute(self):
doc = parseString("")
elem = doc.documentElement
@@ -1541,7 +1533,6 @@ class MinidomTest(unittest.TestCase):
self.confirm(text is None
and len(elem.childNodes) == 2)
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testSchemaType(self):
doc = parseString(
"")
e = doc.documentElement
@@ -1607,7 +1597,6 @@ class MinidomTest(unittest.TestCase):
self.confirm(e.isSameNode(doc.getElementById("w"))
and a2.isId)
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testSetIdAttributeNS(self):
NS1 = "http://xml.python.org/ns1"
NS2 = "http://xml.python.org/ns2"
@@ -1644,7 +1633,6 @@ class MinidomTest(unittest.TestCase):
self.confirm(e.isSameNode(doc.getElementById("w"))
and a2.isId)
- @unittest.expectedFailure # TODO: RUSTPYTHON
def testSetIdAttributeNode(self):
NS1 = "http://xml.python.org/ns1"
NS2 = "http://xml.python.org/ns2"
@@ -1766,7 +1754,6 @@ class MinidomTest(unittest.TestCase):
pi = doc.createProcessingInstruction("y", "z")
pi.nodeValue = "crash"
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_minidom_attribute_order(self):
xml_str = ''
doc = parseString(xml_str)
@@ -1774,13 +1761,11 @@ class MinidomTest(unittest.TestCase):
doc.writexml(output)
self.assertEqual(output.getvalue(), xml_str)
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_toxml_with_attributes_ordered(self):
xml_str = ''
doc = parseString(xml_str)
self.assertEqual(doc.toxml(), xml_str)
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_toprettyxml_with_attributes_ordered(self):
xml_str = ''
doc = parseString(xml_str)
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index 85db8e14c..cb9ae24cc 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -2355,7 +2355,6 @@ class ArgsTestCase(BaseTestCase):
self.check_executed_tests(output, testname, stats=1, parallel=True)
self.assertNotIn('SPAM SPAM SPAM', output)
- @unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
def test_xml(self):
code = textwrap.dedent(r"""
import unittest
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 18a845fe2..2b0777c1d 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -392,7 +392,6 @@ class ElementTreeTest(unittest.TestCase):
self.serialize_check(ET.XML(""),
'hello')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_file_init(self):
stringfile = io.BytesIO(SAMPLE_XML.encode("utf-8"))
tree = ET.ElementTree(file=stringfile)
@@ -508,7 +507,6 @@ class ElementTreeTest(unittest.TestCase):
elem[:] = tuple([subelem])
self.serialize_check(elem, '')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_parsefile(self):
# Test parsing from file.
@@ -688,7 +686,6 @@ class ElementTreeTest(unittest.TestCase):
parser2 = ET.XMLParser()
self.assertIsInstance(parser2.target, ET.TreeBuilder)
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_children(self):
# Test Element children iteration
@@ -1091,7 +1088,6 @@ class ElementTreeTest(unittest.TestCase):
self.assertEqual(str(cm.exception),
'undefined entity &entity;: line 4, column 10')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_namespace(self):
# Test namespace issues.
@@ -1335,7 +1331,6 @@ class ElementTreeTest(unittest.TestCase):
class IterparseTest(unittest.TestCase):
# Test iterparse interface.
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_basic(self):
iterparse = ET.iterparse
@@ -1361,7 +1356,6 @@ class IterparseTest(unittest.TestCase):
])
it.close()
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_external_file(self):
with open(SIMPLE_XMLFILE, 'rb') as source:
it = ET.iterparse(source)
@@ -1374,7 +1368,6 @@ class IterparseTest(unittest.TestCase):
])
self.assertEqual(it.root.tag, 'root')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_events(self):
iterparse = ET.iterparse
@@ -1475,7 +1468,6 @@ class IterparseTest(unittest.TestCase):
with self.assertRaises(FileNotFoundError):
ET.iterparse("nonexistent")
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_resource_warnings_not_exhausted(self):
# Not exhausting the iterator still closes the underlying file (bpo-43292)
it = ET.iterparse(SIMPLE_XMLFILE)
@@ -1514,7 +1506,6 @@ class IterparseTest(unittest.TestCase):
del it
gc_collect()
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_close_not_exhausted(self):
iterparse = ET.iterparse
@@ -2041,7 +2032,6 @@ class XIncludeTest(unittest.TestCase):
else:
return None
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_xinclude_default(self):
from xml.etree import ElementInclude
doc = self.xinclude_loader('default.xml')
@@ -2056,7 +2046,6 @@ class XIncludeTest(unittest.TestCase):
'\n'
'')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_xinclude(self):
from xml.etree import ElementInclude
@@ -2121,7 +2110,6 @@ class XIncludeTest(unittest.TestCase):
' \n'
'') # C5
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_xinclude_repeated(self):
from xml.etree import ElementInclude
@@ -2129,7 +2117,6 @@ class XIncludeTest(unittest.TestCase):
ElementInclude.include(document, self.xinclude_loader)
self.assertEqual(1+4*2, len(document.findall(".//p")))
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_xinclude_failures(self):
from xml.etree import ElementInclude
@@ -2234,7 +2221,6 @@ class BugsTest(unittest.TestCase):
elem.set("123", 123)
check(elem) # attribute value
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_bug_xmltoolkit25(self):
# typo in ElementTree.findtext
@@ -2258,7 +2244,6 @@ class BugsTest(unittest.TestCase):
ET.dump(tree)
self.assertEqual(stdout.getvalue(), '\n')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_bug_xmltoolkit39(self):
# non-ascii element and attribute names doesn't work
@@ -2345,7 +2330,6 @@ class BugsTest(unittest.TestCase):
xmltoolkit63()
self.assertEqual(sys.getrefcount(None), count)
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_bug_200708_newline(self):
# Preserve newlines in attributes.
@@ -2461,7 +2445,6 @@ class BugsTest(unittest.TestCase):
b"\n"
b'
tãg')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_issue6565(self):
elem = ET.XML("")
self.assertEqual(summarize_list(elem), ['tag'])
@@ -2533,7 +2516,6 @@ class BugsTest(unittest.TestCase):
root = ET.XML(xml)
self.assertEqual(root.get('b'), text.decode('utf-8'))
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_expat224_utf8_bug(self):
# bpo-31170: Expat 2.2.3 had a bug in its UTF-8 decoder.
# Check that Expat 2.2.4 fixed the bug.
@@ -3355,7 +3337,6 @@ class ElementTreeTypeTest(unittest.TestCase):
class ElementFindTest(unittest.TestCase):
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_find_simple(self):
e = ET.XML(SAMPLE_XML)
self.assertEqual(e.find('tag').tag, 'tag')
@@ -3379,7 +3360,6 @@ class ElementFindTest(unittest.TestCase):
# Issue #16922
self.assertEqual(ET.XML('').findtext('empty'), '')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_find_xpath(self):
LINEAR_XML = '''
@@ -3402,7 +3382,6 @@ class ElementFindTest(unittest.TestCase):
self.assertRaisesRegex(SyntaxError, 'XPath', e.find, './tag[last()-0]')
self.assertRaisesRegex(SyntaxError, 'XPath', e.find, './tag[last()+1]')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_findall(self):
e = ET.XML(SAMPLE_XML)
e[2] = ET.XML(SAMPLE_SECTION)
@@ -3591,7 +3570,6 @@ class ElementFindTest(unittest.TestCase):
with self.assertRaisesRegex(SyntaxError, 'cannot use absolute path'):
e.findall('/tag')
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_find_through_ElementTree(self):
e = ET.XML(SAMPLE_XML)
self.assertEqual(ET.ElementTree(e).find('tag').tag, 'tag')
@@ -4576,7 +4554,6 @@ class NoAcceleratorTest(unittest.TestCase):
# --------------------------------------------------------------------
class BoolTest(unittest.TestCase):
- @unittest.expectedFailure # TODO: RUSTPYTHON
def test_warning(self):
e = ET.fromstring('')
msg = (
diff --git a/crates/stdlib/src/pyexpat.rs b/crates/stdlib/src/pyexpat.rs
index f690abade..9b55bbb22 100644
--- a/crates/stdlib/src/pyexpat.rs
+++ b/crates/stdlib/src/pyexpat.rs
@@ -43,7 +43,8 @@ macro_rules! create_bool_property {
#[pymodule(name = "pyexpat")]
mod _pyexpat {
use crate::vm::{
- Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
+ AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
+ VirtualMachine,
builtins::{PyBytesRef, PyException, PyModule, PyStr, PyStrRef, PyType, PyUtf8StrRef},
extend_module,
function::{ArgBytesLike, ArgPrimitiveIndex, Either, IntoFuncArgs, OptionalArg},
@@ -355,19 +356,30 @@ mod _pyexpat {
XmlEvent::StartElement {
name, attributes, ..
} => {
- let dict = vm.ctx.new_dict();
- for attribute in attributes {
- let attr_name = self.make_name(&attribute.name);
- dict.set_item(
- attr_name.as_str(),
- vm.ctx.new_str(attribute.value).into(),
- vm,
- )
- .unwrap();
- }
+ let ordered = self.ordered_attributes.read().is(&vm.ctx.true_value);
+ // Build the container.
+ let attrs: PyObjectRef = if ordered {
+ let mut items = Vec::with_capacity(attributes.len() * 2);
+ for attribute in attributes {
+ items.push(vm.ctx.new_str(self.make_name(&attribute.name)).into());
+ items.push(vm.ctx.new_str(attribute.value).into());
+ }
+ vm.ctx.new_list(items).into()
+ } else {
+ let dict = vm.ctx.new_dict();
+ for attribute in attributes {
+ dict.set_item(
+ self.make_name(&attribute.name).as_str(),
+ vm.ctx.new_str(attribute.value).into(),
+ vm,
+ )
+ .unwrap();
+ }
+ dict.into()
+ };
let name_str = PyStr::from(self.make_name(&name)).into_ref(&vm.ctx);
- invoke_handler(vm, &self.start_element, (name_str, dict));
+ invoke_handler(vm, &self.start_element, (name_str, attrs));
}
XmlEvent::EndElement { name, .. } => {
let name_str = PyStr::from(self.make_name(&name)).into_ref(&vm.ctx);