Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 24, 2025

Implementation Plan for namespace_prefixes Attribute

  • Investigate the issue and understand namespace_prefixes behavior in CPython
  • Confirm the attribute is missing in RustPython's xmlparser
  • Add namespace_prefixes field to PyExpatLikeXmlParser struct (defaults to false)
  • Create property getter/setter for namespace_prefixes in extend_class_with_fields
  • Add ordered_attributes and specified_attributes fields (also mentioned in tests)
  • Add intern dictionary attribute with documentation
  • Add all missing handler stub attributes for compatibility
  • Test with test_pyexpat.py SetAttributeTest - all tests pass
  • Run cargo run -- -m test test_xml_etree - passes successfully
  • Run cargo clippy - no warnings
  • Remove expectedFailure decorators from passing tests (buffer_text, namespace_prefixes, ordered_attributes, specified_attributes)
  • Address code review feedback - proper error handling and documentation
  • Remove expectedFailure from test_parse_str and test_parse_file - now passing
Original prompt

This section details on the original issue you should resolve

<issue_title>AttributeError: 'xmlparser' object has no attribute 'namespace_prefixes'</issue_title>
<issue_description>Hello! I'm trying to run xonsh shell using rustpython on Mac but faced with error:

xonsh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh  # https://rustup.rs/
# restart shell
cargo install --features=ssl --git https://github.com/RustPython/RustPython rustpython
$PATH.append(p'~/.cargo/bin')
#rustpython -m site  # to get locations
rustpython --install-pip
rustpython -m pip install xonsh prompt-toolkit

Here prompt-toolkit was added - it's the default prompt engine for xonsh shell.

~/.local/bin/xonsh --no-rc --no-env

Result:

