Skip to content

De-duplicate update_checker: drop the stale copy in src/jabs/utils, keep the jabs-core one - #426

Merged
gbeane merged 1 commit into
mainfrom
claude/quality-2026-08-06
Aug 6, 2026
Merged

De-duplicate update_checker: drop the stale copy in src/jabs/utils, keep the jabs-core one#426
gbeane merged 1 commit into
mainfrom
claude/quality-2026-08-06

Conversation

@gbeane

@gbeane gbeane commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Reasoning

src/jabs/utils/update_checker.py and packages/jabs-core/src/jabs/core/utils/update_checker.py were the same file twice. The only difference in the whole module was how the version string was obtained:

-from jabs.version import version_str
+from jabs.core.utils.version import version_str
...
-        current_version = version_str()
+        current_version = version_str("jabs-behavior-classifier")

Those two calls are equivalent — jabs.version.version_str() is itself a one-line shim that calls jabs.core.utils.version.version_str("jabs-behavior-classifier"). Every other line of the two modules was identical.

So the jabs-core migration for this module had already happened (it's implemented there, exported from jabs.core.utils.__init__, and reachable as jabs.core.utils.check_for_update), but the old root copy was left in place — and the root copy is the one the GUI was actually importing, via from jabs.utils import check_for_update in menu_handlers.py and from jabs.utils import is_pypi_install in update_check_dialog.py. Two live implementations of PyPI-update-checking, only one of which was reachable from the app, and only one of which was covered by tests (the root one — packages/jabs-core/tests/ had no test for its own copy).

I picked this over the other candidates I looked at because it is the highest-confidence, lowest-risk item on the list: it is the monorepo-transition cleanup described in the development guide, the destination file already exists so nothing is being moved, and there is no circular-dependency risk (the root package already depends on jabs-core==0.46.2; jabs-core imports nothing from the root tree). Other candidates I considered and skipped as either riskier or lower value: VideoLabels.counts() in src/jabs/project/video_labels.py is dead code that would raise AttributeError if called (TrackLabels has no counts attribute), and Project.load_counts() has a return annotation of dict[str, tuple[int, int]] where it actually returns dict[int, dict[str, tuple[int, int]]]. Both are real, but removing a public method and correcting a public signature are judgement calls that deserve their own PRs rather than being bundled here.

Why this is safe (net-zero behavior change):

  • jabs.utils.check_for_update and jabs.utils.is_pypi_install still resolve — now to the jabs-core functions. Verified: check_for_update is jabs.core.utils.update_checker.check_for_updateTrue. The two GUI call sites are untouched and need no change.
  • jabs.utils.FINAL_TRAIN_SEED and __all__ are unchanged.
  • The surviving implementation is behaviorally identical to the deleted one, per the diff above.
  • The 20 tests that covered the deleted copy now cover the surviving one, and they pass unmodified apart from their patch targets.

One thing worth flagging for the reviewer: the module path jabs.utils.update_checker no longer exists (only the jabs.utils package-level names do). Nothing in src/, tests/, packages/, docs/, or dev/ imported that path apart from the test file this PR moves — I grepped — but it is technically a narrowing of an internal import surface.

Change

Logic changes

  • src/jabs/utils/update_checker.py — deleted. Duplicate of the jabs-core module.
  • src/jabs/utils/__init__.py — imports check_for_update / is_pypi_install from jabs.core.utils instead of the now-deleted local module. Module docstring notes that these are re-exports, so the next reader doesn't re-add a local copy.
  • packages/jabs-core/src/jabs/core/utils/update_checker.py — the two log calls switched from f-strings to lazy %s formatting (logger.warning("Failed to check for updates: %s", e)), per the logging conventions in CLAUDE.md. Message text is unchanged; both copies had this issue and it seemed worth fixing on the one that survives.

Mechanical updates

(no logic change — safe to skim)

  • tests/utils/test_update_checker.pypackages/jabs-core/tests/test_update_checker.py — the file moves so the surviving implementation is covered by the suite CI runs for that package (_run-tests-action.yml runs each packages/*/tests directory separately). The only content edits are a sed-style retarget of jabs.utils.update_checkerjabs.core.utils.update_checker in the import and in the 10 patch(...) targets, plus the module docstring. No test logic, assertions, or fixtures changed.

Verification

uv run ruff check .                     # All checks passed!
uv run ruff format .                    # 429 files left unchanged
uv run pytest                           # 735 passed, 123 skipped
uv run pytest packages/jabs-core/tests  # 88 passed (includes the 20 moved tests)

No FEATURE_VERSION bump: nothing here touches feature computation or the cache format.


This PR was produced by an automated analysis from Claude Code.


Generated by Claude Code

src/jabs/utils/update_checker.py was a byte-for-byte duplicate of
packages/jabs-core/src/jabs/core/utils/update_checker.py apart from how it
resolved the version string (jabs.version.version_str() vs.
version_str("jabs-behavior-classifier"), which are equivalent). The jabs-core
copy is the one exported by jabs.core.utils, but the GUI was still importing
the stale root copy via jabs.utils.

Delete the root copy and re-export the two helpers from jabs-core in
src/jabs/utils/__init__.py, so jabs.utils.check_for_update and
jabs.utils.is_pypi_install (used by menu_handlers and update_check_dialog)
keep working unchanged.

Move tests/utils/test_update_checker.py to packages/jabs-core/tests/ and
retarget its patch paths, so the surviving implementation stays covered by
the jabs-core suite that CI runs.

Also switch the two log calls in the surviving module to lazy %s formatting,
per the logging conventions in CLAUDE.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MhEg7sSojc4dxBh7FbtZjW
@gbeane gbeane self-assigned this Aug 6, 2026
@gbeane
gbeane requested a lite review from Copilot August 6, 2026 13:48

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 removes the duplicate update_checker implementation from the root src/jabs/utils tree and standardizes the application on the jabs-core implementation, aligning with the monorepo migration direction while preserving the existing GUI import surface (from jabs.utils import ...).

Changes:

  • Deleted the stale duplicate src/jabs/utils/update_checker.py and kept packages/jabs-core/.../update_checker.py as the single implementation.
  • Updated src/jabs/utils/__init__.py to re-export check_for_update / is_pypi_install from jabs.core.utils to maintain backward-compatible imports for the GUI.
  • Moved the update-checker unit tests under packages/jabs-core/tests/ and updated patch/import targets accordingly; adjusted logging calls in the surviving implementation to use lazy %s formatting.

Reviewed changes

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

File Description
src/jabs/utils/update_checker.py Removed duplicate PyPI update-checker module from the root package.
src/jabs/utils/init.py Re-export update-check helpers from jabs-core to keep jabs.utils imports stable.
packages/jabs-core/src/jabs/core/utils/update_checker.py Kept the canonical implementation; updated log formatting to lazy %s.
packages/jabs-core/tests/test_update_checker.py Relocated tests to cover the jabs-core implementation and retargeted patches/imports.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gbeane
gbeane merged commit 7f28551 into main Aug 6, 2026
7 checks passed
@gbeane
gbeane deleted the claude/quality-2026-08-06 branch August 6, 2026 15:46
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.

3 participants