Commit 30e6dd80 authored by di68kap's avatar di68kap
Browse files

- syntaxtree: Node.attr_active renamed to Node.has_attr and semantics changed.

parent e7cfb370
...@@ -16,7 +16,7 @@ cdef class Node: ...@@ -16,7 +16,7 @@ cdef class Node:
cpdef is_anonymous(self) cpdef is_anonymous(self)
cpdef _content(self) cpdef _content(self)
cpdef with_pos(self, pos) cpdef with_pos(self, pos)
cpdef attr_active(self) cpdef has_attr(self)
# cpdef compare_attr(self, other) # cpdef compare_attr(self, other)
# cpdef _tree_repr(self, tab, open_fn, close_fn, data_fn, density, inline, inline_fn) # cpdef _tree_repr(self, tab, open_fn, close_fn, data_fn, density, inline, inline_fn)
# cpdef as_sxpr(self, src, indentation, compact) # cpdef as_sxpr(self, src, indentation, compact)
......
...@@ -198,7 +198,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -198,7 +198,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
else: else:
duplicate = self.__class__(self.tag_name, self.result, True) duplicate = self.__class__(self.tag_name, self.result, True)
duplicate._pos = self._pos duplicate._pos = self._pos
if self.attr_active(): if self.has_attr():
duplicate.attr.update(copy.deepcopy(self._xml_attr)) duplicate.attr.update(copy.deepcopy(self._xml_attr))
# duplicate._xml_attr = copy.deepcopy(self._xml_attr) # this is not cython compatible # duplicate._xml_attr = copy.deepcopy(self._xml_attr) # this is not cython compatible
return duplicate return duplicate
...@@ -437,6 +437,24 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -437,6 +437,24 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
def attr(self): def attr(self):
""" """
Returns a dictionary of XML-attr attached to the node. Returns a dictionary of XML-attr attached to the node.
Examples:
>>> node = Node(None, '')
>>> print('Any attributes present?', node.has_attr())
Any attributes present? False
>>> node.attr['id'] = 'identificator'
>>> node.attr
OrderedDict([('id', 'identificator')])
>>> node.attr['id']
'identificator'
>>> del node['id']
>>> node.attr
OrderedDict()
NOTE: Use `node.attr_active()` rather than bool(node.attr) to check the
presence of any attributes. Attribute dictionaries are created lazily
and node.attr would create a dictionary, even though it may never be
needed any more.
""" """
try: try:
if self._xml_attr is None: # cython compatibility if self._xml_attr is None: # cython compatibility
...@@ -446,14 +464,18 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -446,14 +464,18 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
return self._xml_attr return self._xml_attr
def attr_active(self) -> bool: def has_attr(self) -> bool:
""" """
Returns True, if XML-Attributes of this node have ever been set Returns `True`, if the node has any attributes, `False` otherwise.
or queried, even if unsuccessfully.
This function does not create an attribute dictionary, therefore
it should be prefered to querying node.attr when testing for the
existence of any attributes.
""" """
try: try:
if self._xml_attr is not None: # if self._xml_attr is not None:
return True # return True
return bool(self._xml_attr)
except AttributeError: except AttributeError:
pass pass
return False return False
...@@ -464,12 +486,12 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -464,12 +486,12 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
Returns True, if `self` and `other` have the same attributes with the Returns True, if `self` and `other` have the same attributes with the
same attribute values. same attribute values.
""" """
if self.attr_active(): if self.has_attr():
if other.attr_active(): if other.has_attr():
return self.attr == other.attr return self.attr == other.attr
return len(self.attr) == 0 return len(self.attr) == 0
# self has empty dictionary and other has no attributes # self has empty dictionary and other has no attributes
elif other.attr_active(): elif other.has_attr():
return len(other.attr) == 0 return len(other.attr) == 0
# other has empty attribute dictionary and self as no attributes # other has empty attribute dictionary and self as no attributes
return True # neither self nor other have any attributes return True # neither self nor other have any attributes
...@@ -661,7 +683,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -661,7 +683,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
txt = [left_bracket, node.tag_name] txt = [left_bracket, node.tag_name]
# s += " '(pos %i)" % node.add_pos # s += " '(pos %i)" % node.add_pos
# txt.append(str(id(node))) # for debugging # txt.append(str(id(node))) # for debugging
if node.attr_active(): if node.has_attr():
txt.extend(' `(%s "%s")' % (k, v) for k, v in node.attr.items()) txt.extend(' `(%s "%s")' % (k, v) for k, v in node.attr.items())
if src: if src:
line, col = line_col(lbreaks, node.pos) line, col = line_col(lbreaks, node.pos)
...@@ -715,13 +737,13 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -715,13 +737,13 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
if node.tag_name in omit_tags: if node.tag_name in omit_tags:
return '' return ''
txt = ['<', node.tag_name] txt = ['<', node.tag_name]
has_reserved_attrs = node.attr_active() \ has_reserved_attrs = node.has_attr() \
and any(r in node.attr for r in {'err', 'line', 'col'}) and any(r in node.attr for r in {'err', 'line', 'col'})
if node.attr_active(): if node.has_attr():
txt.extend(' %s="%s"' % (k, v) for k, v in node.attr.items()) txt.extend(' %s="%s"' % (k, v) for k, v in node.attr.items())
if src and not has_reserved_attrs: if src and not has_reserved_attrs:
txt.append(' line="%i" col="%i"' % line_col(line_breaks, node.pos)) txt.append(' line="%i" col="%i"' % line_col(line_breaks, node.pos))
if src == '' and not (node.attr_active() and '_pos' in node.attr) and node.pos >= 0: if src == '' and not (node.has_attr() and '_pos' in node.attr) and node.pos >= 0:
txt.append(' _pos="%i"' % node.pos) txt.append(' _pos="%i"' % node.pos)
if root and id(node) in root.error_nodes and not has_reserved_attrs: if root and id(node) in root.error_nodes and not has_reserved_attrs:
txt.append(' err="%s"' % ''.join(str(err).replace('"', r'\"') txt.append(' err="%s"' % ''.join(str(err).replace('"', r'\"')
...@@ -752,7 +774,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -752,7 +774,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
printed on several lines to avoid unwanted gaps in the output. printed on several lines to avoid unwanted gaps in the output.
""" """
return node.tag_name in inline_tags \ return node.tag_name in inline_tags \
or (node.attr_active() or (node.has_attr()
and node.attr.get('xml:space', 'default') == 'preserve') and node.attr.get('xml:space', 'default') == 'preserve')
line_breaks = linebreaks(src) if src else [] line_breaks = linebreaks(src) if src else []
...@@ -765,7 +787,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil ...@@ -765,7 +787,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil
data = [self.tag_name, data = [self.tag_name,
[child.to_json_obj() for child in self.children] [child.to_json_obj() for child in self.children]
if self.children else str(self._result)] if self.children else str(self._result)]
has_attr = self.attr_active() has_attr = self.has_attr()
if self._pos >= 0 or has_attr: if self._pos >= 0 or has_attr:
data.append(self._pos) data.append(self._pos)
if has_attr: if has_attr:
...@@ -938,7 +960,7 @@ class RootNode(Node): ...@@ -938,7 +960,7 @@ class RootNode(Node):
duplicate.children = NoChildren duplicate.children = NoChildren
duplicate._result = self._result duplicate._result = self._result
duplicate._pos = self._pos duplicate._pos = self._pos
if self.attr_active(): if self.has_attr():
duplicate.attr.update(copy.deepcopy(self._xml_attr)) duplicate.attr.update(copy.deepcopy(self._xml_attr))
# duplicate._xml_attr = copy.deepcopy(self._xml_attr) # this is blocked by cython # duplicate._xml_attr = copy.deepcopy(self._xml_attr) # this is blocked by cython
duplicate.errors = copy.copy(self.errors) duplicate.errors = copy.copy(self.errors)
...@@ -968,7 +990,7 @@ class RootNode(Node): ...@@ -968,7 +990,7 @@ class RootNode(Node):
self.children = node.children self.children = node.children
self._pos = node._pos self._pos = node._pos
self.tag_name = node.tag_name self.tag_name = node.tag_name
if node.attr_active(): if node.has_attr():
self._xml_attr = node._xml_attr self._xml_attr = node._xml_attr
# self._content = node._content # self._content = node._content
if id(node) in self.error_nodes: if id(node) in self.error_nodes:
......
...@@ -531,8 +531,8 @@ def swap_attributes(node: Node, other: Node): ...@@ -531,8 +531,8 @@ def swap_attributes(node: Node, other: Node):
Exchanges the attributes between node and other. This might be Exchanges the attributes between node and other. This might be
needed when rearanging trees. needed when rearanging trees.
""" """
NA = node.attr_active() NA = node.has_attr()
OA = other.attr_active() OA = other.has_attr()
if NA or OA: if NA or OA:
save = node._xml_attr if NA else None save = node._xml_attr if NA else None
if OA: if OA:
...@@ -564,7 +564,7 @@ def _reduce_child(node: Node, child: Node): ...@@ -564,7 +564,7 @@ def _reduce_child(node: Node, child: Node):
""" """
node.result = child.result node.result = child.result
update_attr(child, node) update_attr(child, node)
if child.attr_active(): if child.has_attr():
node._xml_attr = child._xml_attr node._xml_attr = child._xml_attr
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment