Skip to content

chore(deps): bump xorq>=0.3.24 and adapt tests to API changes#265

Closed
ghoersti wants to merge 2 commits into
boringdata:mainfrom
ghoersti:george/update/xorq-0.3.24
Closed

chore(deps): bump xorq>=0.3.24 and adapt tests to API changes#265
ghoersti wants to merge 2 commits into
boringdata:mainfrom
ghoersti:george/update/xorq-0.3.24

Conversation

@ghoersti
Copy link
Copy Markdown
Contributor

Summary

Stacked on top of #264 — please merge that first. Bumps xorq from >=0.3.19 to >=0.3.24 and adapts BSL's xorq integration + tests to the four API changes the bump surfaces.

Between the previously-pinned 0.3.19 and 0.3.24, xorq:

  • get_rebuild_dispatch — the returned callable now takes (rebuild_subexpr, remap, to_catalog) instead of just (rebuild_subexpr).
  • Frozen tag ops — tag-op classes are frozen and declare parent: Relation, so parent=None is no longer constructible and .parent cannot be reassigned after construction.
  • xorq.api.read_parquet removed — callers use deferred_read_parquet.
  • Vendored-ibis literal inference tightened — scalars built via the foreign top-level ibis package are rejected inside a xorq.vendor.ibis expression.

Changes

  • pyproject.toml: xorq>=0.3.19xorq>=0.3.24.
  • test_xorq_backends.py: xo.read_parquetxo.deferred_read_parquet.
  • test_xorq_rebuild.py: pass (rebuild_subexpr, None, None) to dispatch; replace ibis.literal(1) inside a reemit callback with a raw Python scalar so mutate infers in the parent's flavor.
  • serialization/tag_handler.reemit: drop the if tag_node.parent is None guard. xorq now declares parent as a non-null Relation, so the precondition is structurally impossible. Drop the matching test_reemit_raises_on_missing_parent test.

Test plan

  • pytest src/boring_semantic_layer/tests/ → 1003 passed, 1 skipped, 10 xfailed, 5 xpassed on xorq 0.3.24.
  • pytest test_xorq_tag_handler.py test_xorq_rebuild.py test_xorq_convert.py test_xorq_backends.py → 56 passed.

Related

🤖 Generated with Claude Code

ghoersti and others added 2 commits May 19, 2026 00:12
…tent hash

Closes boringdata#263

Both `to_tagged()` and `reemit()` previously wrapped BSL expressions in
a plain Tag node, which xorq's `opaque_node_replacer` strips during
content-hash computation. The result: `source` and
`source.tag("bsl", **metadata)` produced identical hashes, so two
`xorq build` invocations (one for the raw source, one for a BSL model
over it) silently overwrote each other under `builds/<hash>/`. The
same regression applied to rebuilt artifacts coming out of `reemit`.

Switch both call sites to `Table.hashing_tag(...)` so BSL metadata
participates in the hash. HashingTag is a Tag subclass, so existing
`isinstance(op, Tag)` checks in the reconstruct path are unaffected.

Tests:
  - Drop `@pytest.mark.xfail` from the pre-existing
    `test_different_measures_produce_different_hashes` in
    test_xorq_convert.py — that test was xfailed against the bug and
    now passes (uses xorq's authoritative `compute_expr_hash`).
  - Add two new tests in test_xorq_tag_handler.py:
      * test_tagged_op_is_hashing_tag — outer op type is HashingTag.
      * test_tagged_hash_differs_from_untagged_source — tagged hash
        differs from bare source (covers untagged-vs-tagged, no
        pre-existing duplicate).
  - Add two new reemit regression tests:
      * test_reemit_preserves_hashing_tag — pin that `reemit` re-stamps
        with HashingTag, so rebuild paths keep the hash contract.
      * test_reemit_hash_distinguishes_metadata — round-trip via
        `to_tagged → reemit` still produces distinct hashes for distinct
        metadata.

All new tests use `compute_expr_hash` (xorq's content-hash function)
rather than `dask.base.tokenize` for consistency with the existing
tests in test_xorq_convert.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Between the previously-pinned 0.3.19 and the new 0.3.24, xorq:
  - changed the dispatch returned by ``get_rebuild_dispatch`` to take
    ``(rebuild_subexpr, remap, to_catalog)`` instead of just
    ``(rebuild_subexpr)``.
  - made tag-op classes frozen with ``parent: Relation``, so
    ``parent=None`` is no longer constructible (and ``.parent`` cannot
    be mutated after construction).
  - removed ``xorq.api.read_parquet``; callers use
    ``deferred_read_parquet``.
  - tightened ``xorq.vendor.ibis`` literal inference: scalars
    constructed via the foreign top-level ``ibis`` package are
    rejected inside a vendored expression.

Adaptations:
  - test_xorq_backends: rename xo.read_parquet -> xo.deferred_read_parquet.
  - test_xorq_rebuild: pass ``(rebuild_subexpr, None, None)`` to the
    dispatch callable, and replace ``ibis.literal(1)`` inside a reemit
    callback with a raw Python scalar so ``mutate`` infers in the
    parent's flavor.
  - serialization/tag_handler.reemit: drop the ``if tag_node.parent is
    None`` guard. xorq now declares ``parent`` as a non-null
    ``Relation``, so the precondition is structurally impossible. Drop
    the matching ``test_reemit_raises_on_missing_parent`` test (it
    could only fire by mutating a real tag node into an invalid shape,
    which xorq's immutability now rejects).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ghoersti ghoersti force-pushed the george/update/xorq-0.3.24 branch from e1630d1 to 7d32ddd Compare May 19, 2026 05:20
@ghoersti ghoersti closed this May 19, 2026
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