Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Addressed PR comments
  • Loading branch information
ukarroum committed Apr 17, 2026
commit 34af03117c01e934732669a9431b79642bd35d56
27 changes: 24 additions & 3 deletions Lib/test/test_sax.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
XMLFilterBase, prepare_input_source
from xml.sax.expatreader import create_parser
from xml.sax.handler import (feature_namespaces, feature_external_ges,
LexicalHandler)
LexicalHandler, feature_namespace_prefixes)
from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
from xml import sax
from io import BytesIO, StringIO
Expand Down Expand Up @@ -1319,15 +1319,36 @@ def startElementNS(self, name, qname, attrs):
("<E />", "E"),
):
parser = create_parser()
parser.setFeature(handler.feature_namespaces, 1)
parser.setFeature(handler.feature_namespace_prefixes, 1)
parser.setFeature(feature_namespaces, 1)
parser.setFeature(feature_namespace_prefixes, 1)

h = Handler()

parser.setContentHandler(h)
parser.parse(StringIO(xml_s))
self.assertEqual(h.qname, expected_qname)

def test_qualified_names_when_feature_not_set(self):

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

for xml_s in (
"<Q:E xmlns:Q='http://example.org/testuri'/>",
"<E xmlns='http://example.org/testuri'/>",
"<E />",
):
parser = create_parser()
parser.setFeature(feature_namespaces, 1)

h = Handler()

parser.setContentHandler(h)
parser.parse(StringIO(xml_s))

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.

Don't leave 3 blank lines, only 2 is sufficient.

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

self.assertIsNone(h.qname)


# ===========================================================================
#
Expand Down
11 changes: 7 additions & 4 deletions Lib/xml/sax/expatreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def getSystemId(self):
class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator):
"""SAX driver for the pyexpat C module."""

def __init__(self, namespaceHandling=0, namespacePrefixesHandling=0, bufsize=2**16-20):
def __init__(self, namespaceHandling=0, bufsize=2**16-20):
xmlreader.IncrementalParser.__init__(self, bufsize)
self._source = xmlreader.InputSource()
self._parser = None
Expand All @@ -89,7 +89,7 @@ def __init__(self, namespaceHandling=0, namespacePrefixesHandling=0, bufsize=2**
self._entity_stack = []
self._external_ges = 0
self._interning = None
self._namespace_prefixes = namespacePrefixesHandling
self._namespace_prefixes = 0

# XMLReader methods

Expand Down Expand Up @@ -147,8 +147,6 @@ def setFeature(self, name, state):
self._interning = {}
else:
self._interning = None
elif name == feature_namespace_prefixes:
self._namespace_prefixes = state
elif name == feature_validation:
if state:
raise SAXNotSupportedException(
Expand All @@ -157,6 +155,8 @@ def setFeature(self, name, state):
if state:
raise SAXNotSupportedException(
"expat does not read external parameter entities")
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.

@ukarroum I wonder what the expected behaviors is here when feature_namespaces is currently disabled. Or more generally speaking: Do we know anything about the relation between these two features? Potential options seem to be:

  • Block enabling/disabling when their dependency would be violated.
  • Auto-enable/disable to respect dependency at all times
  • Keep the two fully separate but check for both rather than just self._namespace_prefixes where checking for being active?

Just thinking aloud.

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.

good point, I think it will make sense to just enable feature_namespaces when feature_namespace_prefixes is also enabled (and also disable feature_namespace_prefixes if feature_namespaces is disabled).
I will update both set/get feature

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.

actually one drawback I see for this is :

enable feature_namespace_prefixes
disable feature_namespaces
enable feature_namespaces

this will result in feature_namespace_prefixes being disabled which feels odd.

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 went with 1) instead.
I pushed a small change to check if namespace is enabled when we enable namespace prefixes.

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.

@ukarroum I like it. I think one small dedicated test for that would be great where namespaces are disabled and the exception is raise with the expected message. (Arguably, the success case is already covered by existing tests.)

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.

added test

else:
raise SAXNotRecognizedException(
"Feature '%s' not recognized" % name)
Expand Down Expand Up @@ -375,6 +375,9 @@ def start_element_ns(self, name, attrs):
newattrs[apair] = value
qnames[apair] = qname

if not self._namespace_prefixes:
elem_qname = None

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

Expand Down