Skip to content

refactor phase 1: dead-code deletion + SCC rim cuts (23 → 13 modules) - #296

Merged
hussainsultan merged 7 commits into
mainfrom
refactor/phase1-dead-code-and-scc-rim
Aug 18, 2026
Merged

refactor phase 1: dead-code deletion + SCC rim cuts (23 → 13 modules)#296
hussainsultan merged 7 commits into
mainfrom
refactor/phase1-dead-code-and-scc-rim

Conversation

@hussainsultan

Copy link
Copy Markdown
Collaborator

Phase 1 of the SCC-driven refactor, stacked on #295. Two workstreams: peel the strongly-connected component's periphery with mechanical edge cuts, and delete verified-dead code. The SCC ratchet from #295 enforces every cut. Full suite green (1686 passed; the count dropped from #295's 1707 by exactly the deleted dead-feature tests).

SCC rim cuts — 23 → 13 modules

  • agents (and the package root) detachedagents/tools.py imported from_yaml from the package root instead of .yaml; since the root __init__ lazily imports agents, that single line kept agents.tools, agents.backends.langgraph, and boring_semantic_layer's own __init__ in the knot. One-line fix, 3 modules out.
  • chart cluster detached (6 modules)expr.py imported .chart at module level: core depending on a presentation extra, and the edge closing the cycle expr → chart → chart.utils → ops → (lazy) expr. The .chart() method now resolves the chart package at call time (pandas-.plot style); importing the core no longer loads chart at all (verified).
  • convert detached — see below; deleting its dead handlers also deleted its ops import.
  • flavor helpers consolidated in _xorq.pyget_ibis_module is the repo-wide ibis-flavor router (used by query, utils, ops, server, agents) and had nothing to do with nested-array compilation; it moves to the bottom layer along with _unwrap_table_proxy and null_safe_equal, and the 14-line join_utils.py is folded away. nested_compile re-exports get_ibis_module so the documented import path keeps working.

The residual 13-module SCC is the core knot (ops/expr/query/api/format/graph_utils/projection_utils/utils + serialization/*) — phase 2/3 territory.

Dead-code deletion (~1,100 lines)

  • convert.py 496 → 117 lines — the 11 @convert.register handlers for ibis.expr.sql.convert were a parallel, drifted copy of the real to_untagged lowering with no caller anywhere in src or tests (the module was imported by __init__ solely "to register dispatch handlers"). Only the resolver proxies (_Resolver, _AggResolver, _PrefixProxy) survive.
  • api.py 279 → 124 lines — the nine functional wrappers (join_one, filter_, group_by_, …) were pure pass-throughs to the fluent methods: never exported, never documented, used by exactly one test (rewritten fluent-style). What remains is all public API.
  • legacy lambda-to-string codec deleted (~170 lines in utils.py)expr_to_ibis_string/ibis_string_to_expr and five source-introspection helpers were the pre-v2 serialization path, superseded by the structured resolver-tree codec; only tests of the dead feature referenced them, and those are removed with it.
  • graph_utils 569 → ~190 lines — nine dead exports removed (bfs, replace_nodes — real callers use the _xorq shim — to_node_safe, try_to_node, the find_* family, traverse_roots_with, extract_column_from_dimension) plus their private helpers and tests. is_field/is_table_field stay (used by build_dependency_graph).

Deliberately deferred

The three drifted twin test files (tests/ vs agents/tests/ and chart/tests/ copies of test_semantic_mcp, test_mcp_json_parsing, test_chart) are not deduped here — each pair has diverged, so merging them is a test-by-test job, not a mechanical one. The public graph_bfs family stays exported; demoting it belongs with the API-surface phase's single deprecation batch.

Verification

  • python3 -m pytest src/boring_semantic_layer: 1686 passed, 1 skipped, 11 xfailed, 4 xpassed
  • SCC ratchet: allowlist shrunk 23 → 13 in the same commits as the cuts
  • ruff check / ruff format --check: clean
  • Core import verified not to load chart; every deletion grep-verified caller-free before removal

🤖 Generated with Claude Code

hussainsultan and others added 7 commits August 18, 2026 19:08
get_ibis_module is the repo-wide ibis-flavor router (used by query,
utils, ops, server, agents) and had nothing to do with nested-array
compilation; importing it dragged nested_compile into every consumer.
It now lives in _xorq.py (the bottom layer) together with
_unwrap_table_proxy and null_safe_equal; the 14-line join_utils module
is folded away. nested_compile re-exports get_ibis_module so the
documented import path keeps working.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
agents/tools.py imported from_yaml from the package root instead of
.yaml — the root __init__ lazily imports agents, so that one line made
agents.tools, agents.backends.langgraph, AND boring_semantic_layer's
__init__ mutually reachable with the core knot. SCC: 23 -> 20 modules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
expr.py imported .chart at module level — core depending on a
presentation extra, and the edge that closed the cycle keeping all six
chart modules in the SCC (chart.utils reaches down into ops, which
lazily reaches expr). The .chart() method now resolves the chart
package at call time, pandas-.plot style. Core import no longer loads
chart at all. SCC: 20 -> 14 modules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 11 @convert.register handlers were a parallel, drifted copy of the
real to_untagged lowering with no caller anywhere in src or tests (the
module was imported by __init__ solely 'to register dispatch
handlers'). Only the resolver proxies (_Resolver, _AggResolver,
_PrefixProxy) are used — convert.py shrinks 496 -> 117 lines, loses
its ops import, and leaves the import SCC. SCC: 14 -> 13 modules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
join_one/join_many/join_cross/filter_/group_by_/aggregate_/mutate_/
order_by_/limit_ were pure pass-throughs to the fluent methods — never
exported from __init__, never documented, used by exactly one test
(now rewritten fluent-style). api.py: 279 -> 124 lines; what remains
(to_semantic_table, entity_dimension, time_dimension) is all public.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
expr_to_ibis_string / ibis_string_to_expr and their five source-
introspection helpers (~170 lines in utils.py) were the pre-v2
'expressions as strings' serialization path, superseded by the
structured resolver-tree codec. No production caller remained — only
tests exercising the dead feature, which are removed with it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bfs, replace_nodes (real callers use the _xorq shim), to_node_safe,
try_to_node, find_dimensions_and_measures, find_entity_dimensions,
find_event_timestamp_dimensions, traverse_roots_with,
extract_column_from_dimension and their private helpers had zero
non-test callers. Their tests go with them; is_field/is_table_field
stay (used by build_dependency_graph). graph_utils: 569 -> ~190 lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hussainsultan
hussainsultan force-pushed the refactor/phase1-dead-code-and-scc-rim branch from ce453f5 to dfef20f Compare August 18, 2026 23:15
@hussainsultan
hussainsultan changed the base branch from refactor/phase0-safety-net to main August 18, 2026 23:15
@hussainsultan hussainsultan reopened this Aug 18, 2026
@hussainsultan
hussainsultan merged commit c1aa65d into main Aug 18, 2026
9 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.

1 participant