Skip to content

refactor: move require_int/require_float to hflow._field_guards - #464

Open
7487 wants to merge 1 commit into
Hebbian-Robotics:mainfrom
7487:field-guards-463
Open

refactor: move require_int/require_float to hflow._field_guards#464
7487 wants to merge 1 commit into
Hebbian-Robotics:mainfrom
7487:field-guards-463

Conversation

@7487

@7487 7487 commented Sep 8, 2026

Copy link
Copy Markdown

Summary

require_int / require_float now have one definition, src/hflow/_field_guards.py, imported by _frame_statistics.py, _camera_motion.py and testing.py. The byte-identical private copy in testing.py is gone. Same exception types, same message strings, same public names. No behavior change; the other ~50 inline isinstance sites are untouched, per the issue.

Fixes #463

Why

The move is what the issue asks for. One thing did not go as the issue's definition of done predicted, and it is worth being explicit about:

One test edit was required. tests/test_module_boundaries.py enforces two import contracts that any single-definition layout has to cross:

  • _video_measurements/* may import nothing from hflow.* (empty allowlist), and
  • hflow.testing may import only hflow.ffmpeg and hflow.format.

With the layout from the issue and no test change, the guard fails with exactly the three imports this PR adds:

hflow/_video_measurements/_camera_motion.py:10: from hflow._field_guards import require_float -- the video-measurements package must not import hflow or any hflow.* module because it is designed to be extracted into a standalone package
hflow/_video_measurements/_frame_statistics.py:17: from hflow._field_guards import require_float, require_int -- ...
hflow/testing.py:49: from hflow._field_guards import require_float, require_int -- hflow.testing may import only hflow.ffmpeg and hflow.format; ...

The AST guard skips relative imports, so from .._field_guards import ... inside _video_measurements would have passed it silently. I did not do that: it is the same dependency, just hidden from the test. Instead both boundaries allowlist hflow._field_guards by name, with the rule text updated to say so. _field_guards has no imports of its own, so extracting _video_measurements later means vendoring 14 lines. I mutation-checked that a from hflow.storage import ... inside _camera_motion.py is still red under the new rule.

If you would rather keep the _video_measurements allowlist empty, the alternative is to leave _field_guards.py where it was and have testing.py import it from there (only the hflow.testing allowlist changes). Happy to flip; it is a one-line direction change.

Also removed the testing.py module-docstring bullet that explained why the copy existed, since it no longer does.

Validation

uv sync --locked
uv run ruff check                 # All checks passed!
uv run ruff format --check        # 227 files already formatted
uv run ty check                   # All checks passed!
uv run pytest -q                  # 1609 passed, 9 skipped, 27 failed (see note)

Ran on macOS (CI is Linux-only). The 27 failures are all tests/test_packaging*.py raising CythonOverlayBuildError: native overlay builds currently require CPython on Linux; found cpython on darwin; the identical 27 fail on pristine upstream/main (7df224a) in the same environment, so they are platform-only and CI covers them.

Additional checks:

  • uv run pytest -q tests/test_module_boundaries.py with the source change and the unmodified test: 1 failed with the three violations quoted above, then 2 passed with the allowlist.
  • Mutation: appended from hflow.storage import _load_obstore to _camera_motion.py, guard went red naming that line; restored, green.
  • tests/test_testing.py, tests/test_video_measurement_settings_types.py, tests/test_video_measurement_settings_ranges.py: 103 passed, unmodified. These already pin every must be an int[, got ...] / must be an int or float, got ... message through the public constructors, which is why no new test is added for a pure move.
  • git diff --check clean.

Checklist

  • I added or updated outcome-focused tests for changed business logic. -- no business logic changed; existing outcome tests cover both consumers and pass unmodified. The only test edit is the boundary allowlist described above.
  • I updated documentation for changed behavior, flags, formats, or requirements. -- no user-facing behavior changed; docs do not reference _field_guards.
  • I ran uv run ruff check --fix, uv run ruff format, and uv run ty check.
  • I ran the relevant pytest suite.
  • I did not add recordings, generated media, credentials, private URLs, or runtime artifacts.
  • I preserved stored-data compatibility or documented an explicit version change.

🤖 Generated with Claude Code

testing.py carried a byte-identical copy of the two type guards that
_video_measurements/_field_guards.py already defined. Move the module to
the package root, point _frame_statistics, _camera_motion and testing at
it, and delete the copy. Same functions, same exception types and message
strings; no behavior change.

tests/test_module_boundaries.py allowlists hflow._field_guards for the two
boundaries the shared import now crosses (the video-measurements package
and hflow.testing) and keeps every other hflow.* import red.

Fixes Hebbian-Robotics#463

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

👋 Hi @7487 — thank you so much for your first contribution to HFlow!

A maintainer will review your pull request as soon as possible. In the meantime:

💡 Tip: one open pull request per contributor at a time. Issues with an assignee are taken; everything else is fair game.

We are excited to have you here and appreciate your help making the project better! 🙌

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.

testing.py carries a byte-identical copy of _field_guards.require_int/require_float

1 participant