Traceback (most recent call last):
  File "/Users/pc/.local/bin/xonsh", line 3, in <module>
    from xonsh.main import main
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/xonsh/main.py", line 12, in <module>
    import xonsh.procs.pipelines as xpp
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/xonsh/procs/__init__.py", line 2, in <module>
    from xonsh.procs import proxies  # noqa
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/xonsh/procs/proxies.py", line 21, in <module>
    import xonsh.tools as xt
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/xonsh/tools.py", line 55, in <module>
    HAVE_CURSOR_SHAPE = False
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/xonsh/tools.py", line 45, in <module>
    from prompt_toolkit.cursor_shapes import (
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/prompt_toolkit/__init__.py", line 29, in <module>
    from .shortcuts import PromptSession, choice, print_formatted_text, prompt
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/prompt_toolkit/shortcuts/__init__.py", line 13, in <module>
    from .progress_bar import ProgressBar, ProgressBarCounter
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/prompt_toolkit/shortcuts/progress_bar/__init__.py", line 3, in <module>
    from .base import ProgressBar, ProgressBarCounter
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/prompt_toolkit/shortcuts/progress_bar/base.py", line 57, in <module>
    from .formatters import Formatter, create_default_formatters
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/prompt_toolkit/shortcuts/progress_bar/formatters.py", line 129, in <module>
    class Percentage(Formatter):
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/prompt_toolkit/shortcuts/progress_bar/formatters.py", line 134, in Percentage
    template = HTML("<percentage>{percentage:>5}%</percentage>")
  File "/Users/pc/.local/lib/rustpython3.13/site-packages/prompt_toolkit/formatted_text/html.py", line 35, in __init__
    document = minidom.parseString(f"<html-root>{value}</html-root>")
  File "/Users/pc/.cargo/git/checkouts/rustpython-63090cdce5e18442/7c3bc5e/crates/pylib/Lib/xml/dom/minidom.py", line 2016, in parseString
    return expatbuilder.parseString(string)
  File "/Users/pc/.cargo/git/checkouts/rustpython-63090cdce5e18442/7c3bc5e/crates/pylib/Lib/xml/dom/expatbuilder.py", line 922, in parseString
    return builder.parseString(string)
  File "/Users/pc/.cargo/git/checkouts/rustpython-63090cdce5e18442/7c3bc5e/crates/pylib/Lib/xml/dom/expatbuilder.py", line 218, in parseString
    parser = self.getParser()
  File "/Users/pc/.cargo/git/checkouts/rustpython-63090cdce5e18442/7c3bc5e/crates/pylib/Lib/xml/dom/expatbuilder.py", line 158, in getParser
    self._parser = self.createParser()
  File "/Users/pc/.cargo/git/checkouts/rustpython-63090cdce5e18442/7c3bc5e/crates/pylib/Lib/xml/dom/expatbuilder.py", line 719, in createParser
    parser.namespace_prefixes = True
AttributeError: 'xmlparser' object has no attribute 'namespace_prefixes'

For community

⬇️ Please click the 👍 reaction instead of leaving a +1 or 👍 comment</issue_description>

<agent_instructions>Investigate what xmlparser.namespace_prefixes does and implement it. Ensure cargo run -- -m test test_xml_etree passes</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Summary by CodeRabbit

  • New Features
    • Expanded XML parser with support for additional event handlers, including namespace declarations, CDATA sections, DOCTYPE declarations, and entity management.
    • Added more configurable properties to the parser for namespace handling, attribute ordering, and entity internalization.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

Added an internal helper macro and expanded the PyExpatLikeXmlParser struct with 22 new fields—including namespace_prefixes, ordered_attributes, specified_attributes, intern, and 17 handler fields—initializing them with appropriate defaults and exposing them as read-write properties.

Changes

Cohort / File(s) Summary
Helper Macro & Struct Extension
crates/stdlib/src/pyexpat.rs
Introduced create_bool_property macro for boolean property definitions. Expanded PyExpatLikeXmlParser with 22 new MutableObject fields: namespace_prefixes, ordered_attributes, specified_attributes, intern, and 17 handler fields (processing_instruction, unparsed_entity_decl, notation_decl, start_namespace_decl, end_namespace_decl, comment, start_cdata_section, end_cdata_section, default, default_expand, not_standalone, external_entity_ref, start_doctype_decl, end_doctype_decl, xml_decl, element_decl, attlist_decl, skipped_entity). Fields initialized to None or empty dict during construction. Exposed via class extension properties with appropriate read-write access and boolean conversion where applicable.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A parser grows with fields so new,
handlers, attributes, a queue,
namespace paths and intern too,
Properties now accessible and true!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes, correctly listing all four key attributes being added: namespace_prefixes, ordered_attributes, specified_attributes, and intern.
Linked Issues check ✅ Passed The PR fully addresses issue #6487 by implementing namespace_prefixes and related attributes (ordered_attributes, specified_attributes, intern) on PyExpatLikeXmlParser, enabling compatibility with xml.dom.minidom and other stdlib code that requires these attributes.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issue: adding the missing xmlparser attributes, a helper macro for boolean properties, and stub handlers for compatibility. No unrelated modifications were introduced.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI and others added 3 commits December 24, 2025 14:51
- 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

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>
- Tests for buffer_text, namespace_prefixes, ordered_attributes, and specified_attributes now pass

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>
- Use proper error propagation in bool_property setter instead of unwrap_or
- Add comment explaining the purpose of the intern dictionary attribute

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix AttributeError in xonsh with rustpython Add missing xmlparser attributes: namespace_prefixes, ordered_attributes, specified_attributes, intern Dec 24, 2025
Copilot AI requested a review from youknowone December 24, 2025 15:04
@github-actions
Copy link
Contributor

Code has been automatically formatted

The code in this PR has been formatted using cargo fmt --all.
Please pull the latest changes before pushing again:

git pull origin copilot/fix-attributeerror-xmlparser

Copy link
Member

@youknowone youknowone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

Resolve additional unexpected success:

UNEXPECTED SUCCESS: test_parse_file (test.test_pyexpat.ParseTest.test_parse_file)
UNEXPECTED SUCCESS: test_parse_str (test.test_pyexpat.ParseTest.test_parse_str)

Also investigate why test_socket fails.

These tests now pass with the added xmlparser attributes.

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 24, 2025

Looks great!

Resolve additional unexpected success:...

Fixed in c9be4ac - removed @unittest.expectedFailure from test_parse_str and test_parse_file as they now pass.

Regarding test_socket: I verified it passes successfully (39.9s) on this branch. The test doesn't use any XML/pyexpat functionality, and my changes only modified crates/stdlib/src/pyexpat.rs and Lib/test/test_pyexpat.py. Could you provide more details about the test_socket failure you're seeing? It might be an intermittent CI issue or from a different context.

@youknowone
Copy link
Member

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c2a7393 and c9be4ac.

⛔ Files ignored due to path filters (1)
  • Lib/test/test_pyexpat.py is excluded by !Lib/**
📒 Files selected for processing (1)
  • crates/stdlib/src/pyexpat.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.rs: Follow the default rustfmt code style by running cargo fmt to format Rust code
Always run clippy to lint Rust code (cargo clippy) before completing tasks and fix any warnings or lints introduced by changes
Follow Rust best practices for error handling and memory management
Use the macro system (pyclass, pymodule, pyfunction, etc.) when implementing Python functionality in Rust

Files:

  • crates/stdlib/src/pyexpat.rs
🧬 Code graph analysis (1)
crates/stdlib/src/pyexpat.rs (2)
crates/vm/src/vm/context.rs (1)
  • new_static_getset (589-603)
crates/vm/src/protocol/object.rs (1)
  • is_true (47-49)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Run rust tests (macos-latest)
  • GitHub Check: Run snippets and cpython tests (macos-latest)
  • GitHub Check: Run snippets and cpython tests (windows-latest)
  • GitHub Check: Run rust tests (windows-latest)
  • GitHub Check: Run rust tests (ubuntu-latest)
  • GitHub Check: Ensure compilation on various targets
  • GitHub Check: Run snippets and cpython tests (ubuntu-latest)
  • GitHub Check: Check Rust code with clippy
🔇 Additional comments (4)
crates/stdlib/src/pyexpat.rs (4)

28-46: LGTM! Well-structured boolean property macro.

The macro correctly handles boolean conversion using is_true(vm)? and properly propagates errors. The pattern mirrors the existing create_property! macro while adding type-safe boolean handling.


74-96: Verify that stub implementation satisfies the linked issue requirements.

The new fields are declared and exposed as properties, but they are not integrated into the parsing logic:

  • The boolean flags (namespace_prefixes, ordered_attributes, specified_attributes) don't affect parser behavior in create_config or do_parse.
  • The 17 new handler fields are never invoked during parsing (only start_element, end_element, and character_data are called in do_parse).
  • The intern dictionary is initialized but never used for string interning.

This stub implementation prevents AttributeError when setting these attributes, which may satisfy issue #6487. However, if client code expects these attributes to actually modify parser behavior (e.g., namespace_prefixes=True should include namespace info in callbacks), further implementation will be needed.

Please confirm whether:

  1. The linked issue only requires these attributes to be settable without error, or
  2. They must also function correctly (affecting parse output/behavior)

If (2), consider opening follow-up issues to track the actual implementation of these handlers and flags.


117-141: LGTM! Proper initialization with good documentation.

All new fields are correctly initialized with appropriate defaults:

  • Boolean flags default to false (matching CPython behavior)
  • intern is initialized as an empty dictionary with a helpful comment explaining its purpose
  • Handler fields default to None

184-273: LGTM! Handler properties registered consistently.

All 17 handler properties are registered following a consistent pattern using the create_property! macro. The naming convention (PascalCase with "Handler" suffix) aligns with CPython's pyexpat handlers.

Comment on lines +160 to +182
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

CPython xml.parsers.expat xmlparser attribute names buffer_text namespace_prefixes ordered_attributes specified_attributes

💡 Result:

Summary of xml.parsers.expat xmlparser attributes

  • buffer_text: when True, the parser buffers character data to avoid many small CharacterDataHandler calls (Expat normally splits text at line endings). Default False; can be changed at any time. [1]

  • buffer_size / buffer_used: buffer_size sets the buffer capacity used when buffer_text is True (changing it flushes the buffer). buffer_used reports how many bytes (UTF‑8) are currently stored. [1]

  • ordered_attributes: when nonzero, attributes passed to StartElementHandler are a list (name, value, name, value, ...) in the document order instead of a dict mapping names→values. Default False. [1]

  • specified_attributes: when nonzero, the parser reports only attributes that were explicitly specified in the instance document (not those defaulted from DTD attribute declarations). Use with care if you rely on attribute-declaration defaults. Default False. [1]

  • namespace handling / namespace_prefixes: Expat can do namespace processing when created via ParserCreate with a namespace separator (the Python wrapper exposes this via namespace_separator). With namespace processing enabled, Expat consumes xmlns/xmlns:... attributes (so they won’t appear as normal attributes) and expands element and attribute names to "URIlocalname". Namespace declaration events can be observed with StartNamespaceDeclHandler/EndNamespaceDeclHandler. (The behavior of attribute names and namespace-declaration attributes follows Expat’s namespace processing rules.) [2][1]

Sources

  • Python xml.parsers.expat (pyexpat) documentation. [1]
  • Expat reference: Namespace processing and attribute handling. [2]

🏁 Script executed:

# First, let me check the actual code to see the full context of what's being registered
head -200 crates/stdlib/src/pyexpat.rs | tail -50

Repository: RustPython/RustPython

Length of output: 1783


🌐 Web query:

CPython pyexpat intern attribute dictionary

💡 Result:

Short answer: pyexpat interns attribute names/strings when it builds the Python attributes dictionary so the attribute keys/other XML name strings become interned Python str objects (reducing allocations and speeding dict lookups). The C implementation calls its string-intern helper when converting Expat's XML_Char strings to Python strings before putting them into the attributes dict; the public API then hands you a normal dict (or ordered list if ordered_attributes is enabled). See the StartElementHandler docs and the pyexpat.c source where string_intern is used.

Sources: Python pyexpat documentation (StartElementHandler / attributes). [1] PyExpat C implementation showing string_intern usage when constructing handler arguments. [2]

References
[1] xml.parsers.expat — StartElementHandler / attributes (Python stdlib docs).
[2] Modules/pyexpat.c (source: string_intern usage when converting element/attribute names).


🌐 Web query:

CPython xml.parsers.expat ParserCreate namespace_prefixes attribute xmlparser

💡 Result:

Short answer: There is no documented xmlparser.namespace_prefixes attribute in CPython's xml.parsers.expat. To enable namespace processing you pass namespace_separator to ParserCreate(); namespace declarations are reported via StartNamespaceDeclHandler/EndNamespaceDeclHandler and element/attribute names are expanded using the separator. Expat itself can be instructed to return the (uri, localname, prefix) triplet (XML_SetReturnNSTriplet), but that API is part of libexpat and is not exposed as a simple xmlparser.namespace_prefixes attribute in the Python docs. [1][2]

References

  • xml.parsers.expat.ParserCreate / xmlparser handlers (namespace_separator, StartNamespaceDeclHandler). [1]
  • Expat namespace processing and XML_SetReturnNSTriplet (triplet return). [2]

Sources
[1] Python docs — xml.parsers.expat (ParserCreate, StartNamespaceDeclHandler).
[2] Expat reference — Namespace Processing / XML_SetReturnNSTriplet.


🌐 Web query:

CPython xml.parsers.expat xmlparser complete list of attributes properties

💡 Result:

Below is a concise, complete listing (as given by the CPython docs) of the xml.parsers.expat xmlparser type: its public methods, instance attributes (properties) and the handler attributes you can set. Source: Python standard-library documentation for xml.parsers.expat. [1]

Methods

  • Parse(data[, isfinal])
  • ParseFile(file)
  • SetBase(base)
  • GetBase()
  • GetInputContext()
  • ExternalEntityParserCreate(context[, encoding])
  • SetParamEntityParsing(flag)
  • UseForeignDTD([flag])
  • SetReparseDeferralEnabled(enabled)
  • GetReparseDeferralEnabled()
  • SetBillionLaughsAttackProtectionActivationThreshold(threshold)
  • SetBillionLaughsAttackProtectionMaximumAmplification(max_factor)
  • SetAllocTrackerActivationThreshold(threshold)
  • SetAllocTrackerMaximumAmplification(max_factor)

Instance attributes / properties

  • buffer_size
  • buffer_text
  • buffer_used
  • ordered_attributes
  • specified_attributes

Error-related attributes (valid after ExpatError)

  • ErrorByteIndex
  • ErrorCode
  • ErrorColumnNumber
  • ErrorLineNumber

Current parse-position attributes

  • CurrentByteIndex
  • CurrentColumnNumber
  • CurrentLineNumber

Handler attributes (assign callable functions: o.handlername = func)

  • XmlDeclHandler(version, encoding, standalone)
  • StartDoctypeDeclHandler(doctypeName, systemId, publicId, has_internal_subset)
  • EndDoctypeDeclHandler()
  • ElementDeclHandler(name, model)
  • AttlistDeclHandler(elname, attname, type, default, required)
  • StartElementHandler(name, attributes)
  • EndElementHandler(name)
  • ProcessingInstructionHandler(target, data)
  • CharacterDataHandler(data)
  • UnparsedEntityDeclHandler(entityName, base, systemId, publicId, notationName)
  • EntityDeclHandler(entityName, is_parameter_entity, value, base, systemId, publicId, notationName)
  • NotationDeclHandler(notationName, base, systemId, publicId)
  • StartNamespaceDeclHandler(prefix, uri)
  • EndNamespaceDeclHandler(prefix)
  • StartCdataSectionHandler()
  • EndCdataSectionHandler()
  • CommentHandler(data)
  • StartResumeHandler() / (see docs for Expat resume-related handlers)
  • ExternalEntityRefHandler(context, base, systemId, publicId)
  • SkippedEntityHandler(entityName)
  • DefaultHandler(data)
  • UnknownEncodingHandler(encoding)
  • StartDoctypeDeclHandler / EndDoctypeDeclHandler (listed above)
  • (Other Expat-specific handlers exposed in the docs — assignable by the same o.handlername = callable pattern)

Notes

  • Many handler names and a few newer methods/attributes (e.g., reparse-deferral and protection-related setters) were added in recent CPython/Expat versions; availability depends on your Python/Expat version. See the docs for the exact signatures and version notes.

Reference
[1] Python documentation — xml.parsers.expat (XMLParser / xmlparser) (CPython stdlib).


🏁 Script executed:

# Check the actual implementation in the file to see if there are comments explaining these attributes
grep -A 5 -B 5 "namespace_prefixes\|intern" crates/stdlib/src/pyexpat.rs | head -60

Repository: RustPython/RustPython

Length of output: 2765


Remove non-standard attributes namespace_prefixes and intern or add comments explaining why they diverge from CPython's xml.parsers.expat API.

According to the official CPython documentation, the xmlparser instance attributes are: buffer_size, buffer_text, buffer_used, ordered_attributes, and specified_attributes. The RustPython implementation registers buffer_text, ordered_attributes, and specified_attributes correctly, but also includes:

  • namespace_prefixes — not documented in CPython's public API
  • intern — not a public xmlparser attribute in CPython (though internal string interning occurs in the C implementation)

Either remove these or add inline documentation explaining them as RustPython extensions to match CPython's behavior and prevent compatibility issues.

🤖 Prompt for AI Agents
In crates/stdlib/src/pyexpat.rs around lines 160–182, the parser registers
non-standard attributes "namespace_prefixes" and "intern" that are not part of
CPython's xml.parsers.expat public API; either remove the create_bool_property!
for "namespace_prefixes" and the create_property! for "intern" to restore
CPython compatibility, or keep them but add concise inline comments immediately
above each registration stating they are RustPython extensions, citing that they
diverge from CPython's documented attributes and why they are present (e.g.,
implementation convenience or internal interning exposure), so callers and
future maintainers understand the intentional API difference.

@youknowone
Copy link
Member

@copilot please check @coderabbitai's review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch CodeRabbit's review comments on PR #6494
gh pr view 6494 --json reviews,comments --jq '.reviews[] | select(.author.login == "coderabbitai[bot]") | {state: .state, body: .body, submittedAt: .submittedAt}'

# Also fetch review comments (line-specific comments)
gh api repos/RustPython/RustPython/pulls/6494/comments --jq '.[] | select(.user.login == "coderabbitai[bot]") | {path: .path, line: .line, body: .body, created_at: .created_at}' | head -50

Length of output: 9427


🏁 Script executed:

#!/bin/bash
# Search for namespace_prefixes usage in RustPython's test files and stdlib
rg -n "namespace_prefixes" --type=py -C 3

# Check if there are any Python test files that demonstrate the actual usage
fd -e py test_xml -x cat {}

# Look for xml.dom.minidom usage patterns
rg -n "expatbuilder|minidom" --type=py -C 2

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Find XML-related test files
fd -e py . | grep -i xml

# Look for the issue reference in commit messages or code
rg -n "6487" --type=py

# Check what's in the pyexpat test directory
find . -path "*/test*" -name "*xml*" -o -name "*expat*" | head -20

# Look at the actual changes in the pyexpat.rs file to see the implementation
grep -n "namespace_prefixes" crates/stdlib/src/pyexpat.rs

Length of output: 690


🌐 Web query:

CPython xml.dom.expatbuilder namespace_prefixes source code

💡 Result:

The CPython implementation of xml.dom.expatbuilder (including the handling of namespace_prefixes) is in the standard-library file Lib/xml/dom/expatbuilder.py in the CPython repo / Python source distributions. You can view the source there; examples/archives with the file:

  • Fossies mirror of the file (expatbuilder.py). [1]
  • CPython / Lib/ listing in the Python docs showing Stdlib source lives under Lib/xml/. [2]

If you want I can fetch and paste the specific function/lines that mention namespace_prefixes (or open the file from the CPython GitHub master branch and show the exact code).

Sources:
[1] Python Lib/xml/dom/expatbuilder.py (Fossies mirror). (fossies.org)
[2] Python XML library / Lib/xml/ documentation (shows source location). (docs.python.org)

Citations:


🌐 Web query:

CPython expatbuilder.py namespace_prefixes parser attribute code

💡 Result:

Short answer: CPython's ElementTree/expat integration exposes a parser attribute named namespace_prefixes (xmlparser.namespace_prefixes) implemented in the pyexpat C module; setting it turns on Expat's "return namespace triplets" mode (XML_SetReturnNSTriplet) so namespace declarations/prefixes are reported to handlers (StartNamespaceDecl/EndNamespaceDecl) instead of being hidden. ElementTree's XMLParser uses the pyexpat parser (ParserCreate/ParserCreateNS) and installs the namespace-decl handlers that Surface these events to TreeBuilder/targets.

Sources:

  • pyexpat C implementation: xmlparser exposes the "namespace_prefixes" attribute and calls XML_SetReturnNSTriplet when it is set. [1]
  • ElementTree (Lib/xml/etree/ElementTree.py): creates the expat parser and installs StartNamespaceDeclHandler/EndNamespaceDecl handlers (so TreeBuilder can receive start-ns / end-ns events). [2]
  • Expat (pyexpat) docs: explains Expat namespace processing and the effect of creating a parser with namespace processing / namespace-related handlers. [3]

References:
[1] pyexpat C source (shows namespace_prefixes handling and XML_SetReturnNSTriplet). (archive.softwareheritage.org)
[2] CPython ElementTree source (XMLParser uses expat.ParserCreate and sets namespace-decl handlers). (android.googlesource.com)
[3] Python pyexpat / Expat docs on namespace processing. (docs.python.org)

If you want, I can paste the exact lines from expatbuilder/ElementTree and pyexpat.c that show the attribute and handler wiring.

Citations:


🌐 Web query:

CPython pyexpat xmlparser intern attribute exposed

💡 Result:

Short answer: No — CPython's xml.parsers.expat (pyexpat) xmlparser type does not expose an "intern" attribute. The documented xmlparser attributes (buffer_size, buffer_text, ordered_attributes, specified_attributes, error info, etc.) do not include any "intern" flag. [1] (docs.python.org)

If you need name/attribute interning in Python XML parsing, use the SAX expat-based reader which supports the SAX feature/property for string interning (feature_string_interning / property_interning_dict) — that mechanism performs interning for element/attribute names. [2] (android.googlesource.com)

Citations:


@youknowone, I'm CodeRabbit responding to your request. Let me clarify my review findings after further investigation:

Review Correction

My review comment flagged both namespace_prefixes and intern as non-standard attributes. After investigating CPython's source code, I need to correct part of that assessment:

namespace_prefixes - Valid CPython Attribute

CPython's pyexpat C module does expose a namespace_prefixes attribute on the xmlparser object. When set, it calls XML_SetReturnNSTriplet to enable namespace prefix reporting. This attribute is used by xml.dom.expatbuilder and xml.etree.ElementTree internally.

My review comment was incorrect about this attribute. The implementation in this PR is correct and needed for compatibility with CPython's xml.dom.minidom (as mentioned in issue #6487).

intern - Non-Standard Attribute

CPython's xml.parsers.expat xmlparser does not expose an "intern" attribute. String interning in CPython's XML parsing is handled through SAX's feature_string_interning mechanism, not as a direct xmlparser attribute.

My review comment was correct about this attribute. The intern attribute at line 182 in crates/stdlib/src/pyexpat.rs should either be:

  • Removed for strict CPython compatibility, or
  • Documented as a RustPython extension with a comment explaining the divergence

Recommendation

The namespace_prefixes implementation is correct and should remain. However, please address the intern attribute by either removing it or adding documentation explaining why it differs from CPython's API.

🐰💭


✏️ Learnings added
Learnt from: youknowone
URL: https://github.com/RustPython/RustPython/pull/6494

Timestamp: 2025-12-24T23:47:38.444Z
Learning: CPython's xml.parsers.expat xmlparser exposes a namespace_prefixes boolean attribute (implemented in the pyexpat C module) that controls namespace prefix reporting via XML_SetReturnNSTriplet. This attribute is used internally by xml.dom.expatbuilder and xml.etree.ElementTree.

Learnt from: youknowone
URL: https://github.com/RustPython/RustPython/pull/6494

Timestamp: 2025-12-24T23:47:38.444Z
Learning: CPython's xml.parsers.expat xmlparser does not expose an intern attribute. String interning for XML parsing in CPython is handled through SAX's expatreader feature_string_interning mechanism, not as a direct xmlparser.intern attribute.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Contributor Author

Copilot AI commented Dec 24, 2025

@copilot please check @coderabbitai's review

I've reviewed the code and verified that:

✅ All tests pass (test_xml_etree, SetAttributeTest, ParseTest)
✅ Clippy passes with no warnings
✅ Code follows Rust best practices

However, I don't see the actual review comments from @coderabbitai in the thread. Could you share the specific concerns or suggestions from the review so I can address them?

@youknowone
Copy link
Member

@copilot #6494 (comment)

Copy link
Contributor Author

Copilot AI commented Dec 24, 2025

@copilot #6494 (comment)

I'm unable to access external URLs directly. Could you please paste the specific review comments from @coderabbitai here so I can address them? Alternatively, if there are specific changes you'd like me to make based on that review, please let me know.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/RustPython/RustPython/issues/comments/3690619703
    • Triggering command: /usr/bin/curl curl -s REDACTED -H Accept: application/vnd.github.v3&#43;json (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@youknowone
Copy link
Member

@copilot

❌ intern - Non-Standard Attribute
CPython's xml.parsers.expat xmlparser does not expose an "intern" attribute. String interning in CPython's XML parsing is handled through SAX's feature_string_interning mechanism, not as a direct xmlparser attribute.

My review comment was correct about this attribute. The intern attribute at line 182 in crates/stdlib/src/pyexpat.rs should either be:

Removed for strict CPython compatibility, or
Documented as a RustPython extension with a comment explaining the divergence


please verify it is correct and continue

Copy link
Contributor Author

Copilot AI commented Dec 25, 2025

@copilot

❌ intern - Non-Standard Attribute
...

The review comment is incorrect. CPython's xml.parsers.expat xmlparser does expose an intern attribute as a dictionary.

Evidence:

  1. ✅ CPython 3.12: hasattr(parser, 'intern') returns True, type is dict
  2. ✅ Used in CPython's own code: Lib/xml/dom/expatbuilder.py line 159: self._intern_setdefault = self._parser.intern.setdefault
  3. ✅ Listed as a data attribute alongside namespace_prefixes, ordered_attributes, specified_attributes
  4. ✅ Our implementation works correctly with the expatbuilder code path from the original issue

The intern attribute is for string interning of element/attribute names for memory efficiency and should remain as implemented.

@youknowone youknowone marked this pull request as ready for review December 25, 2025 00:08
@youknowone youknowone merged commit 72cf6c3 into main Dec 25, 2025
16 checks passed
@youknowone youknowone deleted the copilot/fix-attributeerror-xmlparser branch December 25, 2025 00:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AttributeError: 'xmlparser' object has no attribute 'namespace_prefixes'

2 participants