pyrtan / tests / test_extract.py
2,234 bytes · last changed 2026-10-25 in Initial public release
| 1 | import pytest |
| 2 | |
| 3 | from pyrtan.extract import ExtractError, extract, validate |
| 4 | from pyrtan.template import MISSING |
| 5 | |
| 6 | HTML = '<ul><li class="s"><a href="/a">A</a><span>1</span></li><li class="s"><a href="/b">B</a><span>2</span></li></ul>' |
| 7 | SOURCE = {"status": 200, "body": HTML, "json": {"items": [{"t": "x"}], "price": "$12.50"}} |
| 8 | |
| 9 | |
| 10 | def test_json_path(): |
| 11 | assert extract({"into": "t", "json": "json.items[0].t"}, SOURCE) == "x" |
| 12 | assert extract({"into": "t", "json": "json.items[9].t"}, SOURCE) is MISSING |
| 13 | |
| 14 | |
| 15 | def test_regex(): |
| 16 | assert extract({"into": "p", "regex": r"\$([0-9.]+)", "from": "json.price"}, SOURCE) == "12.50" |
| 17 | assert extract({"into": "p", "regex": r"href=\"(/\w)\"", "all": True}, SOURCE) == ["/a", "/b"] |
| 18 | assert extract({"into": "p", "regex": "zzz"}, SOURCE) is MISSING |
| 19 | assert extract({"into": "p", "regex": "<li", "group": 0}, SOURCE) == "<li" |
| 20 | |
| 21 | |
| 22 | def test_css_text_attr_all_fields(): |
| 23 | assert extract({"into": "x", "css": "li a"}, SOURCE) == "A" |
| 24 | assert extract({"into": "x", "css": "li a", "attr": "href", "all": True}, SOURCE) == ["/a", "/b"] |
| 25 | rows = extract({"into": "x", "css": "li.s", "all": True, "fields": {"name": "a", "n": "span", "href": {"css": "a", "attr": "href"}}}, SOURCE) |
| 26 | assert rows == [{"name": "A", "n": "1", "href": "/a"}, {"name": "B", "n": "2", "href": "/b"}] |
| 27 | assert extract({"into": "x", "css": "h1"}, SOURCE) is MISSING |
| 28 | assert extract({"into": "x", "css": "h1", "all": True}, SOURCE) == [] |
| 29 | |
| 30 | |
| 31 | def test_css_caches_parsed_document(): |
| 32 | cache = {} |
| 33 | extract({"into": "x", "css": "li a"}, SOURCE, cache) |
| 34 | extract({"into": "y", "css": "span"}, SOURCE, cache) |
| 35 | assert len(cache) == 1 |
| 36 | |
| 37 | |
| 38 | def test_validate(): |
| 39 | validate({"into": "a", "json": "x"}) |
| 40 | with pytest.raises(ExtractError): |
| 41 | validate({"into": "a"}) |
| 42 | with pytest.raises(ExtractError): |
| 43 | validate({"into": "a", "json": "x", "css": "y"}) |
| 44 | with pytest.raises(ExtractError): |
| 45 | validate({"into": "a", "regex": "("}) |
| 46 | with pytest.raises(ExtractError): |
| 47 | validate({"into": "a", "css": "a ~ b"}) |
| 48 | with pytest.raises(ExtractError): |
| 49 | validate({"into": "a", "css": "li", "fields": {"x": "a ~ b"}}) |
| 50 | with pytest.raises(ExtractError): |
| 51 | validate({"json": "x"}) |