1
1
mirror of https://git.launchpad.net/beautifulsoup synced 2025-10-05 16:02:46 +02:00

* Making ResultSet inherit from MutableSequence still resulted in too many

breaking changes in users of the library, so I reverted the
  ResultSet code back to where it was in 4.13.5 and added tests of all known
  breaking behavior. [bug=2125906]
This commit is contained in:
Leonard Richardson
2025-09-29 05:57:41 -04:00
parent 9798e1a448
commit c400f4b986
3 changed files with 19 additions and 30 deletions

View File

@@ -1,3 +1,10 @@
= 4.14.2 (20250929)
* Making ResultSet inherit from MutableSequence still resulted in too many
breaking changes in users of the library, so I reverted the
ResultSet code back to where it was in 4.13.5 and added tests of all known
breaking behavior. [bug=2125906]
= 4.14.1 (20250929)
* Made ResultSet inherit from MutableSequence instead of Sequence,

View File

@@ -3184,50 +3184,26 @@ class Tag(PageElement):
_PageElementT = TypeVar("_PageElementT", bound=PageElement)
class ResultSet(MutableSequence[_PageElementT], Generic[_PageElementT]):
"""A ResultSet is a sequence of `PageElement` objects, gathered as the result
class ResultSet(List[_PageElementT], Generic[_PageElementT]):
"""A ResultSet is a list of `PageElement` objects, gathered as the result
of matching an :py:class:`ElementFilter` against a parse tree. Basically, a list of
search results.
"""
source: Optional[ElementFilter]
result: MutableSequence[_PageElementT]
def __init__(
self, source: Optional[ElementFilter], result: MutableSequence[_PageElementT] = []
self, source: Optional[ElementFilter], result: Iterable[_PageElementT] = ()
) -> None:
self.result = result or []
super(ResultSet, self).__init__(result)
self.source = source
def insert(self, index, value):
return self.result.insert(index, value)
def __len__(self) -> int:
return len(self.result)
def __getitem__(self, index):
return self.result[index]
def __delitem__(self, key):
return self.result.__delitem__(key)
def __setitem__(self, key, value):
return self.result.__setitem__(key, value)
def __getattr__(self, key: str) -> None:
"""Raise a helpful exception to explain a common code fix."""
raise AttributeError(
f"""ResultSet object has no attribute "{key}". You're probably treating a sequence of elements like a single element. Did you call find_all() when you meant to call find()?"""
f"""ResultSet object has no attribute "{key}". You're probably treating a list of elements like a single element. Did you call find_all() when you meant to call find()?"""
)
def __eq__(self, other: Any) -> bool:
"""A ResultSet is equal to a list if its results are equal to that list.
A ResultSet is equal to another ResultSet if their results are equal,
even if the results come from different sources.
"""
return bool(self.result == other)
# Now that all the classes used by SoupStrainer have been defined,
# import SoupStrainer itself into this module to preserve the
# backwards compatibility of anyone who imports

View File

@@ -134,7 +134,7 @@ class TestResultSet:
with pytest.raises(AttributeError) as e:
rs.name
assert (
"""ResultSet object has no attribute "name". You're probably treating a sequence of elements like a single element. Did you call find_all() when you meant to call find()?"""
"""ResultSet object has no attribute "name". You're probably treating a list of elements like a single element. Did you call find_all() when you meant to call find()?"""
== str(e.value)
)
@@ -170,3 +170,9 @@ class TestResultSet:
rs = ResultSet(None, [1,2,3])
rs[1] = 4
assert rs == [1,4,3]
def test_add_resultsets_together(self):
# ResultSets can be added together like lists. (pandas depends on this.)
rs1 = ResultSet(None, [1,2,3])
rs2 = ResultSet(None, [4,5,6])
assert rs1 + rs2 == [1,2,3,4,5,6]