From 1418f32b993ccaf79f31136ddfdf047c209b4321 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Mon, 5 Oct 2026 21:59:11 +0000 Subject: [PATCH] Make select's offset the 0-based position of the first match select() and select_one() documented offset as the number of initial matches to skip, but treated it as the 1-based position of the first match: offset=0 and offset=1 both started at the first match, and offset=2 skipped only one. Skip offset matches, so that offset is the 0-based position of the first match, as documented. Update the examples in the documentation, which relied on the old behavior. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Anders Kaseorg --- docs/docs/querying.md | 4 ++-- python/markupever/iterators.py | 2 +- python/tests/test_dom.py | 11 ++++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/docs/querying.md b/docs/docs/querying.md index a6443e4..c35f8ab 100644 --- a/docs/docs/querying.md +++ b/docs/docs/querying.md @@ -40,10 +40,10 @@ for element in tree.select("[class^=par-]"): # Element(name=QualName(local="p", ns="http://www.w3.org/1999/xhtml", prefix=None), attrs=[(QualName(local="class"), "par-one")], template=false, integration_point=false) # Element(name=QualName(local="p", ns="http://www.w3.org/1999/xhtml", prefix=None), attrs=[(QualName(local="class"), "par-two")], template=false, integration_point=false) -print(tree.select_one("p", offset=3)) +print(tree.select_one("p", offset=2)) # Element(name=QualName(local="p", ns="http://www.w3.org/1999/xhtml", prefix=None), attrs=[(QualName(local="class"), "end-par")], template=false, integration_point=false) -for element in tree.select("[class*=par]", offset=3, limit=1): +for element in tree.select("[class*=par]", offset=2, limit=1): print(element) # Element(name=QualName(local="p", ns="http://www.w3.org/1999/xhtml", prefix=None), attrs=[(QualName(local="class"), "end-par")], template=false, integration_point=false) ``` diff --git a/python/markupever/iterators.py b/python/markupever/iterators.py index 84c6524..b08b5cf 100644 --- a/python/markupever/iterators.py +++ b/python/markupever/iterators.py @@ -108,7 +108,7 @@ def __init__( self.__raw = iter(_rustlib.Select(value._raw, expr)) self.__limit = limit or -1 - self.__offset = offset - 1 + self.__offset = offset def __iter__(self): return self diff --git a/python/tests/test_dom.py b/python/tests/test_dom.py index 7220e41..65f2aca 100644 --- a/python/tests/test_dom.py +++ b/python/tests/test_dom.py @@ -333,7 +333,7 @@ def test_select(): assert count == 1 count = 0 - for tag in dom.select("p", offset=3): + for tag in dom.select("p", offset=2): count += 1 assert isinstance(tag, markupever.dom.Element) assert tag.name == "p" @@ -341,6 +341,15 @@ def test_select(): assert count == 1 + # offset is the 0-based position of the first match. + assert [tag.id for tag in dom.select("p", offset=0)] == ["title", "text", None] + assert [tag.id for tag in dom.select("p", offset=1)] == ["text", None] + assert [tag.id for tag in dom.select("p", offset=1, limit=1)] == ["text"] + assert list(dom.select("p", offset=3)) == [] + assert dom.select_one("p", offset=0).id == "title" + assert dom.select_one("p", offset=1).id == "text" + assert dom.select_one("p", offset=3) is None + tag = dom.select_one("nav.nav2") assert tag.name == "nav" assert tag.class_list == ["nav2"]