diff options
-rw-r--r-- | NEWS.txt | 14 | ||||
-rw-r--r-- | bs4/element.py | 57 | ||||
-rw-r--r-- | bs4/tests/test_tree.py | 8 | ||||
-rw-r--r-- | doc/source/index.rst | 5 |
4 files changed, 50 insertions, 34 deletions
@@ -9,6 +9,12 @@ only returns the first match, instead of a list of matches. [bug=1349367] +* You can now create a Tag object without specifying a + TreeBuilder. Patch by Martijn Pieters. [bug=1307471] + +* You can now create a NavigableString or a subclass just by invoking + the constructor. [bug=1294315] + * Started using a standard MIT license. [bug=1294662] * Added a Chinese translation of the documentation by Delong .w. @@ -74,11 +80,9 @@ * Improved the exception raised when you call .unwrap() or .replace_with() on an element that's not attached to a tree. -* You can now create a Tag object without specifying a - TreeBuilder. Patch by Martijn Pieters. [bug=1307471] - -* You can now create a NavigableString or a subclass just by invoking - the constructor. [bug=1294315] +* Raise a NotImplementedError whenever an unsupported CSS pseudoclass + is used in select(). Previously some cases did not result in a + NotImplementedError. = 4.3.2 (20131002) = diff --git a/bs4/element.py b/bs4/element.py index cc21c5c..7c787b1 100644 --- a/bs4/element.py +++ b/bs4/element.py @@ -1336,35 +1336,38 @@ class Tag(PageElement): "A pseudo-class must be prefixed with a tag name.") pseudo_attributes = re.match('([a-zA-Z\d-]+)\(([a-zA-Z\d]+)\)', pseudo) found = [] - if pseudo_attributes is not None: + if pseudo_attributes is None: + pseudo_type = pseudo + pseudo_value = None + else: pseudo_type, pseudo_value = pseudo_attributes.groups() - if pseudo_type == 'nth-of-type': - try: - pseudo_value = int(pseudo_value) - except: - raise NotImplementedError( - 'Only numeric values are currently supported for the nth-of-type pseudo-class.') - if pseudo_value < 1: - raise ValueError( - 'nth-of-type pseudo-class value must be at least 1.') - class Counter(object): - def __init__(self, destination): - self.count = 0 - self.destination = destination - - def nth_child_of_type(self, tag): - self.count += 1 - if self.count == self.destination: - return True - if self.count > self.destination: - # Stop the generator that's sending us - # these things. - raise StopIteration() - return False - checker = Counter(pseudo_value).nth_child_of_type - else: + if pseudo_type == 'nth-of-type': + try: + pseudo_value = int(pseudo_value) + except: raise NotImplementedError( - 'Only the following pseudo-classes are implemented: nth-of-type.') + 'Only numeric values are currently supported for the nth-of-type pseudo-class.') + if pseudo_value < 1: + raise ValueError( + 'nth-of-type pseudo-class value must be at least 1.') + class Counter(object): + def __init__(self, destination): + self.count = 0 + self.destination = destination + + def nth_child_of_type(self, tag): + self.count += 1 + if self.count == self.destination: + return True + if self.count > self.destination: + # Stop the generator that's sending us + # these things. + raise StopIteration() + return False + checker = Counter(pseudo_value).nth_child_of_type + else: + raise NotImplementedError( + 'Only the following pseudo-classes are implemented: nth-of-type.') elif token == '*': # Star selector -- matches everything diff --git a/bs4/tests/test_tree.py b/bs4/tests/test_tree.py index 6ce2a07..7edf848 100644 --- a/bs4/tests/test_tree.py +++ b/bs4/tests/test_tree.py @@ -1828,6 +1828,14 @@ class TestSoupSelector(TreeTest): ('div[data-tag]', ['data1']) ) + def test_unsupported_pseudoclass(self): + self.assertRaises( + NotImplementedError, self.soup.select, "a:no-such-pseudoclass") + + self.assertRaises( + NotImplementedError, self.soup.select, "a:nth-of-type(a)") + + def test_nth_of_type(self): # Try to select first paragraph els = self.soup.select('div#inner p:nth-of-type(1)') diff --git a/doc/source/index.rst b/doc/source/index.rst index ee68d99..f6d3e38 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1138,8 +1138,9 @@ whose ``href`` attribute _does not_ match a regular expression:: # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] -Here's a function that returns ``True`` if a tag is surrounded by -string objects:: +The function can be as complicated as you need it to be. Here's a +function that returns ``True`` if a tag is surrounded by string +objects:: from bs4 import NavigableString def surrounded_by_strings(tag): |