mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Add missing xmlparser attributes: namespace_prefixes, ordered_attributes, specified_attributes, intern (#6494)
* Add namespace_prefixes and other missing xmlparser attributes - Added namespace_prefixes, ordered_attributes, specified_attributes (boolean attributes) - Added intern dictionary attribute - Added stub handlers for all missing handler types to ensure compatibility - Created bool_property macro to ensure boolean attributes are converted correctly * Remove expectedFailure decorators from passing tests - Tests for buffer_text, namespace_prefixes, ordered_attributes, and specified_attributes now pass --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
2 files changed
+182
-7
No files matched your search
Vendored
-6
@@ -20,28 +20,24 @@ class SetAttributeTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.parser = expat.ParserCreate(namespace_separator='!')
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_buffer_text(self):
|
||||
self.assertIs(self.parser.buffer_text, False)
|
||||
for x in 0, 1, 2, 0:
|
||||
self.parser.buffer_text = x
|
||||
self.assertIs(self.parser.buffer_text, bool(x))
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_namespace_prefixes(self):
|
||||
self.assertIs(self.parser.namespace_prefixes, False)
|
||||
for x in 0, 1, 2, 0:
|
||||
self.parser.namespace_prefixes = x
|
||||
self.assertIs(self.parser.namespace_prefixes, bool(x))
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_ordered_attributes(self):
|
||||
self.assertIs(self.parser.ordered_attributes, False)
|
||||
for x in 0, 1, 2, 0:
|
||||
self.parser.ordered_attributes = x
|
||||
self.assertIs(self.parser.ordered_attributes, bool(x))
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_specified_attributes(self):
|
||||
self.assertIs(self.parser.specified_attributes, False)
|
||||
for x in 0, 1, 2, 0:
|
||||
@@ -244,7 +240,6 @@ class ParseTest(unittest.TestCase):
|
||||
# Issue #6697.
|
||||
self.assertRaises(AttributeError, getattr, parser, '\uD800')
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_parse_str(self):
|
||||
out = self.Outputter()
|
||||
parser = expat.ParserCreate(namespace_separator='!')
|
||||
@@ -255,7 +250,6 @@ class ParseTest(unittest.TestCase):
|
||||
operations = out.out
|
||||
self._verify_parse_output(operations)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_parse_file(self):
|
||||
# Try parsing a file
|
||||
out = self.Outputter()
|
||||
|
||||
@@ -25,6 +25,26 @@ macro_rules! create_property {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! create_bool_property {
|
||||
($ctx: expr, $attributes: expr, $name: expr, $class: expr, $element: ident) => {
|
||||
let attr = $ctx.new_static_getset(
|
||||
$name,
|
||||
$class,
|
||||
move |this: &PyExpatLikeXmlParser| this.$element.read().clone(),
|
||||
move |this: &PyExpatLikeXmlParser,
|
||||
value: PyObjectRef,
|
||||
vm: &VirtualMachine|
|
||||
-> PyResult<()> {
|
||||
let bool_value = value.is_true(vm)?;
|
||||
*this.$element.write() = vm.ctx.new_bool(bool_value).into();
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
|
||||
$attributes.insert($ctx.intern_str($name), attr.into());
|
||||
};
|
||||
}
|
||||
|
||||
#[pymodule(name = "pyexpat")]
|
||||
mod _pyexpat {
|
||||
use crate::vm::{
|
||||
@@ -51,6 +71,29 @@ mod _pyexpat {
|
||||
character_data: MutableObject,
|
||||
entity_decl: MutableObject,
|
||||
buffer_text: MutableObject,
|
||||
namespace_prefixes: MutableObject,
|
||||
ordered_attributes: MutableObject,
|
||||
specified_attributes: MutableObject,
|
||||
intern: MutableObject,
|
||||
// Additional handlers (stubs for compatibility)
|
||||
processing_instruction: MutableObject,
|
||||
unparsed_entity_decl: MutableObject,
|
||||
notation_decl: MutableObject,
|
||||
start_namespace_decl: MutableObject,
|
||||
end_namespace_decl: MutableObject,
|
||||
comment: MutableObject,
|
||||
start_cdata_section: MutableObject,
|
||||
end_cdata_section: MutableObject,
|
||||
default: MutableObject,
|
||||
default_expand: MutableObject,
|
||||
not_standalone: MutableObject,
|
||||
external_entity_ref: MutableObject,
|
||||
start_doctype_decl: MutableObject,
|
||||
end_doctype_decl: MutableObject,
|
||||
xml_decl: MutableObject,
|
||||
element_decl: MutableObject,
|
||||
attlist_decl: MutableObject,
|
||||
skipped_entity: MutableObject,
|
||||
}
|
||||
type PyExpatLikeXmlParserRef = PyRef<PyExpatLikeXmlParser>;
|
||||
|
||||
@@ -71,6 +114,31 @@ mod _pyexpat {
|
||||
character_data: MutableObject::new(vm.ctx.none()),
|
||||
entity_decl: MutableObject::new(vm.ctx.none()),
|
||||
buffer_text: MutableObject::new(vm.ctx.new_bool(false).into()),
|
||||
namespace_prefixes: MutableObject::new(vm.ctx.new_bool(false).into()),
|
||||
ordered_attributes: MutableObject::new(vm.ctx.new_bool(false).into()),
|
||||
specified_attributes: MutableObject::new(vm.ctx.new_bool(false).into()),
|
||||
// String interning dictionary - used by the parser to intern element/attribute names
|
||||
// for memory efficiency and faster comparisons. See CPython's pyexpat documentation.
|
||||
intern: MutableObject::new(vm.ctx.new_dict().into()),
|
||||
// Additional handlers (stubs for compatibility)
|
||||
processing_instruction: MutableObject::new(vm.ctx.none()),
|
||||
unparsed_entity_decl: MutableObject::new(vm.ctx.none()),
|
||||
notation_decl: MutableObject::new(vm.ctx.none()),
|
||||
start_namespace_decl: MutableObject::new(vm.ctx.none()),
|
||||
end_namespace_decl: MutableObject::new(vm.ctx.none()),
|
||||
comment: MutableObject::new(vm.ctx.none()),
|
||||
start_cdata_section: MutableObject::new(vm.ctx.none()),
|
||||
end_cdata_section: MutableObject::new(vm.ctx.none()),
|
||||
default: MutableObject::new(vm.ctx.none()),
|
||||
default_expand: MutableObject::new(vm.ctx.none()),
|
||||
not_standalone: MutableObject::new(vm.ctx.none()),
|
||||
external_entity_ref: MutableObject::new(vm.ctx.none()),
|
||||
start_doctype_decl: MutableObject::new(vm.ctx.none()),
|
||||
end_doctype_decl: MutableObject::new(vm.ctx.none()),
|
||||
xml_decl: MutableObject::new(vm.ctx.none()),
|
||||
element_decl: MutableObject::new(vm.ctx.none()),
|
||||
attlist_decl: MutableObject::new(vm.ctx.none()),
|
||||
skipped_entity: MutableObject::new(vm.ctx.none()),
|
||||
}
|
||||
.into_ref(&vm.ctx))
|
||||
}
|
||||
@@ -89,7 +157,120 @@ mod _pyexpat {
|
||||
character_data
|
||||
);
|
||||
create_property!(ctx, attributes, "EntityDeclHandler", class, entity_decl);
|
||||
create_property!(ctx, attributes, "buffer_text", class, buffer_text);
|
||||
create_bool_property!(ctx, attributes, "buffer_text", class, buffer_text);
|
||||
create_bool_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"namespace_prefixes",
|
||||
class,
|
||||
namespace_prefixes
|
||||
);
|
||||
create_bool_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"ordered_attributes",
|
||||
class,
|
||||
ordered_attributes
|
||||
);
|
||||
create_bool_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"specified_attributes",
|
||||
class,
|
||||
specified_attributes
|
||||
);
|
||||
create_property!(ctx, attributes, "intern", class, intern);
|
||||
// Additional handlers (stubs for compatibility)
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"ProcessingInstructionHandler",
|
||||
class,
|
||||
processing_instruction
|
||||
);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"UnparsedEntityDeclHandler",
|
||||
class,
|
||||
unparsed_entity_decl
|
||||
);
|
||||
create_property!(ctx, attributes, "NotationDeclHandler", class, notation_decl);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"StartNamespaceDeclHandler",
|
||||
class,
|
||||
start_namespace_decl
|
||||
);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"EndNamespaceDeclHandler",
|
||||
class,
|
||||
end_namespace_decl
|
||||
);
|
||||
create_property!(ctx, attributes, "CommentHandler", class, comment);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"StartCdataSectionHandler",
|
||||
class,
|
||||
start_cdata_section
|
||||
);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"EndCdataSectionHandler",
|
||||
class,
|
||||
end_cdata_section
|
||||
);
|
||||
create_property!(ctx, attributes, "DefaultHandler", class, default);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"DefaultHandlerExpand",
|
||||
class,
|
||||
default_expand
|
||||
);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"NotStandaloneHandler",
|
||||
class,
|
||||
not_standalone
|
||||
);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"ExternalEntityRefHandler",
|
||||
class,
|
||||
external_entity_ref
|
||||
);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"StartDoctypeDeclHandler",
|
||||
class,
|
||||
start_doctype_decl
|
||||
);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"EndDoctypeDeclHandler",
|
||||
class,
|
||||
end_doctype_decl
|
||||
);
|
||||
create_property!(ctx, attributes, "XmlDeclHandler", class, xml_decl);
|
||||
create_property!(ctx, attributes, "ElementDeclHandler", class, element_decl);
|
||||
create_property!(ctx, attributes, "AttlistDeclHandler", class, attlist_decl);
|
||||
create_property!(
|
||||
ctx,
|
||||
attributes,
|
||||
"SkippedEntityHandler",
|
||||
class,
|
||||
skipped_entity
|
||||
);
|
||||
}
|
||||
|
||||
fn create_config(&self) -> xml::ParserConfig {
|
||||
|
||||
Reference in new issue
Block a user