Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Iterative Dvc Updater

From Leeroopedia


Knowledge Sources
Domains Version_Management, User_Interface
Last Updated 2026-02-10 10:00 GMT

Overview

Concrete tool for managing DVC version checking and update notifications, provided by the DVC library.

Description

The Updater class is responsible for checking whether a newer version of DVC is available and notifying the user when an update is found. It follows a cache-based approach: version information fetched from a remote endpoint is stored in a local JSON file (the updater file), and subsequent checks read from this cache until it becomes stale (older than 24 hours).

The class lives in dvc/updater.py and is initialized with a tmp_dir path where the updater file and its associated lock file are created. The lock is acquired via dvc.lock.make_lock to prevent concurrent read/write conflicts. The current DVC version is parsed from dvc.__version__ using the packaging.version module.

The check() method is the primary entry point. It first evaluates whether update checking should be skipped entirely -- checks are suppressed in CI environments (the CI environment variable), DVC test mode (DVC_TEST), Snap package installations, and when the user has disabled updates via the core.check_update config option. If none of these conditions apply, the method acquires a lock and proceeds: if the updater file is missing or outdated, it delegates to fetch() to retrieve the latest version; otherwise, it reads the cached version and compares it against the current version using packaging.version.parse.

When the cached version is newer than the installed version, _notify() is called to display a styled Rich message to stderr. The notification includes the current and latest versions along with package-manager-specific upgrade instructions (pip, brew, apt, conda, choco, yum, etc.). Notification is suppressed if stderr is not a TTY.

The fetch() method supports both detached (daemon) and inline modes. In detached mode (the default), it spawns a background daemon process via dvc.daemon.daemon to perform the HTTP request without blocking the user command. In inline mode, it directly calls _get_latest_version(), which performs a GET request to the updater endpoint (configurable via the DVC_UPDATER_ENDPOINT environment variable, defaulting to https://updater.dvc.org) with a 10-second timeout.

The module-level notify_updates() function provides a convenience wrapper that opens a DVC Repo, constructs an Updater, and calls check(). It silently suppresses NotDvcRepoError so it can be safely called from any directory.

Usage

Import Updater when you need programmatic control over version checking, or use notify_updates as a fire-and-forget entry point in CLI command postprocessing. The check() method is typically called at the end of DVC CLI commands to inform users about available updates without interrupting their workflow.

Code Reference

Source Location

  • Repository: DVC
  • File: dvc/updater.py
  • Lines: 191 total
  • Class: Updater (L17-179)
  • Function: notify_updates (L182-190)

Signature

class Updater:
    URL = "https://updater.dvc.org"
    UPDATER_FILE = "updater"
    TIMEOUT = 24 * 60 * 60  # every day
    TIMEOUT_GET = 10

    def __init__(self, tmp_dir, friendly=False, hardlink_lock=False):
        ...

    def check(self):
        ...

    def fetch(self, detach=True):
        ...

    def _notify(self, latest: str, pkg: Optional[str] = PKG) -> None:
        ...

    def is_enabled(self):
        ...
def notify_updates():
    ...

Import

from dvc.updater import Updater, notify_updates

I/O Contract

Updater.__init__

Name Type Required Description
tmp_dir str Yes Path to the temporary directory where the updater cache file and lock file are stored.
friendly bool No If True, use a friendly (non-blocking) lock. Defaults to False.
hardlink_lock bool No If True, use hardlink-based locking instead of the default lock mechanism. Defaults to False.

Updater.check

Name Type Required Description
(none) -- -- Takes no arguments. Reads from the updater cache file and compares versions. Skips entirely in CI, test, snap, or disabled environments.

Side Effects:

  • May spawn a daemon process to fetch the latest version (via fetch).
  • May write a styled notification to stderr if a newer version is available and stderr is a TTY.

Updater.fetch

Name Type Required Description
detach bool No If True (default), spawns a background daemon to perform the HTTP request. If False, performs the request inline in the current process.

Side Effects:

  • Writes the latest version information as JSON to the updater cache file.
  • In detached mode, spawns a daemon process via dvc.daemon.daemon.

Updater.is_enabled

Name Type Description
return bool True if the core.check_update config option is enabled (defaults to True), False otherwise.

notify_updates

Name Type Description
(none) -- Takes no arguments. Opens a DVC Repo from the current working directory, constructs an Updater, and calls check(). Silently suppresses NotDvcRepoError.

Usage Examples

Basic Usage

from dvc.updater import notify_updates

# Call at the end of a CLI command to check for updates
notify_updates()

Programmatic Version Checking

from dvc.updater import Updater

# Create an Updater instance with a custom tmp directory
updater = Updater(tmp_dir="/path/to/repo/.dvc/tmp")

# Check if update checking is enabled in config
if updater.is_enabled():
    # Perform a synchronous (inline) fetch to get the latest version
    updater.fetch(detach=False)

    # The updater file now contains the latest version info
    updater.check()

Environment-Aware Usage

import os
from dvc.updater import Updater

# In CI environments, check() is a no-op
os.environ["CI"] = "true"
updater = Updater(tmp_dir="/path/to/repo/.dvc/tmp")
updater.check()  # Does nothing -- CI environment detected

# With custom endpoint for internal mirror
os.environ["DVC_UPDATER_ENDPOINT"] = "https://internal.example.com/dvc-version"
updater = Updater(tmp_dir="/path/to/repo/.dvc/tmp")
updater.fetch(detach=False)  # Fetches from custom endpoint

Internal Details

Caching Strategy

The updater uses a file-based cache with a 24-hour TTL. The cache file is a JSON document containing version information from the remote endpoint. The _is_outdated_file() method checks the file modification time against TIMEOUT (86400 seconds). When the file is missing or stale, a new fetch is triggered.

Lock Management

All file operations are wrapped in a lock (_with_lock) to prevent concurrent modification. If the lock cannot be acquired, the operation is silently skipped with a debug-level log message. This ensures that update checking never blocks or crashes the user's primary DVC command.

Notification Formatting

The _get_message() method constructs a Rich-formatted message that includes both the current and latest versions. The _get_update_instructions() static method provides package-manager-specific upgrade commands for: pip, rpm (yum), brew, deb (apt-get), conda, and choco. For binary/exe/osxpkg distributions, it directs the user to the DVC website.

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment