Skip to content

QueryResult abstraction to help with SGraph Quqery Lang queries#152

Merged
villelaitila merged 4 commits intosoftagram:mainfrom
villelaitila:The_truth_is_rarely_pure_and_never_simple____Oscar_Wilde
Apr 7, 2026
Merged

QueryResult abstraction to help with SGraph Quqery Lang queries#152
villelaitila merged 4 commits intosoftagram:mainfrom
villelaitila:The_truth_is_rarely_pure_and_never_simple____Oscar_Wilde

Conversation

@villelaitila
Copy link
Copy Markdown
Contributor

  • Add exclude_attrs support to ModelCompare and fix set intersection bug
  • Add SGraph Query Language (P1+P2) — architecture-native filtering and dependency queries
  • feat(query): add max_depth parameter to chain search
  • feat(query): return QueryResult with chains from query()

villelaitila and others added 4 commits March 28, 2026 21:46
… dependency queries

Parser: recursive descent with 9-level priority (OR, AND, parens, ---, --->,
-->, --, NOT, attribute filters, keyword/path fallback).

Expressions: 14 AST node types covering element selection, attribute filtering,
direct/transitive dependency search, shortest path, and boolean logic.

Evaluator: ghost-parent view model pattern — result elements preserve correct
paths without copying the full ancestor tree. Supports chain search (DFS, max
depth 20, cycle prevention) and shortest path (undirected BFS).

78 tests covering parser token recognition, precedence, and integration tests
against a realistic multi-module test model with dependency chains.
The chain search operator (--->) had a hardcoded depth cap of 20 hops,
which prevented finding lineage chains deeper than that. Add a max_depth
parameter to query() and evaluate() that plumbs through to the chain
search DFS. Default remains 20 to preserve existing behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The query() function now returns a QueryResult dataclass instead of a
raw SGraph. This bundles two pieces of information that callers
previously had to compute themselves:

  result.subgraph  – the filtered SGraph (same as before)
  result.chains    – tuple of ordered SElement tuples discovered by
                     chain searches (--->)

For non-chain queries (filters, attribute matches), chains is the
empty tuple — always present, never None.

The chain elements are the ORIGINAL model instances (not subgraph
copies), so callers can use ``elem is original`` identity checks and
access full attrs without worrying about parallel object hierarchies.

Internally _eval_chain_search already had the ordered chain in the
DFS recursion (the ``chain`` parameter); it just didn't expose it.
A new optional ``chain_collector`` parameter threads through
evaluate() into the DFS, picking up the path tuple at every match.

The chain_collector is intentionally NOT threaded through NotExpr
branches: chains found inside a NOT are the EXCLUDED set, not the
user-visible result, and surfacing them would mislead.

BREAKING CHANGE: query() now returns QueryResult instead of SGraph.
Callers that previously did ``query(...).rootNode`` must either
- migrate to ``query(...).subgraph.rootNode``, or
- continue calling sgraph.query.evaluator.evaluate() directly, which
  still returns SGraph for use as an internal helper.

The 78 tests in tests/test_query.py adapted by updating only one
shared helper function (``get_all_paths``) to read .subgraph if
present. All 78 tests still pass.
Default Python repr (`<sgraph.sgraph.SGraph object at 0x...>`) is
unhelpful in logs and obscures object identity when the same model
is bound to several variables/dict keys. The new repr shows the
root path, element count, and id, e.g.:

    <SGraph empty elements=0 id=0x10ad>
    <SGraph root=/junit4 elements=42 id=0x10ad>
    <SGraph roots=[a,b,c,...] count=12 elements=10000+ id=0x10bd>

Element count uses an iterative bounded walk
(_REPR_COUNT_LIMIT = 10000), so repr() stays cheap on multi-million
node models — important because debuggers, loggers, and exception
formatters call repr() at arbitrary moments. The body is wrapped
in try/except so a malformed model can never crash a logger.

Also commits the existing untracked tests/mini_model.xml fixture
that the new multi-root tests depend on, and updates the stale
README example.
@softagram-bot
Copy link
Copy Markdown

Softagram Impact Report for pull/152 (head commit: 7240444)

TL;DR Arch. Impact: 105 | Changed code files: 11 | Directly impacted code files: 38

⭐ Change Overview

Showing the changed files, dependency changes and the impact - click for full size
(Open in Softagram Desktop for full details)

⭐ Details of Dependency Changes

details of dependency changes - click for full size
(Open in Softagram Desktop for full details)

[]

📄 Full report

Impact Report explained. Give feedback on this report to support@softagram.com

@villelaitila villelaitila merged commit e66c09b into softagram:main Apr 7, 2026
1 check 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.

2 participants