summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonard Richardson <leonardr@segfault.org>2015-06-28 07:42:38 -0400
committerLeonard Richardson <leonardr@segfault.org>2015-06-28 07:42:38 -0400
commit83d8623191dddac3ebb1dd4f3aeff1f3e5a8c912 (patch)
treeff116351e82cce604e1a56e6b3f7a395a402a634
parentab7fa80de890e03919741a61b828305d941c6ab0 (diff)
downloadbeautifulsoup4-83d8623191dddac3ebb1dd4f3aeff1f3e5a8c912.tar.gz
Raise a NotImplementedError whenever an unsupported CSS pseudoclass
is used in select(). Previously some cases did not result in a NotImplementedError.
-rw-r--r--NEWS.txt14
-rw-r--r--bs4/element.py57
-rw-r--r--bs4/tests/test_tree.py8
-rw-r--r--doc/source/index.rst5
4 files changed, 50 insertions, 34 deletions
diff --git a/NEWS.txt b/NEWS.txt
index bcd4223..9126ddf 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -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):