Visitar URL original
Bump filelock from 3.15.4 to 4.1.0 by dependabot[bot] · Pull Request #3572 · DeepLabCut/DeepLabCut · GitHub
Skip to content

Bump filelock from 3.15.4 to 4.1.0 - #3572

Closed
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/uv/filelock-4.1.0
Closed

dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/uv/filelock-4.1.0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Oct 30, 2026

Copy link
Copy Markdown
Contributor

Bumps filelock from 3.15.4 to 4.1.0.

Release notes

Sourced from filelock's releases.

4.1.0

Features

  • Import OwnerMode, CompromiseReason and has_fcntl from filelock. #790 by @​gaborbernat.
  • AcquireReturnProxy is generic in the lock type, so with lock.acquire() as held: types held as the lock's own class. #803 by @​gaborbernat.
  • A Timeout from a soft lock names a holder on another host or in another PID namespace, which no contender ever reclaims. #815 by @​gaborbernat.
  • Every option given in seconds takes a Decimal or Fraction, as a file lock's timeout already did, and a read-write lock or lease refuses a bool or string one. #815 by @​gaborbernat.

Bug fixes

  • is_lock_held_by_us and is_lock_held_by_us return False for a marker an earlier process with the same PID left behind. #774 by @​lprnmns.
  • SoftFileLock removes its marker when writing it fails and closing the descriptor fails too, so the lock path no longer stays blocked. #775 by @​harbinresearcher.
  • acquire and acquire no longer wait past timeout when poll_interval is longer than the time left. #777 by @​feiiiiii5.
  • SoftReadWriteLock ignores a generation-log entry whose name is not 20 ASCII digits, which used to stop its heartbeat thread or delete real generations. #778 by @​dxbjavid.
  • ReadWriteLock, SoftReadWriteLock and their async wrappers treat a inf timeout like -1 and raise ValueError for a blocking nan one. #779 by @​darrenhuai.
  • ReadWriteLock and SoftReadWriteLock accept a timeout above TIMEOUT_MAX instead of raising OverflowError. #780 by @​darrenhuai.
  • acquire raises ValueError for a blocking nan timeout or a poll_interval above TIMEOUT_MAX, and treats a inf timeout like -1. #781 by @​gaborbernat.
  • SoftFileLock and MarkerSoftFileLock treat a marker cut before its final newline as malformed, so a crash-truncated record self-heals and a read mid-write no longer breaks a live lock. #782 by @​gaborbernat.
  • UnixFileLock no longer deletes another process's live marker when it falls back to a soft lock on ENOSYS, and on macOS a lock path ending in a separator raises FileNotFoundError instead of retrying. #785 by @​gaborbernat.
  • SoftFileLock and SoftFileLease put back a live successor's marker that a racing stale break moved aside, so a third contender no longer acquires beside the successor. #786 by @​gaborbernat.
  • StrictSoftFileLock removes every claim a failed acquire published, counts an EEXIST link that landed as published, and no longer reports is_locked after a failed claim cleanup. #787 by @​gaborbernat.
  • On Python 3.10 without the exceptiongroup backport, a release failure under the default context_error_policy no longer turns into ModuleNotFoundError; cleanup failures chain instead of grouping, and on_acquired is allowed. #788 by @​gaborbernat.
  • AsyncReadWriteLock and AsyncSoftReadWriteLock drop a task's hold when a caller cancels it during a release that still completes, instead of blocking every later writer. #789 by @​gaborbernat.
  • SoftFileLease releases a lease dropped while held, at garbage collection or interpreter exit, and raises ValueError for a heartbeat_interval above TIMEOUT_MAX. #791 by @​gaborbernat.
  • StrictSoftFileLock judges an abandoned private record's age by the filesystem's clock, so a client clock ahead of an NFS server no longer aborts live publications. #792 by @​gaborbernat.
  • BaseAsyncFileLock raises RuntimeError instead of CancelledError when its executor shuts down with the call still queued, and a waiter interrupted by anything else no longer wedges later calls. #793 by @​gaborbernat.
  • Constructing or closing a second ReadWriteLock on a held database no longer drops the holder's lock, so other processes stay excluded. #794 by @​gaborbernat.
  • SoftReadWriteLock no longer admits a second writer after <path>.rw is removed under a live instance, and flushes each snapshot before publishing it so a crash cannot leave an empty one that wedges every peer. #795 by @​gaborbernat.
  • SoftFileLease reclaims a dead MarkerSoftFileLock owner, and expires a lease or a malformed soft marker after it stays unchanged on the contender's own monotonic clock, so clock skew cannot break it. #796 by @​gaborbernat.
  • A soft lock marker written in a Linux container records its PID namespace with the hostname, so a sibling container that shares the hostname and volume no longer breaks a live lock. #797 by @​gaborbernat.
  • SoftReadWriteLock.close() makes an acquire still waiting in another thread raise RuntimeError, where it used to take the lock on the closed instance and hold it until the process exited. #798 by @​gaborbernat.
  • SoftReadWriteLock reads the head from gen/HEAD, so a client whose cached directory listing is more than 64 generations stale no longer takes an old generation for the head and forks the log. #799 by @​gaborbernat.
  • When the garbage collector finalizes a held BaseAsyncFileLock, it releases on a loop running in another thread, or in place once no loop is left; the lifetime check and path resolution now run in the executor. #800 by @​gaborbernat.
  • SoftReadWriteLock waits out a holder's own stale_threshold before evicting it, keys its singleton on the path its log sits beside, and no longer leaks ledger entries or the holder record of a failed acquire. #801 by @​gaborbernat.
  • lock_descriptor raises ValueError for a blocking poll_interval above TIMEOUT_MAX up front, instead of OverflowError once the descriptor is contended. #802 by @​sricharanreddycheruku.
  • BaseFileLock rejects a bool or string timeout, an out-of-range mode and a non-bool blocking set at any time, rejects unknown options on a singleton cache hit, and tracks an on_acquired reacquire. #803 by @​gaborbernat.
  • StrictSoftFileLock raises SoftFileLockProtocolError naming a directory, symlink or exited soft-lock owner's marker at the lock path, and lock_path_occupant shows what blocks it. #804 by @​gaborbernat.
  • ReadWriteLock raises ValueError for a WAL-mode database instead of disk I/O error, and its /dev/fd fallback links beside the database, so a lock off the TMPDIR filesystem no longer fails with EXDEV. #805 by @​gaborbernat.
  • ReadWriteLock.release() from a thread that holds no read level raises RuntimeError instead of ending another thread's read lock and letting a writer in. #806 by @​gaborbernat.
  • SoftFileLockLifetimeWarning derives from FutureWarning instead of DeprecationWarning, so Python shows it by default outside __main__. #807 by @​gaborbernat.
  • SoftFileLock applies an explicit mode past the umask as UnixFileLock does, and reads a marker number spelled other than in ASCII digits, or a lease with an empty token, as malformed. #807 by @​gaborbernat.
  • ReadWriteLock raises OSError when its database is unlinked or replaced while an acquisition waits, instead of taking a lock that no later opener sees. #808 by @​gaborbernat.
  • On a thread-local synchronous lock, release with force=True and garbage collection release holds exited threads left, and a release() re-entered from a signal handler closes the descriptor once. #810 by @​gaborbernat.
  • SoftFileLease records a lease_duration given as a float subclass, such as NumPy's, in a form every contender parses, so a live lease is no longer evicted as malformed. #815 by @​gaborbernat.
  • StrictSoftFileLock raises SoftFileLockProtocolError for a file at the lock path it cannot parse once it stays unchanged for two seconds, instead of waiting on it forever. #815 by @​gaborbernat.
  • A lock finalized at interpreter exit no longer hangs when a daemon thread stopped inside filelock's fork bookkeeping. #815 by @​gaborbernat.

... (truncated)

Changelog

Sourced from filelock's changelog.

########### Changelog ###########

.. towncrier-draft-entries:: Unreleased

.. towncrier release notes start

.. _release-4-2-5:


4.2.5 (2026-10-30)


.. _release-4-2-5-fixed:

Fixed

  • :meth:~filelock.BaseFileLock.acquire and :meth:~filelock.BaseAsyncFileLock.acquire raise :class:TypeError for a blocking that is not a :class:bool, as the constructor and the blocking setter already do. A truthy value such as the string "false" used to count as True, so a call meant as a single attempt waited for the instance's timeout, and without a limit at the default -1 (:pr:870) by :user:simpleqt and :user:gaborbernat.
  • A :class:~filelock.SoftFileLock acquisition whose first read of its new marker's identity failed reads it again before rolling back. On Windows the rollback could otherwise not recognize the marker it had created, and the empty marker it left blocked the path for every later acquisition, since no contender breaks an empty marker (:pr:869) by :user:simpleqt and :user:gaborbernat.
  • A fork() child of a process holding a :class:~filelock.SoftFileLease starts from an unheld claim. It used to inherit the parent's token, last compromise and heartbeat, so :attr:~filelock.SoftFileLease.token and :attr:~filelock.SoftFileLease.compromise reported a claim the child never held while is_locked reported it unheld (:pr:868) by :user:dxbjavid and :user:gaborbernat.
  • A nested acquire of a held :class:~filelock.FileLock or :class:~filelock.SoftFileLock no longer creates the lock file's parent directory. After a rename of that directory during the hold, the nested acquire recreated the old name, and when a file had taken the name it raised :class:FileExistsError and left the hold's recursion count incremented (:pr:878) by :user:0x5t4l1n and :user:gaborbernat.
  • Fix :class:ReadWriteLock <filelock.ReadWriteLock> failing every acquire with "link directory ... was replaced while opening" in a group-writable directory whose inherited ACL, such as an NFSv4 one on ZFS, opens the link directory to the group. The lock now closes the empty link directory to its owner, and where the filesystem refuses that, such as ZFS with aclmode=restricted, it names the directory to make writable by its owner only (:pr:898) by :user:gaborbernat.
  • Fix :class:~filelock.SoftFileLock, :class:~filelock.MarkerSoftFileLock and :class:~filelock.SoftFileLease raising OverflowError out of acquire(), or never reclaiming a dead holder's lock, when a stranded restore claim beside the lock names a process number outside 1..2**31-1 or spells it in non-ASCII digits. Such a claim is now ignored, as no filelock writes one (:pr:871) by :user:dxbjavid and :user:gaborbernat.
  • Fix soft locks on Windows keeping the marker of a holder that has exited while another process still holds a handle to it, such as a parent's subprocess.Popen after wait() or multiprocessing.Process after join(). Acquiring such a lock with the default timeout=-1 waited forever (:pr:874) by :user:nk-batman21.
  • Fix the read-only reopen of a lock file this account cannot write resolving a relative path against the working directory of the moment. A chdir between the refused O_RDWR open and the reopen made the acquisition wait on a file that is not there, or probe one in another directory. The reopen now uses the path the acquisition pinned

... (truncated)

Commits
  • 6c0ecc2 Release 4.1.0
  • df06bbd 🐛 fix: close regressions since 4.0.12 (#815)
  • 0712045 🐛 fix(read-write): refuse a database moved mid-acquire (#808)
  • 73fefc1 📝 docs: point canonical and og:url at versioned pages (#813)
  • 181b36b 🧪 test(lease): give the age-out test a real-time margin (#814)
  • 2c19af4 🐛 fix(api): release thread holds, guard reentry (#810)
  • 367b111 🐛 fix(soft-rw): publish the head through gen/HEAD (#799)
  • 61582c5 🐛 fix(api): validate lock options up front (#803)
  • 20c4b5a 🐛 fix(descriptor): reject poll intervals above TIMEOUT_MAX (#802)
  • cf092c7 🧪 test: drop timing races from two runner-load flakes (#809)
  • Additional commits viewable in compare view

Most Recent Ignore Conditions Applied to This Pull Request
Dependency Name Ignore Conditions
filelock [< 4, > 3.15.4]

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    You can disable automated security fix PRs for this repo from the Security Alerts page.

Bumps [filelock](https://github.com/tox-dev/filelock) from 3.15.4 to 4.1.0.
- [Release notes](https://github.com/tox-dev/filelock/releases)
- [Changelog](https://github.com/tox-dev/filelock/blob/main/docs/changelog.rst)
- [Commits](tox-dev/filelock@3.15.4...4.1.0)

---
updated-dependencies:
- dependency-name: filelock
  dependency-version: 4.1.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file python:uv Pull requests that update python:uv code labels Oct 30, 2026
@C-Achard C-Achard added the 3.0.3 label Nov 3, 2026
@C-Achard

C-Achard commented Nov 3, 2026

Copy link
Copy Markdown
Member

Superseded by #3577, which targets dev.

@C-Achard C-Achard closed this Nov 3, 2026
deruyter92 pushed a commit to Denny-Hwang/DeepLabCut that referenced this pull request Nov 4, 2026
MMathisLab added a commit that referenced this pull request Nov 14, 2026
* Remove empty pytorch benchmark module

* Stabilize randomized PyTorch tests

Replace random test inputs with deterministic fixtures and stable pytest ids across the pose-estimation PyTorch tests. This avoids run-after-discovery desync, which makes the tests impossible to run in e.g. the VSCode pytest extension

* Diversify PyTorch test coverage

Assign per-case RNG seeds to the PyTorch pose estimation tests and replace a few random samples with fixed edge-case parameters. This keeps test IDs stable while covering a wider range of augmentation, batch size, and input-size combinations.

* Update test_api_utils.py

* Fix ratio kwarg

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix uv package upgrades in GUI updater

The GUI updater was invoking `uv pip install -U ...`, which can upgrade the wrong packages when requirements include extras. This patch strips extras from package specs and uses `--upgrade-package` with the canonical distribution names, preserving the requested package set while keeping the pip fallback intact. It also adds regression coverage for the uv-only and uv-then-pip command-building paths.

* Bump urllib3 from 2.7.0 to 2.8.0

Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](urllib3/urllib3@2.7.0...2.8.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.8.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Remove unused adapt_labeled_data_to_new_project from conversioncode

The function had no callers and could not run (tqdm.tqdm on the tqdm class).
Per maintainer discussion in #3532 it is removed rather than fixed. Also
drops the numpy, tqdm and deeplabcut imports that only it used.

* fix unfitted ellipse tracking

* test also unfitted ellipse track with identities

* Expose DataLoader persistent_workers and prefetch_factor in train_settings

Training on small datasets over hundreds of epochs respawns DataLoader
workers every epoch (persistent_workers=False) with a fixed prefetch depth
of 2, leaving GPU utilization on the table for CPU-heavy pipelines. These
knobs existed in PyTorch but were not reachable through TrainSettingsConfig,
pytorch_config.yaml, or pytorch_cfg_updates (strict schema rejects them).

- TrainSettingsConfig: add dataloader_persistent_workers (default False)
  and dataloader_prefetch_factor (default None = PyTorch default 2,
  validated >= 1).
- train(): forward both to the training DataLoader when
  dataloader_workers > 0; warn and ignore them for single-process loading
  (PyTorch requires workers for both options). .get() with defaults keeps
  old persisted configs without the keys working.
- base.yaml / base_detector.yaml defaults + pytorch_config.md docs.

Adds config roundtrip/validation tests and train() DataLoader-kwarg tests.

Addresses #3547

* fixup: StrictPositiveInt, shared dataloader-kwargs helper, compat test

* Add contribution requirements to AGENTS

This change adds a Contributing section to AGENTS.md documenting new human review disclosure, issue/PR checks, dev setup commands, and testing expectations for DeepLabCut contributions.

* Bump werkzeug from 3.1.8 to 3.1.9

Bumps [werkzeug](https://github.com/pallets/werkzeug) from 3.1.8 to 3.1.9.
- [Release notes](https://github.com/pallets/werkzeug/releases)
- [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst)
- [Commits](pallets/werkzeug@3.1.8...3.1.9)

---
updated-dependencies:
- dependency-name: werkzeug
  dependency-version: 3.1.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* add reject_reserved_keys validator

* revert Dataloader througput settings

Reverts acbf42a and 658becf.

* add TrainSettingsConfig.dataloader_kwargs

* Add missing runner config field

* Bump uv to 0.13.4 and certifi to 2026.10.19 (emSign/eMudhra CA incident)

* Bump soupsieve from 2.8.4 to 2.9

Bumps [soupsieve](https://github.com/facelessuser/soupsieve) from 2.8.4 to 2.9.
- [Release notes](https://github.com/facelessuser/soupsieve/releases)
- [Commits](facelessuser/soupsieve@2.8.4...2.9)

---
updated-dependencies:
- dependency-name: soupsieve
  dependency-version: '2.9'
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* AGENTS.md: remove duplicate text

* point the collate_fn hint at data.train.collate

The training loader reads run_config["data"]["train"]["collate"], so the hint sent
users to a key the config does not have.

* Bump anyio from 4.13.0 to 4.14.2 (#3523)

Bumps [anyio](https://github.com/agronholm/anyio) from 4.13.0 to 4.14.2.
- [Release notes](https://github.com/agronholm/anyio/releases)
- [Commits](agronholm/anyio@4.13.0...4.14.2)

---
updated-dependencies:
- dependency-name: anyio
  dependency-version: 4.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cyril Achard <cyril.achard@epfl.ch>

* Docker: require pip>=26.2.2 and certifi>=2026.10.19, refresh ca-certificates (#3561)

* Update AGENTS.md

Co-authored-by: Jaap de Ruyter van Steveninck <32810691+deruyter92@users.noreply.github.com>

* Update AGENTS.md

* Apply suggestion from @deruyter92

* Update AGENTS.md

Co-authored-by: Cyril Achard <cyril.achard@epfl.ch>

* Bump gitpython from 3.1.59 to 3.1.62 (#3542)

Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.59 to 3.1.62.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](gitpython-developers/GitPython@3.1.59...3.1.62)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-version: 3.1.62
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cyril Achard <cyril.achard@epfl.ch>

* Bump tornado from 6.5.8 to 6.5.9 (#3540)

Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.5.8 to 6.5.9.
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](tornadoweb/tornado@v6.5.8...v6.5.9)

---
updated-dependencies:
- dependency-name: tornado
  dependency-version: 6.5.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cyril Achard <cyril.achard@epfl.ch>

* Seek to the first frame in `KmeansbasedFrameselectioncv2` for consecutive indices (#3531)

* Seek to the first frame in KmeansbasedFrameselectioncv2 for consecutive indices

When the candidate frame indices are consecutive (e.g. extract_frames with
algo="kmeans" and the default cluster_step=1), frames were read sequentially
from the current reader position without seeking first. With start > 0 the
clustering therefore ran on the first frames of the video instead of the
requested [start, stop] range, while the returned indices still pointed into
that range. Seek to the first index before reading.

* VideoReader tests: move `FakeVideoReader` to conftest.py

* VideoReader tests: add test for extract outlier frames path

---------

Co-authored-by: Jaap de Ruyter van Steveninck <32810691+deruyter92@users.noreply.github.com>

* Update tests/pose_estimation_pytorch/other/test_dataset.py

* Fix metadata generation for portable pickling in video API (#3564)

* Refactor pickle loading to handle paths from different operating systems (#3565)

* Add version-aware known_defect pytest marker (#3526)

Centralize known-defect version bounds in tests/conftest.py.
The known_defect marker applies a strict AssertionError-only xfail through the registered version and rejects unknown defect names during collection

* Add regression tests for dataset enumeration (#3527)

* Add regression tests for dataset enumeration

Add shared training-dataset fixtures and strict-xfail coverage for labeled-data enumeration edge cases. The new tests document and pin bugs around `_labeled` folder filtering, substring-based stem removal, and unfiltered labeled-data merges, while also adding a control case and clarifying known-defect metadata in `tests/conftest.py`.

* Add missing video declaration

- The fixture's video_sets is empty, so session-01 was not named by the config either; only the backup folder should be unconfigured
- A fix that merges only folders named in video_sets would have returned no frames, and pd.concat would raise ValueError instead of the test passing, making the fix look like a regression

* Adapt versions for tests (require fixed in 3.1.0)

* `InferenceRunner` + `analyze_videos`: Fix top-down analysis crashing for zero-detections and unreadable video handling (#3488)

* fix _generate_output_data crash on empty predictions

Handle the valid case where PyTorch video inference returns zero predictions.

* Allow create_df_from_prediction() to handle an empty predictions list.

videos with zero
detections would fail after serialization on `np.stack([])`

Return an
empty DataFrame with the expected DLC column schema instead and add a
regression test for the empty-output case.

* Treat zero predictions as a distinct warning case in `video_inference()`

* Don't write dataframe for empty predictions

- add informative warning
- add guard in dataframe export: raise ValueError if no predictions

* update test_videos: pop `"PAFinds"` before comparison

* update test_videos: assert no DF is written for empty predictions

* Return empty-detection inference results

Ensure inference emits results for images whenever a prediction exists, even when no detections are produced and thus no queue item is generated. This avoids dropping frames with valid predictions but empty detection outputs.

* Use CTD predictions for video output

Fixes a mismatch in `analyze_videos` where the DataFrame export step still used `predictions` instead of `ctd_predictions`. This ensures saved video analysis results use the corrected prediction set from the current processing path.

* Handle empty prediction outputs gracefully

When a video produces no pose predictions, analysis now writes all-NaN placeholder predictions so downstream HDF5 export and filtering can continue instead of failing on an empty result set. The DataFrame export path was adjusted to handle these fallback frames correctly and raises clearer errors only for genuinely invalid empty input. FMPOSE 3D inference now also raises a clear RuntimeError when no 2D poses are detected for a video.

* Reuse shared frame key width helper

Move frame key zero-padding logic into `runners.shelving.frame_key_width` and use it from both video output generation and shelf writing. This keeps frame key formatting consistent across full-data exports and on-the-fly shelving, while preserving the default width when the frame count is unknown.

* Clarify video inference warnings

Refines `video_inference` logging so empty results distinguish unreadable videos from detector misses, and keeps re-encoding guidance for partial reads. Expands tests to cover zero-prediction, partial-prediction, and shelf-writer cases.

* Go back to ValueError for empty predictions

* Remove NaN fallback for empty video predictions

Simplifies `analyze_videos` by always passing the inference `predictions` directly to `create_df_from_prediction` when `save_as_df` is enabled, and removes the special-case branch that generated all-NaN placeholder rows when no predictions were produced. The unused `_nan_predictions` helper and its warning/error handling were also deleted.

* Fix CTD export guard for empty predictions

Use the CTD prediction list when deciding whether to write the dataframe, so `.h5` export still happens based on the converted CTD results instead of an unrelated variable. The warning now also explains that the CTD pickle had no frames when export is skipped.

* Clarify empty CTD prediction handling

Add an explanatory comment in `analyze_videos` documenting why `ctd_predictions` can be empty, and why the code warns and skips dataframe creation instead of raising. This captures edge cases like zero-frame pickle output and `save_as_df=False`.

* Centralize test fakes

* Add test for async with no images

* Clarify async inference test comment

Refines the test docstring in `test_runners_inference.py` to describe the async behavior more clearly by comparing it to the sequential path without implying a regression pin.

* Use shared frame key width helper

ShelfWriter now always derives its frame key width through `frame_key_width()` instead of keeping a separate default. This removes duplicated fallback logic and keeps frame index formatting consistent with the shared helper.

* Don't write pickle for unreadable video

All readable frames yield a prediction. An empty list of predictions means the video  could not be read, and no pickle should be saved: it would be detected as analyzed.

* Video inference: update warning for empty predictions

since #3488, all readable frames yield a prediction (even when no animal was detectied) an empty predictions means no readable frames.

* InferenceRunner: don't emit results for producer exceptions

* update code comment

* fix ShelfWriter: report zero framens when empty

* Skip unreadable videos with shelf writer + improve docstring and log message

* Fix  warning typo + update tests

* Remove unreachable CTD empty-export branch and reword FMPose error

---------

Co-authored-by: C-Achard <cyril.achard@epfl.ch>

* Bump pillow from 12.2.0 to 12.3.0 (#3563)

Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.2.0 to 12.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](python-pillow/Pillow@12.2.0...12.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Restrict filterpy version to <2

* Update default Python version to 3.12 in workflow configurations (#3568)

Bump the dev docs workflow python version to 3.12 to avoid failure on 3.10 inompcatible pymdown/mkdocstrings pair being installed in CI.

Code is parsed, not imported, so this would not hide failures from using old python patterns or 3.13+ only-patterns (other jobs would catch it ideally), so there should be no immediate downside to the bump.

Co-authored-by: Jaap de Ruyter van Steveninck <32810691+deruyter92@users.noreply.github.com>

* replace crashing monkeypatch in pd options (#3571)

* Bump pyasn1, oauthlib, gitpython and filelock

- Combines dependabot security updates #3572, #3573, #3574 and #3575, rebuilt on dev

* Omit `dataloader_kwargs` from `TrainSettingsConfig` if unset to ensure forward compatibility (#3576)

* add model_serializer for TrainSettingsConfig.dataloader_kwargs

omit dataloader_kwargs in the .to_dict, .to_yaml and to_commented_map views when the field is not configured (empty or None)

This keeps forward compatibility in older deeplabcut versions

* dataset_kwargs: Use pydantic 2.11 `exclude_if` instead of model serializer

* update pyproject.toml + uv lock: require pydantic 2.11

* Update pyproject.toml

* update uv.lock

* Fix GUI freeze when showing trajectory plots in Analyze Videos (#3466)

* Run trajectory plots after analysis completes

Store plotting options before starting the worker and defer `plot_trajectories(showfigures=True)` to a main-thread finished slot. The analysis pipeline now always runs with `showfigures=False`, only opens trajectory plots when analysis succeeds, and centralizes button/progress-bar reset in the completion handler.

* Fix trajectory plot timing with deferred timer

Refactor post-analysis trajectory plot display to use a single-shot QTimer, ensuring the UI (button re-enable, progress bar hide) fully updates before plots are shown. Also fixes the `_handle_analysis_error` slot signature to accept the error argument, and adds error handling around trajectory plot display.

* Avoid duplicate trajectory plotting in GUI

Update the Analyze Videos tab so `deeplabcut.plot_trajectories(...)` only runs when `plot_trajectories` is enabled and `show_trajectory_plots` is not. This prevents triggering the plotting routine in cases where trajectory plots are already being shown through the separate display flow.

* Refactor pending plot cleanup logic

Extract repeated None-assignment into `_clear_pending_trajectory_plots()` helper. Also move the button re-enable and progress bar hide after the plot timer/clear logic to ensure UI updates happen regardless of plot path.

* Refactor: Each batch now saves its trajectory plots to disk as it finishes

---------

Co-authored-by: Jaap de Ruyter van Steveninck <32810691+deruyter92@users.noreply.github.com>
Co-authored-by: Mackenzie Weygandt Mathis <mathis@rowland.harvard.edu>

* Add Cookbook recipe: fish swimming kinematics from DeepLabCut (#3398)

* Add Cookbook recipe: fish swimming kinematics from DeepLabCut

Adds a post-processing recipe showing how to derive swimming-kinematics
metrics (tail-beat frequency, swimming speed, body curvature, diel index)
from single-animal DeepLabCut pose tracks, and how to use the
Spearman-Brown reliability index to choose a reliable observation
duration. Registers the page in the docs table of contents.

Adapted from Hwang et al. 2026, Ecological Informatics 95, 103760.

* move fish kinematics recipe to dlc-utils community contributions

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mackenzie Weygandt Mathis <mathis@rowland.harvard.edu>
Co-authored-by: Jaap de Ruyter van Steveninck <32810691+deruyter92@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Juan Cobos <juan.cobos@igf.cnrs.fr>
Co-authored-by: Cyril Achard <cyril.achard@epfl.ch>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mohammad Hijjawi <mohammad.hijjawi1997@gmail.com>
Co-authored-by: lu123bing <12312702@mail.sustech.edu.cn>
Co-authored-by: Jaap de Ruyter <deruyter92@gmail.com>
Co-authored-by: Jaap de Ruyter van Steveninck <32810691+deruyter92@users.noreply.github.com>
Co-authored-by: Mohammad Hijjawi <51020382+MohammadHijjawi97@users.noreply.github.com>
Co-authored-by: Mackenzie Weygandt Mathis <mathis@rowland.harvard.edu>
Co-authored-by: Sungjoo(Dennis) Hwang <48212469+Denny-Hwang@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.0.3 dependencies Pull requests that update a dependency file python:uv Pull requests that update python:uv code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant