Changelog#
The format is based on Keep a Changelog.
[1.1.12] - 2026-05-26#
Fixed#
OMPE-93585:
test_non_terminal_double_star_with_predicate_does_not_bypass_subsequent_tokensnow uses the canonical bracketed wildcard query shapeFrame/**/Button[*].identifier=='target'instead of the unbracketedFrame/**/Button.identifier=='target'. Matches the form 50+ downstreamomni.kit.ui_test.find()callers use and routes the token through_find_children_by_typeas intended — theType.predicate==valueshape (no brackets) goes down a different dispatcher path that does not exercise the class-filtered descendant expansion the regression test is meant to cover. (Jeffrey Qiu review feedback 2026-05-26.)
[1.1.11] - 2026-05-26#
Fixed#
OMPE-93585: Guard widget tree traversal against
Nonechildren.ui.Inspector.get_childrencan legitimately returnnullptrentries for native widgets (notablyui.TreeViewwith a hidden header — seeTreeView::_getChildreninomni.ui). Previouslyfind_widgets/find_first_widgetrecursed into those entries, callingInspector.get_children/hasattr/eval("w."+predicate)onNoneand on partially-destroyed widgets, which crashed the Kit process with SIGSEGV whenomni.kit.ui_test.find()targeted the Script Editor window. All traversal call sites now funnel through a single defensive_safe_get_childrenchokepoint that filters outNoneand converts C++ binding faults into a benign empty list. Predicate evaluation is wrapped in a per-widgettry/exceptso a single bad widget no longer kills the whole query. Theget_widget_path,get_widget_children_with_path, andget_window_widget_pathslayout helpers were also routed through_safe_get_childrenso the same defensive behaviour applies consistently across the codebase. (CodeRabbit feedback id 54571668)_get_descendantswas converted from recursive to iterative form to avoid Python recursion-limit blow-ups on deeply nested widget trees (e.g. Script Editor LogView). The new iterative form pushes children onto the stack withstack.extend(reversed(...))so the leftmost sibling pops first and the historical deterministic left-to-right traversal order is preserved — 50+ downstreamui_test.find()callers acrossomni.kit.menu.utils,omni.kit.property.usd,omni.kit.widget.stage,omni.kit.window.inspector, andomni.kit.widget.searchfieldrely on that order to pick “the first” match. The same reversed-extend treatment is applied in_get_descendants_with_predicate. (CodeRabbit feedback id 54373939)_safe_predicate_filterand the inner_safe_eval_predicate(used by_get_descendants_with_predicate) no longer derive an attribute name withpredicate.split('=')[0]and gate evaluation onhasattr. That gate silently dropped every predicate shape that was not a plainattr=='value'equality —identifier!='x'became"identifier!",width>10had no=at all (so the attribute became the full expression), and method/property expressions such asidentifier.startswith('foo')were always skipped. TUTORIAL.md guarantees that “the predicate can be any valid python expression”, so the gate violated the documented contract. The per-widgettry/exceptalready keeps a bad widget from crashing traversal, so the gate is redundant and has been removed. (review feedback id 54120186)find_widgetnow routes its diagnostic “did find widgets” log through_safe_get_children, soNoneplaceholders emitted by native widgets such asui.TreeViewnever reach the comprehension that readsa.identifier. The attribute access inside the comprehension is additionally wrapped ingetattr/tryso a partially-destroyed native widget that raises during attribute lookup degrades to a placeholder name instead of taking down the diagnostic log site. (review feedback id 54120188)Scoped the
**+ predicate short-circuit in_process_widget_tokensto the case where**is the FINAL widget token. For queries such asFrame/**/Button.identifier=='foo'the**is non-terminal: the trailingButtontoken still has to filter the descendants discovered by**before the final predicate is applied. The previous unconditional short-circuit returned the first descendant whose predicate matched even when the trailing token ruled it out (e.g. a Label withidentifier=='foo'rather than a Button), because the remaining path tokens never ran._get_descendants_with_predicategained anis_finalflag so the helper’s per-widget return only fires when the caller actually wants the predicate-as-final-filter semantics. (CodeRabbit feedback id 54616202)
Added#
_find_children_by_typenow treats the class-name token*as a wildcard and honours a bracketed integer index. Query segments*[*],*[0],*[N]all match the appropriate children regardless of class —*[*]returns every child,*[N]returns the Nth child in declaration order. Previously the dispatcher only routed tokens containing the literal substring[*]to this helper, so*[N]fell through to_child_widgetand silently returnedNone(no class is literally named*). This makes the documented contract from TUTORIAL.md actually hold, and gives the literal bug-trigger pattern from the OMPE-93585 Isaac Sim report (Frame/**/*[*]) — plus the indexed shape — a semantically meaningful match instead of an empty result. (CodeRabbit feedback id 54571676)
Security#
Added a prominent module-level
SECURITY NOTEblock and awarningadmonition on theOmniUIQueryclass docstring making it explicit that the.<predicate>tail of a query string is evaluated with the built-in :func:eval, thatOmniUIQueryis a test helper, and that callers MUST treat predicate strings as trusted in-process test-code input.evalis deliberately kept (rather than swapped for a constrained AST evaluator) because TUTORIAL.md guarantees “the predicate can be any valid python expression” and 50+ downstreamomni.kit.ui_test.find()callers rely on the full expression surface; restricting it would re-introduce the same class of regression the predicate-gate fix already had to undo. (CodeRabbit feedback id 54639054)
[1.1.10] - 2026-02-18#
Changed#
Changed find_menu_item description
[1.1.9] - 2025-11-07#
Fixed#
Make sure the queried window is a ui.Window type instead of ui.WindowHandle in case that it is destroyed
[1.1.8] - 2025-04-30#
Changed#
Updated documentation with AI agent.
[1.1.7] - 2024-11-07#
Changes#
OMPE-22724: Fix ui query get the same path for different widget issue.
[1.1.6] - 2024-10-28#
Changes#
Updated API and all exports
[1.1.5] - 2024-07-18#
Added#
OMPE-15065: Add function get_widget_children_with_path to get all child widgets with path for given widget and path
[1.1.4] - 2024-05-29#
Added#
Fix find_first_widget’s attribute error.
[1.1.3] - 2024-05-20#
Added#
Added function find_first_widget to get the first matched widget for a query.
[1.1.2] - 2024-01-29#
Added#
OM-119448: Added function get_window_widget_paths to get all widget paths of a window.
[1.1.1] - 2022-01-10#
support for widgets under Treeviews (i.e those created by the treeview delegate)
[1.1.0] - 2021-11-09#
(breaking!) Remove add to omni.ui namespace magic as it breaks intellisense
Add support for starting search from a set of root widgets
Fix few query search bugs
[1.0.1] - 2021-10-29#
Added#
When multiple windows with the same name are found, use the 1st visible one.
[1.0.0] - 2021-09-08#
Added#
The initial release