Skip to content

v1.2.0

Choose a tag to compare

@praneethnamburi praneethnamburi released this 17 May 01:17
· 88 commits to master since this release

[1.2.0] - 2026-05-16

Audit-and-polish release. No public API changes.

Added

  • utils.find_nearest and siblings (find_nearest_idx,
    find_nearest_val, find_nearest_idx_val), surfaced via the
    package's utils module. Cash-out from the pntools retirement
    pass; previously unreleased on master since 4cdbe64.
  • GitHub Actions CI: pytest matrix across Python 3.10–3.12 and
    {ubuntu-22.04, macos-latest, windows-latest}. Ubuntu is the
    authoritative runner; macOS / Windows are continue-on-error for
    this release while the numpy<2 pin keeps decord / tables
    wheel availability flaky on those platforms. ffmpeg is installed
    via OS-conditional steps (apt, brew, choco) so the workflow
    works on Apple Silicon macos-latest.
  • __all__ on datanavigator/__init__.py. from datanavigator import * now exposes 39 documented names (down from 53 — dropped
    the stdlib leaks os / sys / shutil and the 11 submodule
    attributes). Submodule access via datanavigator.utils.X or
    from datanavigator import utils is unchanged.
  • TODO.md seeded with deferred-to-1.3.0 items, nice-to-have polish,
    and stretch goals.
  • [project.optional-dependencies] dev = ["pytest"] in
    pyproject.toml, plus pytest in requirements.yml (previously
    the test suite was unrunnable as-shipped — no env in the repo
    could run it).
  • New regression tests in tests/test_pointtracking.py:
    test_video_annotation_to_dlc_populates_values (synthetic) and
    test_video_annotation_to_dlc_real_data_roundtrip (skipif-gated
    against the OPR02 DLC fixture on the S: drive). Pin the
    chained-assignment fix above.

Changed

  • Cross-platform default paths. On macOS / Linux,
    datanavigator._config.CLIP_FOLDER and CACHE_FOLDER now default
    to ~/datanavigator/_clipcollection and ~/datanavigator/_cache.
    Windows defaults are unchanged (C:\\data\\_clipcollection,
    C:\\data\\_cache). CLIP_FOLDER / CACHE_FOLDER environment
    variable overrides are unchanged.
  • Python floor raised to 3.10 (3.7–3.9 are EOL since 2023-06).
  • DeepLabCut HDF5 paths in VideoAnnotation (load, _load_dlc,
    _dlc_df_to_annotation_dict, _dlc_trace_to_annotation_dict,
    to_dlc) are now docstring-tagged DUSTrack-shaped so the
    upcoming 1.3.0 migration to dustrack.VideoAnnotation has a
    greppable anchor.
  • Module-level docstring added to pointtracking.py.
  • Opportunistic PEP 604 / PEP 585 type-hint modernization in the
    files this audit was already touching: events.py,
    pointtracking.py, components.py, plots.py (Optional[X]
    X | None, Union[A, B]A | B, List / Tuple / Dict
    list / tuple / dict). The remaining modules retain legacy
    typing imports; a portfolio-wide sweep is deferred to 1.3.0.
  • pyproject.toml: added [tool.black], [tool.isort], and
    [tool.pytest.ini_options] blocks so contributors don't need to
    reconstruct the conventions from CONVENTIONS.md.

Fixed

  • VideoBrowser.extract_clip and VideoPlotBrowser.extract_clip now
    fall back to libx264 when h264_nvenc (NVIDIA hardware encoder)
    is unavailable. Previously hardcoded; failed with
    Unknown encoder 'h264_nvenc' or Cannot load nvcuda.dll on
    CPU-only hosts, CI runners, and macOS / Apple Silicon.
  • is_pathname_valid now catches ValueError (which Python 3.5+
    raises for "embedded null character" in os.lstat) in addition
    to the stale TypeError catch. The function now returns False
    for NUL-bearing paths on modern Python instead of leaking the
    exception.
  • tests/test_utils.py path-validity assertions are now
    platform-aware: Windows tests with < (a reserved char on
    Windows), POSIX tests with an embedded NUL byte. The old test
    failed on Linux because POSIX accepts < in path components.
  • VideoPlotBrowser setup no longer crashes on matplotlib ≥ 3.8:
    Grouper.join was removed in 3.8, replaced by Axes.sharex().
    This was a latent bug surfaced by the 1.2.0 audit's fresh-env
    test run (matplotlib 3.10.9). test_video_plot_browser_init
    passes again.
  • VideoPlotBrowser.onclick right-click-to-seek now works on
    Python ≥ 3.11. The check compared str(event.button) to the
    literal "MouseButton.RIGHT", which silently broke when
    Python 3.11 changed IntEnum.__str__ to return the integer
    value — str(MouseButton.RIGHT) is now "3". Replaced with an
    enum comparison (event.button == MouseButton.RIGHT). The
    failure had been mis-triaged in the 1.2.0 audit as a headless-
    Agg dispatch quirk; it was a runtime defect for every user on
    Python ≥ 3.11, not test-only. Confirmed by running
    test_video_plot_browser_init on Python 3.12 + matplotlib 3.10.7.
  • VideoAnnotation.to_dlc no longer uses pandas chained assignment
    (df.loc[row][col] = val), which pandas emits a FutureWarning
    on every call and which will silently no-op once Copy-on-Write
    becomes the default in pandas 3.0. Validated byte-equivalent to
    the pre-fix code on real OPR02 4-point DLC labeled-data (438
    frames × 4 labels = 1752 annotations).
  • tests/conftest.py now sets matplotlib.use("Agg", force=True)
    before any pyplot import, so the test suite runs cleanly headless
    without depending on MPLBACKEND=Agg being set in the
    environment.
  • tests/test_opticalflow.py::test_lucas_kanade_rstc no longer
    returns a tuple (pytest PytestReturnNotNoneWarning); the
    removed return statement was replaced with shape assertions on
    the reverse / RSTC paths.
  • Typo in the ffmpeg-not-found warning ("Cound" → "Could") at
    datanavigator/__init__.py.
  • Dead code after the early return in Event.to_portions.
  • Stale debug print(label_orig_to_internal) in
    _dlc_df_to_annotation_dict.
  • Three commented-out blocks in pointtracking.py (a duplicated
    ctrl+alt+c key binding, the self.ann.update_display /
    show_one_trace alternative paths in
    VideoPointAnnotator.update, and the set_xlim conditional in
    update_annotation_visibility) plus an unclosed-quote comment.
  • plots.py:add_selectors "Unable to add selectors" diagnostic now
    goes through logging.getLogger(__name__).debug instead of stdout
    print.

Notes

  • The numpy<2 pin is retained: it tracks transitive constraints in
    tables (PyTables) and decord, not anything in datanavigator
    itself. It will be revisited in 1.3.0 once CI confirms
    tables >= 3.10 (numpy-2-compatible) works across the matrix.
  • src/datanavigator/ layout migration is deferred to 1.3.0, which
    is already touching the package layout via the pointtracking.py
    split.