Skip to content

Keep namespace wildcards in canonical() of combined selectors and :is() - #204

Merged
wRAR merged 2 commits into
scrapy:masterfrom
itecz26:canonical-namespace-wildcard
Oct 19, 2026
Merged

wRAR merged 2 commits into
scrapy:masterfrom
itecz26:canonical-namespace-wildcard

Conversation

@itecz26

@itecz26 itecz26 commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

canonical() of a combined selector, :is() and :where() strips a leading * from its argument with lstrip("*"), which also eats the * of a *| namespace wildcard: parse('foo *|bar')[0].canonical() returns foo |bar, so "any namespace" turns into "no namespace" and re-parsing it translates to descendant::bar instead of descendant::*[local-name() = 'bar'], matching different elements. Selector.canonical() and Negation.canonical() already only strip a * followed by #, ., [ or :; this uses the same check at the three lstrip sites, with round-trip cases added to test_css_export.

CombinedSelector, Matching and SpecificityAdjustment dropped a redundant
universal selector from their subselector with lstrip("*"), which also
stripped the "*" of a "*|" namespace wildcard: "foo *|bar" became
"foo |bar", turning "any namespace" into "no namespace". Only strip a
"*" followed by "#", ".", "[" or ":", as Selector and Negation do.
@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.79%. Comparing base (ec61e4b) to head (ba2a704).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #204   +/-   ##
=======================================
  Coverage   99.79%   99.79%           
=======================================
  Files           3        3           
  Lines         987      987           
  Branches      162      162           
=======================================
  Hits          985      985           
  Misses          1        1           
  Partials        1        1           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@wRAR

wRAR commented Oct 16, 2026

Copy link
Copy Markdown
Member

Can you please look into missing coverage?

@itecz26

itecz26 commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

the missed line was the strip in CombinedSelector.canonical(): before, lstrip("*") ran on any subselector longer than one char, so it was always covered as a no-op, but nothing tested an actual *.foo after a combinator. added foo *.bar and foo > *[bar] cases, which cover it, and patch coverage is back to master's level (the remaining miss at parser.py:1065 is pre-existing).

@wRAR
wRAR merged commit 16b4c40 into scrapy:master Oct 19, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants