summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS.txt3
-rw-r--r--bs4/element.py27
-rw-r--r--bs4/tests/test_tree.py15
3 files changed, 33 insertions, 12 deletions
diff --git a/NEWS.txt b/NEWS.txt
index 461f49d..b91f384 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -17,6 +17,9 @@
* Fixed a bug that caused a crash when you passed a dictionary as an
attribute value (possibly because you mistyped "attrs"). [bug=842419]
+* Fixed a bug that wrecked the tree if you replaced an element with an
+ empty string. [bug=728697]
+
= 4.0.0b4 (20120208) =
* Added BeautifulSoup.new_string() to go along with BeautifulSoup.new_tag()
diff --git a/bs4/element.py b/bs4/element.py
index c053181..474364b 100644
--- a/bs4/element.py
+++ b/bs4/element.py
@@ -51,7 +51,7 @@ class PageElement(object):
self.next_element = None
self.previous_sibling = None
self.next_sibling = None
- if self.parent and self.parent.contents:
+ if self.parent is not None and self.parent.contents:
self.previous_sibling = self.parent.contents[-1]
self.previous_sibling.next_sibling = self
@@ -89,7 +89,7 @@ class PageElement(object):
def extract(self):
"""Destructively rips this element out of the tree."""
- if self.parent:
+ if self.parent is not None:
del self.parent.contents[self.parent.index(self)]
#Find the two elements that would be next to each other if
@@ -98,17 +98,17 @@ class PageElement(object):
last_child = self._last_descendant()
next_element = last_child.next_element
- if self.previous_element:
+ if self.previous_element is not None:
self.previous_element.next_element = next_element
- if next_element:
+ if next_element is not None:
next_element.previous_element = self.previous_element
self.previous_element = None
last_child.next_element = None
self.parent = None
- if self.previous_sibling:
+ if self.previous_sibling is not None:
self.previous_sibling.next_sibling = self.next_sibling
- if self.next_sibling:
+ if self.next_sibling is not None:
self.next_sibling.previous_sibling = self.previous_sibling
self.previous_sibling = self.next_sibling = None
return self
@@ -152,7 +152,7 @@ class PageElement(object):
new_child.previous_sibling = previous_child
new_child.previous_sibling.next_sibling = new_child
new_child.previous_element = previous_child._last_descendant()
- if new_child.previous:
+ if new_child.previous_element is not None:
new_child.previous_element.next_element = new_child
new_childs_last_element = new_child._last_descendant()
@@ -162,23 +162,26 @@ class PageElement(object):
parent = self
parents_next_sibling = None
- while not parents_next_sibling:
+ while parents_next_sibling is None and parent is not None:
parents_next_sibling = parent.next_sibling
parent = parent.parent
- if not parent: # This is the last element in the document.
+ if parents_next_sibling is not None:
+ # We found the element that comes next in the document.
break
- if parents_next_sibling:
+ if parents_next_sibling is not None:
new_childs_last_element.next_element = parents_next_sibling
else:
+ # The last element of this tag is the last element in
+ # the document.
new_childs_last_element.next_element = None
else:
next_child = self.contents[position]
new_child.next_sibling = next_child
- if new_child.next_sibling:
+ if new_child.next_sibling is not None:
new_child.next_sibling.previous_sibling = new_child
new_childs_last_element.next_element = next_child
- if new_childs_last_element.next_element:
+ if new_childs_last_element.next_element is not None:
new_childs_last_element.next_element.previous_element = new_childs_last_element
self.contents.insert(position, new_child)
diff --git a/bs4/tests/test_tree.py b/bs4/tests/test_tree.py
index 6ff87fc..511d907 100644
--- a/bs4/tests/test_tree.py
+++ b/bs4/tests/test_tree.py
@@ -664,6 +664,21 @@ class TestTreeModification(SoupTest):
soup = self.soup(text)
self.assertRaises(ValueError, soup.a.insert, 0, soup.a)
+ def test_replace_with_maintains_next_element_throughout(self):
+ soup = self.soup('<p><a>one</a><b>three</b></p>')
+ a = soup.a
+ b = a.contents[0]
+ # Make it so the <a> tag has two text children.
+ a.insert(1, "two")
+
+ # Now replace each one with the empty string.
+ left, right = a.contents
+ left.replaceWith('')
+ right.replaceWith('')
+
+ # The <b> tag is still connected to the tree.
+ self.assertEqual("three", soup.b.string)
+
def test_replace_final_node(self):
soup = self.soup("<b>Argh!</b>")
soup.find(text="Argh!").replace_with("Hooray!")