Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6ecfc28
bpo-54873: Backported namespaces prefixes support for xml.sax.expatre…
ukarroum Apr 26, 2024
e9ac454
bpo-54873: Added News entry
ukarroum Apr 26, 2024
9c365c2
Merge branch 'main' into fix-issue-54873
ukarroum Jun 9, 2024
2fc666a
Merge branch 'main' into fix-issue-54873
ukarroum Apr 29, 2025
fe9d82f
Merge branch 'main' into fix-issue-54873
ukarroum Nov 2, 2025
be878cb
Moved test_namespace_prefix to test_sax.py
ukarroum Nov 2, 2025
0e3f870
test_sax: Replaced namespace tests with one test on qualified names
ukarroum Nov 2, 2025
c88e7ed
ExpatParser: Add namespacePrefixesHandling
ukarroum Nov 2, 2025
27cb273
namespace prefixes: add link to w3.org
ukarroum Nov 2, 2025
91112b9
Merge branch 'main' into fix-issue-54873
ukarroum Nov 24, 2025
d3cbe5f
Merge branch 'main' into fix-issue-54873
ukarroum Apr 17, 2026
1d343f1
Update imports in Lib/test/test_sax.py
ukarroum Apr 17, 2026
256a97b
Approuved readibility of unit test
ukarroum Apr 17, 2026
7c0da60
Update pyXML spelling in News.d
ukarroum Apr 17, 2026
e219450
Update Lib/xml/sax/expatreader.py
ukarroum Apr 17, 2026
34af031
Addressed PR comments
ukarroum Apr 17, 2026
8075f8b
Merge branch 'fix-issue-54873' of github.com:ukarroum/cpython into fi…
ukarroum Apr 17, 2026
2004846
Removed unused import
ukarroum Apr 17, 2026
c3e00e2
Update news entry
ukarroum Apr 17, 2026
d3b08ec
Update Doc/whatsnew/3.15.rst
ukarroum Apr 17, 2026
e8bcb30
Update news entry
ukarroum Apr 17, 2026
dfff704
Merge branch 'fix-issue-54873' of github.com:ukarroum/cpython into fi…
ukarroum Apr 17, 2026
7de4ce5
Add a check on namespace feature when enabling namespace prefixes
ukarroum Apr 17, 2026
08d659e
Add test for feature_namespace_prefixes enabled while feature_namespa…
ukarroum Apr 17, 2026
7cdc402
Update Lib/test/test_sax.py
ukarroum Apr 17, 2026
cd7de73
Update test
ukarroum Apr 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Lib/test/test_xml_expatreader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import unittest
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are we having a new test file? there should already be a testfile for expat reader.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I assumed all xml unit tests were in the test_xml_* files. Looks like there is a test_sax.py.
Moved test there.


from xml.sax.expatreader import create_parser
from xml.sax import handler


class feature_namespace_prefixes(unittest.TestCase):
def setUp(self):
self.parser = create_parser()
self.parser.setFeature(handler.feature_namespaces, 1)
self.parser.setFeature(handler.feature_namespace_prefixes, 1)

def test_prefix_given(self):
class Handler(handler.ContentHandler):
def startElementNS(self, name, qname, attrs):
self.qname = qname

h = Handler()

self.parser.setContentHandler(h)
self.parser.feed("<Q:E xmlns:Q='http://example.org/testuri'/>")
self.parser.close()
print("self.assertEqual")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What are those?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A shamelessly forgot debug print.
I removed it

self.assertFalse(h.qname is None)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is not sufficient. We should match against the exact qname.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed

17 changes: 10 additions & 7 deletions Lib/xml/sax/expatreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def __init__(self, namespaceHandling=0, bufsize=2**16-20):
self._entity_stack = []
self._external_ges = 0
self._interning = None
self._namespace_prefixes = 1
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is it 1 by default?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed to use a new namespacePrefixesHandling argument.


# XMLReader methods

Expand Down Expand Up @@ -126,8 +127,9 @@ def getFeature(self, name):
return self._namespaces
elif name == feature_string_interning:
return self._interning is not None
elif name in (feature_validation, feature_external_pes,
feature_namespace_prefixes):
elif name == feature_namespace_prefixes:
return self._namespace_prefixes
elif name in (feature_validation, feature_external_pes):
return 0
elif name == feature_external_ges:
return self._external_ges
Expand All @@ -147,6 +149,8 @@ def setFeature(self, name, state):
self._interning = {}
else:
self._interning = None
elif name == feature_namespace_prefixes:
self._namespace_prefixes = state
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My vote for moving this one further down — right after elif name == feature_external_pes: — to match the left side of the diff.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

elif name == feature_validation:
if state:
raise SAXNotSupportedException(
Expand All @@ -155,10 +159,6 @@ def setFeature(self, name, state):
if state:
raise SAXNotSupportedException(
"expat does not read external parameter entities")
elif name == feature_namespace_prefixes:
if state:
raise SAXNotSupportedException(
"expat does not report namespace prefixes")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Was it a limitation from the C extension module? was it a Expat version limitation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I did a quick git blame, and looks like this specific check was added in this commit: 18476a3 (from 2002).
and in this commit Expat version used is 1.95 (which should support namespace prefixes), so I would say the limitation was probably just in the python wrapper.

else:
raise SAXNotRecognizedException(
"Feature '%s' not recognized" % name)
Expand Down Expand Up @@ -347,11 +347,14 @@ def start_element_ns(self, name, attrs):
pair = name.split()
if len(pair) == 1:
# no namespace
elem_qname = name
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have no idea whether this is correct or not here. Is there some specs that we could follow for the implementation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

if you're referring specificaly to elem_qname, there is the spec: https://www.w3.org/TR/xml-names/#ns-qualnames.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I also added another test to test the "else" branch.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@picnixz these lines are 1:1 from PyXML 0.8.4:

meld

pair = (None, name)
elif len(pair) == 3:
elem_qname = "%s:%s" % (pair[2], pair[1])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note to self: This is the key value provider in this pull request. pair[2] was previously not exposed.

pair = pair[0], pair[1]
else:
# default namespace
elem_qname = pair[1]
pair = tuple(pair)

newattrs = {}
Expand All @@ -374,7 +377,7 @@ def start_element_ns(self, name, attrs):
newattrs[apair] = value
qnames[apair] = qname

self._cont_handler.startElementNS(pair, None,
self._cont_handler.startElementNS(pair, elem_qname,
Comment thread
ukarroum marked this conversation as resolved.
AttributesNSImpl(newattrs, qnames))

def end_element_ns(self, name):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Backported namespaces prefixes support for xml.sax.expatreader from PyXml
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A What's New entry should be written; this is a new feature. Also, I don't think we should indicate PyXML either. Please look at other changelog entries involving pyexpat to have an idea of how to write them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.
reason why I added the "from PyXml" is that I didn't write the code from scratch.
I backported / copied it from the existing PyXml implementation.

Not sure how to correctly credit the original library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
Backported namespaces prefixes support for xml.sax.expatreader from PyXml
Backported namespaces prefixes support for xml.sax.expatreader from PyXML

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread
ukarroum marked this conversation as resolved.
Outdated
(0.8.4)
Loading