Skip to content

Commit 1fd1013

Browse files
authored
fix: prevent IndexError in adaptive relocation when auto_save is enabled (#340)
2 parents 9c0c857 + 3d96baf commit 1fd1013

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

scrapling/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ def xpath(
671671
element_data = self.retrieve(identifier or selector)
672672
if element_data:
673673
elements = self.relocate(element_data, percentage)
674-
if elements is not None and auto_save:
674+
if elements and auto_save:
675675
self.save(elements[0], identifier or selector)
676676

677677
return self.__handle_elements(elements)

tests/parser/test_adaptive.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,32 @@ def test_element_relocation(self):
5656
assert relocated[0].has_class("new-class")
5757
assert relocated[0].css(".new-description")[0].text == "Description 1"
5858

59+
def test_relocation_auto_save_no_match_above_threshold(self):
60+
"""Adaptive relocation with `auto_save=True` must not crash when no element
61+
clears the `percentage` threshold (relocate() returns an empty list)."""
62+
original_html = """
63+
<div class="container">
64+
<article class="product" id="target">
65+
<h3>Widget</h3>
66+
<p class="desc">A widget</p>
67+
</article>
68+
</div>
69+
"""
70+
# Unrelated structure so nothing can match a high threshold
71+
changed_html = "<html><body><span>totally unrelated content</span></body></html>"
72+
73+
old_page = Selector(original_html, url="example.com", adaptive=True)
74+
new_page = Selector(changed_html, url="example.com", adaptive=True)
75+
76+
old_page.css("#target", identifier="target", auto_save=True)
77+
78+
# Before the fix this raised `IndexError: list index out of range` because the
79+
# guard checked `elements is not None` but relocate() returns [] (never None).
80+
result = new_page.css(
81+
"#target", identifier="target", adaptive=True, auto_save=True, percentage=95
82+
)
83+
assert list(result) == []
84+
5985
@pytest.mark.asyncio
6086
async def test_element_relocation_async(self):
6187
"""Test relocating element after structure change in async mode"""

0 commit comments

Comments
 (0)