Stefan Behnel added the comment:

@gene_wood: that's unrelated. This ticket is about attributes being rejected 
incorrectly.

Fixing the example of the OP:

>>> from xml.etree.ElementTree import *
>>> svg = ElementTree(XML("""
... <svg width="12cm" height="4cm" viewBox="0 0 1200 400" 
xmlns="http://www.w3.org/2000/svg"; version="1.1">
... <rect x="1" y="1" width="1198" height="398" fill="none" stroke="blue" 
stroke-width="2" />
... </svg>
... """))
>>> tostring(svg.getroot())   # formatting is mine
b'<svg:svg xmlns:svg="http://www.w3.org/2000/svg"; height="4cm" version="1.1" 
viewBox="0 0 1200 400" width="12cm">\n
      <svg:rect fill="none" height="398" stroke="blue" stroke-width="2" 
width="1198" x="1" y="1" />\n
  </svg:svg>'
>>> svg.write('simple_new.svg',encoding='UTF-8',default_namespace='http://www.w3.org/2000/svg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/xml/etree/ElementTree.py", line 826, in write
    qnames, namespaces = _namespaces(self._root, default_namespace)
  File "/usr/lib/python3.3/xml/etree/ElementTree.py", line 942, in _namespaces
    add_qname(key)
  File "/usr/lib/python3.3/xml/etree/ElementTree.py", line 920, in add_qname
    "cannot use non-qualified names with "
ValueError: cannot use non-qualified names with default_namespace option
>>> svg.write('simple_new.svg',encoding='UTF-8')
>>> 

So, it works without namespace defaulting and fails with an incorrect error 
when a default namespace is provided. Clearly a bug.

Regarding the proposed patch: it looks like the right thing to do in general, 
but it has a relatively high code impact. I would prefer a patch with lower 
churn. One thing that could be tried is to use only one tag cache dict and 
extend the key from the plain tag to (tag, is_attribute). Might have a 
performance impact on the already slow serialiser, though. In any case, both 
approaches are quite wasteful, because they duplicate the entire 
namespace-prefix mapping just because there might be a single namespace that 
behaves differently for atributes. An alternative could be to split the *value* 
of the mapping in two: (element_prefix, attribute_prefix). This would keep the 
overhead at serialisation low, with only slightly more work when building the 
mapping. At first sight, I like that idea better.

This code returns a list in one case and a set-like view in another (Py3):

+    if default_namespace:
+        prefixes_list = [ (default_namespace, "") ]
+        prefixes_list.extend(namespaces.items())
+    else:
+        prefixes_list = namespaces.items()

I can't see the need for this change. Why can't the default namespace be stored 
in the namespaces dict right from the start, as it was before?

As a minor nitpick, this lambda based sort key:

    key=lambda x: x[1]):  # sort on prefix

is better expressed using operator.itemgetter(1).

I'd also rename the "defaultable" flag to "is_attribute" and pass it as keyword 
argument (bare boolean parameters are unreadable in function calls).

Given the impact of this change, I'd also suggest not applying it to Py2.x 
anymore.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue17088>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to