v1.2.0
[1.2.0] - 2026-05-16
Audit-and-polish release. No public API changes.
Added
utils.find_nearestand siblings (find_nearest_idx,
find_nearest_val,find_nearest_idx_val), surfaced via the
package'sutilsmodule. Cash-out from thepntoolsretirement
pass; previously unreleased onmastersince4cdbe64.- 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 arecontinue-on-errorfor
this release while thenumpy<2pin keepsdecord/tables
wheel availability flaky on those platforms. ffmpeg is installed
via OS-conditional steps (apt,brew,choco) so the workflow
works on Apple Siliconmacos-latest. __all__ondatanavigator/__init__.py.from datanavigator import *now exposes 39 documented names (down from 53 — dropped
the stdlib leaksos/sys/shutiland the 11 submodule
attributes). Submodule access viadatanavigator.utils.Xor
from datanavigator import utilsis unchanged.TODO.mdseeded with deferred-to-1.3.0 items, nice-to-have polish,
and stretch goals.[project.optional-dependencies] dev = ["pytest"]in
pyproject.toml, pluspytestinrequirements.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_FOLDERandCACHE_FOLDERnow default
to~/datanavigator/_clipcollectionand~/datanavigator/_cache.
Windows defaults are unchanged (C:\\data\\_clipcollection,
C:\\data\\_cache).CLIP_FOLDER/CACHE_FOLDERenvironment
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-taggedDUSTrack-shapedso the
upcoming 1.3.0 migration todustrack.VideoAnnotationhas 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_clipandVideoPlotBrowser.extract_clipnow
fall back tolibx264whenh264_nvenc(NVIDIA hardware encoder)
is unavailable. Previously hardcoded; failed with
Unknown encoder 'h264_nvenc'orCannot load nvcuda.dllon
CPU-only hosts, CI runners, and macOS / Apple Silicon.is_pathname_validnow catchesValueError(which Python 3.5+
raises for "embedded null character" inos.lstat) in addition
to the staleTypeErrorcatch. The function now returnsFalse
for NUL-bearing paths on modern Python instead of leaking the
exception.tests/test_utils.pypath-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.VideoPlotBrowsersetup no longer crashes on matplotlib ≥ 3.8:
Grouper.joinwas removed in 3.8, replaced byAxes.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.onclickright-click-to-seek now works on
Python ≥ 3.11. The check comparedstr(event.button)to the
literal"MouseButton.RIGHT", which silently broke when
Python 3.11 changedIntEnum.__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_initon Python 3.12 + matplotlib 3.10.7.VideoAnnotation.to_dlcno longer uses pandas chained assignment
(df.loc[row][col] = val), which pandas emits aFutureWarning
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.pynow setsmatplotlib.use("Agg", force=True)
before any pyplot import, so the test suite runs cleanly headless
without depending onMPLBACKEND=Aggbeing set in the
environment.tests/test_opticalflow.py::test_lucas_kanade_rstcno longer
returns a tuple (pytestPytestReturnNotNoneWarning); 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+ckey binding, theself.ann.update_display/
show_one_tracealternative paths in
VideoPointAnnotator.update, and theset_xlimconditional in
update_annotation_visibility) plus an unclosed-quote comment. plots.py:add_selectors"Unable to add selectors" diagnostic now
goes throughlogging.getLogger(__name__).debuginstead of stdout
print.
Notes
- The
numpy<2pin is retained: it tracks transitive constraints in
tables(PyTables) anddecord, 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 thepointtracking.py
split.