Skip to content

Optimize query_one#5948

Merged
willmcgugan merged 6 commits into
mainfrom
query-one-optimize
Jul 10, 2025
Merged

Optimize query_one#5948
willmcgugan merged 6 commits into
mainfrom
query-one-optimize

Conversation

@willmcgugan

Copy link
Copy Markdown
Member

A special case optimization for query_one with a simple id selector.

Previously widget.query_one("#foo") would search each node in turn until it found a matching ID. In most cases this is quick enough, but here are potential pathological cases where it could be slow.

This update uses the index on the node list to make this much faster.

@willmcgugan

Copy link
Copy Markdown
Member Author

@TomJGooding Want to take a gander?

@willmcgugan willmcgugan requested a review from Copilot July 10, 2025 13:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a special-case optimization for query_one when using a simple ID selector, routing those lookups through an indexed BFS lookup instead of a full selector parse.

  • Add is_id_selector helper (with caching) in the CSS parser.
  • Implement walk_breadth_search_id in the DOM walker for fast ID-based lookups.
  • Integrate the new search path into query_one and update imports.
  • Add unit tests for the new is_id_selector function.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
tests/css/test_parse.py Import is_id_selector and add parametrized tests for ID selectors
src/textual/walk.py Add walk_breadth_search_id for efficient BFS ID search
src/textual/dom.py Hook ID-search path into query_one and update related imports
src/textual/css/parse.py Define is_id_selector (regex + LRU cache) and adjust imports
Comments suppressed due to low confidence (4)

tests/css/test_parse.py:1278

  • [nitpick] Consider adding test cases for ID selectors including hyphens or underscores (e.g. '#foo-bar', '#foo_bar') and uppercase letters to ensure full coverage of valid IDENTIFIER patterns.
    "selector, expected",

src/textual/walk.py:142

  • [nitpick] The function name 'walk_breadth_search_id' is somewhat verbose; consider renaming to something more concise like 'find_by_id_bfs' to improve clarity.
def walk_breadth_search_id(

src/textual/walk.py:147

  • In the docstring, correct the comparative 'that' to 'than': 'more efficient than ...' for grammatical accuracy.
    This is more efficient that [walk_breadth_first][textual.walk.walk_breadth_first] for this special case, as it can use an index.

src/textual/css/parse.py:43

  • [nitpick] The escape of '#' in a raw string (r"\#") is unnecessary; it can be simplified to r"#" to improve readability.
RE_ID_SELECTOR = re.compile(r"\#" + IDENTIFIER)

@willmcgugan willmcgugan merged commit e5f5fb9 into main Jul 10, 2025
21 checks passed
@willmcgugan willmcgugan deleted the query-one-optimize branch July 10, 2025 14:03
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.

2 participants