def __getattr__(self, tagName: str) -> Tag: if tagName == "transparent": return Tag("") # allow for E.del as E.del_ tagName = tagName.rstrip("_") if tagName not in VALID_HTML_TAG_NAMES: raise AttributeError(f"unknown tag {tagName!r}") return Tag(tagName)
def __getattr__(self, tagName): if tagName == 'transparent': return Tag('') # allow for E.del as E.del_ tagName = tagName.rstrip('_') if tagName not in VALID_HTML_TAG_NAMES: raise AttributeError('unknown tag %r' % (tagName,)) return Tag(tagName)
def test_serializeUnicode(self): """ Test that unicode is encoded correctly in the appropriate places, and raises an error when it occurs in inappropriate place. """ snowman = u'\N{SNOWMAN}' return gatherResults([ self.assertFlattensTo(snowman, '\xe2\x98\x83'), self.assertFlattensTo(tags.p(snowman), '<p>\xe2\x98\x83</p>'), self.assertFlattensTo(Comment(snowman), '<!--\xe2\x98\x83-->'), self.assertFlattensTo(CDATA(snowman), '<![CDATA[\xe2\x98\x83]]>'), self.assertFlatteningRaises(Tag(snowman), UnicodeEncodeError), self.assertFlatteningRaises(Tag('p', attributes={snowman: ''}), UnicodeEncodeError), ])
def test_tagWithoutLocation(self): """ If a L{FlattenerError} is created with a L{Tag} instance without source location information, only the tagName is included in the string representation of the exception. """ self.assertEqual( str(FlattenerError(RuntimeError("reason"), [Tag('span')], [])), "Exception while flattening:\n" " Tag <span>\n" "RuntimeError: reason\n")
def test_tag(self): """ If a L{FlattenerError} is created with a L{Tag} instance with source location information, the source location is included in the string representation of the exception. """ tag = Tag('div', filename='/foo/filename.xhtml', lineNumber=17, columnNumber=12) self.assertEqual( str(FlattenerError(RuntimeError("reason"), [tag], [])), "Exception while flattening:\n" " File \"/foo/filename.xhtml\", line 17, column 12, in \"div\"\n" "RuntimeError: reason\n")
def startElementNS(self, namespaceAndName, qname, attrs): """ Gets called when we encounter a new xmlns attribute. @param namespaceAndName: a (namespace, name) tuple, where name determines which type of action to take, if the namespace matches L{TEMPLATE_NAMESPACE}. @param qname: ignored. @param attrs: attributes on the element being started. """ filename = self.sourceFilename lineNumber = self.locator.getLineNumber() columnNumber = self.locator.getColumnNumber() ns, name = namespaceAndName if ns == TEMPLATE_NAMESPACE: if name == 'transparent': name = '' elif name == 'slot': try: # Try to get the default value for the slot default = attrs[(None, 'default')] except KeyError: # If there wasn't one, then use None to indicate no # default. default = None el = slot( attrs[(None, 'name')], default=default, filename=filename, lineNumber=lineNumber, columnNumber=columnNumber) self.stack.append(el) self.current.append(el) self.current = el.children return render = None attrs = OrderedDict(attrs) for k, v in items(attrs): attrNS, justTheName = k if attrNS != TEMPLATE_NAMESPACE: continue if justTheName == 'render': render = v del attrs[k] # nonTemplateAttrs is a dictionary mapping attributes that are *not* in # TEMPLATE_NAMESPACE to their values. Those in TEMPLATE_NAMESPACE were # just removed from 'attrs' in the loop immediately above. The key in # nonTemplateAttrs is either simply the attribute name (if it was not # specified as having a namespace in the template) or prefix:name, # preserving the xml namespace prefix given in the document. nonTemplateAttrs = OrderedDict() for (attrNs, attrName), v in items(attrs): nsPrefix = self.prefixMap.get(attrNs) if nsPrefix is None: attrKey = attrName else: attrKey = '%s:%s' % (nsPrefix, attrName) nonTemplateAttrs[attrKey] = v if ns == TEMPLATE_NAMESPACE and name == 'attr': if not self.stack: # TODO: define a better exception for this? raise AssertionError( '<{%s}attr> as top-level element' % (TEMPLATE_NAMESPACE,)) if 'name' not in nonTemplateAttrs: # TODO: same here raise AssertionError( '<{%s}attr> requires a name attribute' % (TEMPLATE_NAMESPACE,)) el = Tag('', render=render, filename=filename, lineNumber=lineNumber, columnNumber=columnNumber) self.stack[-1].attributes[nonTemplateAttrs['name']] = el self.stack.append(el) self.current = el.children return # Apply any xmlns attributes if self.xmlnsAttrs: nonTemplateAttrs.update(OrderedDict(self.xmlnsAttrs)) self.xmlnsAttrs = [] # Add the prefix that was used in the parsed template for non-template # namespaces (which will not be consumed anyway). if ns != TEMPLATE_NAMESPACE and ns is not None: prefix = self.prefixMap[ns] if prefix is not None: name = '%s:%s' % (self.prefixMap[ns],name) el = Tag( name, attributes=OrderedDict(nonTemplateAttrs), render=render, filename=filename, lineNumber=lineNumber, columnNumber=columnNumber) self.stack.append(el) self.current.append(el) self.current = el.children
def startElementNS( self, namespaceAndName: Tuple[str, str], qname: Optional[str], attrs: Mapping[Tuple[Optional[str], str], str], ) -> None: """ Gets called when we encounter a new xmlns attribute. @param namespaceAndName: a (namespace, name) tuple, where name determines which type of action to take, if the namespace matches L{TEMPLATE_NAMESPACE}. @param qname: ignored. @param attrs: attributes on the element being started. """ filename = self.sourceFilename lineNumber = self.locator.getLineNumber() columnNumber = self.locator.getColumnNumber() ns, name = namespaceAndName if ns == TEMPLATE_NAMESPACE: if name == "transparent": name = "" elif name == "slot": default: Optional[str] try: # Try to get the default value for the slot default = attrs[(None, "default")] except KeyError: # If there wasn't one, then use None to indicate no # default. default = None sl = slot( attrs[(None, "name")], default=default, filename=filename, lineNumber=lineNumber, columnNumber=columnNumber, ) self.stack.append(sl) self.current.append(sl) self.current = sl.children return render = None attrs = OrderedDict(attrs) for k, v in list(attrs.items()): attrNS, justTheName = k if attrNS != TEMPLATE_NAMESPACE: continue if justTheName == "render": render = v del attrs[k] # nonTemplateAttrs is a dictionary mapping attributes that are *not* in # TEMPLATE_NAMESPACE to their values. Those in TEMPLATE_NAMESPACE were # just removed from 'attrs' in the loop immediately above. The key in # nonTemplateAttrs is either simply the attribute name (if it was not # specified as having a namespace in the template) or prefix:name, # preserving the xml namespace prefix given in the document. nonTemplateAttrs = OrderedDict() for (attrNs, attrName), v in attrs.items(): nsPrefix = self.prefixMap.get(attrNs) if nsPrefix is None: attrKey = attrName else: attrKey = f"{nsPrefix}:{attrName}" nonTemplateAttrs[attrKey] = v if ns == TEMPLATE_NAMESPACE and name == "attr": if not self.stack: # TODO: define a better exception for this? raise AssertionError( f"<{{{TEMPLATE_NAMESPACE}}}attr> as top-level element") if "name" not in nonTemplateAttrs: # TODO: same here raise AssertionError( f"<{{{TEMPLATE_NAMESPACE}}}attr> requires a name attribute" ) el = Tag( "", render=render, filename=filename, lineNumber=lineNumber, columnNumber=columnNumber, ) self.stack[-1].attributes[nonTemplateAttrs["name"]] = el self.stack.append(el) self.current = el.children return # Apply any xmlns attributes if self.xmlnsAttrs: nonTemplateAttrs.update(OrderedDict(self.xmlnsAttrs)) self.xmlnsAttrs = [] # Add the prefix that was used in the parsed template for non-template # namespaces (which will not be consumed anyway). if ns != TEMPLATE_NAMESPACE and ns is not None: prefix = self.prefixMap[ns] if prefix is not None: name = "{}:{}".format(self.prefixMap[ns], name) el = Tag( name, attributes=OrderedDict( cast(Mapping[Union[bytes, str], str], nonTemplateAttrs)), render=render, filename=filename, lineNumber=lineNumber, columnNumber=columnNumber, ) self.stack.append(el) self.current.append(el) self.current = el.children