Skip to content

Platform

provide.foundation.platform

TODO: Add module docstring.

Classes

PlatformError

PlatformError(
    message: str,
    *,
    platform: str | None = None,
    operation: str | None = None,
    **kwargs: Any
)

Bases: FoundationError

Raised when platform detection or system operations fail.

Parameters:

Name Type Description Default
message str

Error message describing the platform issue.

required
platform str | None

Optional platform identifier.

None
operation str | None

Optional operation that failed.

None
**kwargs Any

Additional context passed to FoundationError.

{}

Examples:

>>> raise PlatformError("Failed to detect OS")
>>> raise PlatformError("Unsupported platform", platform="freebsd")
Source code in provide/foundation/errors/platform.py
def __init__(
    self,
    message: str,
    *,
    platform: str | None = None,
    operation: str | None = None,
    **kwargs: Any,
) -> None:
    if platform:
        kwargs.setdefault("context", {})["platform.name"] = platform
    if operation:
        kwargs.setdefault("context", {})["platform.operation"] = operation
    super().__init__(message, **kwargs)

SystemInfo

System information container.

Functions

get_arch_name

get_arch_name() -> str

Get normalized architecture name.

Returns:

Type Description
str

Normalized architecture (amd64, arm64, x86, i386)

Source code in provide/foundation/platform/detection.py
@cached()
def get_arch_name() -> str:
    """Get normalized architecture name.

    Returns:
        Normalized architecture (amd64, arm64, x86, i386)

    """
    try:
        arch = platform.machine().lower()
        # Normalize common architectures
        if arch in ["x86_64", "amd64"]:
            return "amd64"
        if arch in ["aarch64", "arm64"]:
            return "arm64"
        if arch in ["i686", "i586", "i486"]:
            return "x86"
        return arch
    except Exception as e:
        log.error("Failed to detect architecture", error=str(e))
        raise PlatformError(
            "Failed to detect architecture",
            code="PLATFORM_ARCH_DETECTION_FAILED",
            error=str(e),
        ) from e

get_cpu_brand

get_cpu_brand() -> str

Get CPU brand string.

Returns:

Type Description
str

CPU brand string (e.g., "Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz")

Example

from provide.foundation.platform import get_cpu_brand get_cpu_brand() 'Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz'

Source code in provide/foundation/platform/cpu.py
def get_cpu_brand() -> str:
    """Get CPU brand string.

    Returns:
        CPU brand string (e.g., "Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz")

    Example:
        >>> from provide.foundation.platform import get_cpu_brand
        >>> get_cpu_brand()
        'Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz'

    """
    info = get_cpu_info()
    return str(info.get("brand_raw") or info.get("brand") or "Unknown")

get_cpu_count

get_cpu_count() -> int | None

Get number of logical CPUs.

Returns:

Type Description
int | None

Number of logical CPUs, or None if not available

Example

from provide.foundation.platform import get_cpu_count get_cpu_count() 8

Source code in provide/foundation/platform/cpu.py
def get_cpu_count() -> int | None:
    """Get number of logical CPUs.

    Returns:
        Number of logical CPUs, or None if not available

    Example:
        >>> from provide.foundation.platform import get_cpu_count
        >>> get_cpu_count()
        8

    """
    info = get_cpu_info()
    count = info.get("count")
    if count is None:
        return None
    return int(count)

get_cpu_flags

get_cpu_flags() -> list[str]

Get list of CPU flags/features.

Returns:

Type Description
list[str]

List of CPU flags (e.g., ["sse", "avx", "avx2"]), or empty list if not available

Example

from provide.foundation.platform import get_cpu_flags flags = get_cpu_flags() 'avx2' in flags True

Source code in provide/foundation/platform/cpu.py
def get_cpu_flags() -> list[str]:
    """Get list of CPU flags/features.

    Returns:
        List of CPU flags (e.g., ["sse", "avx", "avx2"]), or empty list if not available

    Example:
        >>> from provide.foundation.platform import get_cpu_flags
        >>> flags = get_cpu_flags()
        >>> 'avx2' in flags
        True

    """
    info = get_cpu_info()
    flags = info.get("flags")
    if flags is None:
        return []
    if isinstance(flags, list):
        return flags
    return []

get_cpu_info

get_cpu_info() -> dict[str, str | int | list[str] | None]

Get detailed CPU information.

Returns comprehensive CPU information including brand, vendor, architecture, flags, and feature support.

Returns:

Type Description
dict[str, str | int | list[str] | None]

Dictionary containing CPU information. Keys include:

dict[str, str | int | list[str] | None]
  • brand: CPU brand string (e.g., "Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz")
dict[str, str | int | list[str] | None]
  • vendor_id: Vendor identifier (e.g., "GenuineIntel", "AuthenticAMD")
dict[str, str | int | list[str] | None]
  • arch: Architecture (e.g., "X86_64", "ARM_8")
dict[str, str | int | list[str] | None]
  • bits: Bit width (32 or 64)
dict[str, str | int | list[str] | None]
  • count: Number of logical CPUs
dict[str, str | int | list[str] | None]
  • flags: List of CPU flags/features (e.g., ["sse", "avx", "avx2"])
dict[str, str | int | list[str] | None]
  • hz_advertised: Advertised clock speed in Hz
dict[str, str | int | list[str] | None]
  • hz_actual: Actual clock speed in Hz
dict[str, str | int | list[str] | None]
  • family: CPU family
dict[str, str | int | list[str] | None]
  • model: CPU model
dict[str, str | int | list[str] | None]
  • stepping: CPU stepping
dict[str, str | int | list[str] | None]

When py-cpuinfo is not available, returns basic information from

dict[str, str | int | list[str] | None]

platform module.

Example

from provide.foundation.platform import get_cpu_info info = get_cpu_info() info['brand'] 'Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz' 'avx2' in info.get('flags', []) True

Source code in provide/foundation/platform/cpu.py
@cached()
def get_cpu_info() -> dict[str, str | int | list[str] | None]:
    """Get detailed CPU information.

    Returns comprehensive CPU information including brand, vendor, architecture,
    flags, and feature support.

    Returns:
        Dictionary containing CPU information. Keys include:
        - brand: CPU brand string (e.g., "Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz")
        - vendor_id: Vendor identifier (e.g., "GenuineIntel", "AuthenticAMD")
        - arch: Architecture (e.g., "X86_64", "ARM_8")
        - bits: Bit width (32 or 64)
        - count: Number of logical CPUs
        - flags: List of CPU flags/features (e.g., ["sse", "avx", "avx2"])
        - hz_advertised: Advertised clock speed in Hz
        - hz_actual: Actual clock speed in Hz
        - family: CPU family
        - model: CPU model
        - stepping: CPU stepping

        When py-cpuinfo is not available, returns basic information from
        platform module.

    Example:
        >>> from provide.foundation.platform import get_cpu_info
        >>> info = get_cpu_info()
        >>> info['brand']
        'Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz'
        >>> 'avx2' in info.get('flags', [])
        True

    """
    if _HAS_CPUINFO:
        try:
            info = cpuinfo.get_cpu_info()
            log.debug(
                "Detailed CPU info gathered",
                brand=info.get("brand_raw"),
                arch=info.get("arch"),
                count=info.get("count"),
            )
            return info
        except Exception as e:
            log.warning("Failed to get detailed CPU info, falling back to basic info", error=str(e))

    # Fallback: Basic CPU info from platform module
    basic_info: dict[str, str | int | list[str] | None] = {
        "brand": platform.processor() or "Unknown",
        "vendor_id": None,
        "arch": platform.machine(),
        "bits": 64 if platform.machine().endswith("64") else 32,
        "count": None,
        "flags": None,
        "hz_advertised": None,
        "hz_actual": None,
        "family": None,
        "model": None,
        "stepping": None,
    }

    # Try to get CPU count from os module
    try:
        import os

        basic_info["count"] = os.cpu_count()
    except Exception:
        pass

    log.debug("Basic CPU info gathered (py-cpuinfo not available)", arch=basic_info["arch"])

    return basic_info

get_cpu_type

get_cpu_type() -> str | None

Get CPU type/family information.

Returns:

Type Description
str | None

CPU type string or None if unavailable

Source code in provide/foundation/platform/detection.py
@cached()
def get_cpu_type() -> str | None:
    """Get CPU type/family information.

    Returns:
        CPU type string or None if unavailable

    """
    try:
        processor = platform.processor()
        if not processor:
            return None

        # Try different CPU detection strategies
        for detector in [_detect_intel_cpu, _detect_amd_cpu, _detect_apple_cpu]:
            result = detector(processor)
            if result:
                return result

        # Return cleaned processor string as fallback
        return processor.strip()

    except Exception as e:
        log.warning("Failed to detect CPU type", error=str(e))

    return None

get_os_name

get_os_name() -> str

Get normalized OS name.

Returns:

Type Description
str

Normalized OS name (darwin, linux, windows)

Source code in provide/foundation/platform/detection.py
@cached()
def get_os_name() -> str:
    """Get normalized OS name.

    Returns:
        Normalized OS name (darwin, linux, windows)

    """
    try:
        os_name = platform.system().lower()
        if os_name in ("darwin", "macos"):
            return "darwin"
        return os_name
    except Exception as e:
        log.error("Failed to detect OS", error=str(e))
        raise PlatformError(
            "Failed to detect operating system",
            code="PLATFORM_OS_DETECTION_FAILED",
            error=str(e),
        ) from e

get_os_version

get_os_version() -> str | None

Get OS version information.

Returns:

Type Description
str | None

OS version string or None if unavailable

Source code in provide/foundation/platform/detection.py
@cached()
def get_os_version() -> str | None:
    """Get OS version information.

    Returns:
        OS version string or None if unavailable

    """
    try:
        system = platform.system()

        if system == "Darwin":
            # macOS version
            mac_ver = platform.mac_ver()
            if mac_ver[0]:
                return mac_ver[0]
        elif system == "Linux":
            # Linux kernel version
            release = platform.release()
            if release:
                # Extract major.minor version
                parts = release.split(".")
                if len(parts) >= 2:
                    return f"{parts[0]}.{parts[1]}"
                return release
        elif system == "Windows":
            # Windows version
            version = platform.version()
            if version:
                return version

        # Fallback to platform.release()
        release = platform.release()
        if release:
            return release
    except Exception as e:
        log.warning("Failed to detect OS version", error=str(e))

    return None

get_platform_string

get_platform_string() -> str

Get normalized platform string in format 'os_arch'.

Returns:

Type Description
str

Platform string like 'darwin_arm64' or 'linux_amd64'

Source code in provide/foundation/platform/detection.py
@cached()
def get_platform_string() -> str:
    """Get normalized platform string in format 'os_arch'.

    Returns:
        Platform string like 'darwin_arm64' or 'linux_amd64'

    """
    os_name = get_os_name()
    arch = get_arch_name()
    platform_str = f"{os_name}_{arch}"
    log.debug("Detected platform", platform=platform_str, os=os_name, arch=arch)
    return platform_str

get_system_info

get_system_info() -> SystemInfo

Gather comprehensive system information.

Returns:

Type Description
SystemInfo

SystemInfo object with all available system details

Source code in provide/foundation/platform/info.py
@cached()
def get_system_info() -> SystemInfo:
    """Gather comprehensive system information.

    Returns:
        SystemInfo object with all available system details

    """
    # Basic platform info
    os_name = get_os_name()
    arch = get_arch_name()
    platform_str = get_platform_string()
    os_version = get_os_version()
    cpu_type = get_cpu_type()

    # Python info
    python_version = platform.python_version()

    # System info
    hostname = None
    with contextlib.suppress(Exception):
        hostname = platform.node()

    # User info
    username = os.environ.get("USER") or os.environ.get("USERNAME")
    home_dir = str(Path("~").expanduser())
    # Use secure temp directory - prefer environment variables over Foundation's temp dir
    from provide.foundation.file.temp import system_temp_dir

    temp_dir = os.environ.get("TMPDIR") or os.environ.get("TEMP") or str(system_temp_dir())

    # CPU info
    num_cpus = None
    with contextlib.suppress(Exception):
        num_cpus = os.cpu_count()

    # Memory info (requires psutil for accurate values)
    total_memory = None
    available_memory = None
    try:
        import psutil

        mem = psutil.virtual_memory()
        total_memory = mem.total
        available_memory = mem.available
    except ImportError:
        log.debug(
            "psutil not available, memory info unavailable",
            hint="Install with: pip install provide-foundation[platform]",
        )
    except Exception as e:
        log.debug("Failed to get memory info", error=str(e))

    # Disk usage
    disk_usage = None
    try:
        disk_usage = {}
        for path in ["/", home_dir, temp_dir]:
            if Path(path).exists():
                usage = shutil.disk_usage(path)
                disk_usage[path] = {
                    "total": usage.total,
                    "used": usage.used,
                    "free": usage.free,
                }
    except Exception as e:
        log.debug("Failed to get disk usage", error=str(e))

    info = SystemInfo(
        os_name=os_name,
        arch=arch,
        platform=platform_str,
        os_version=os_version,
        cpu_type=cpu_type,
        python_version=python_version,
        hostname=hostname,
        username=username,
        home_dir=home_dir,
        temp_dir=temp_dir,
        num_cpus=num_cpus,
        total_memory=total_memory,
        available_memory=available_memory,
        disk_usage=disk_usage,
    )

    log.debug(
        "System information gathered",
        platform=platform_str,
        os=os_name,
        arch=arch,
        python=python_version,
        cpus=num_cpus,
    )

    return info

has_cpu_flag

has_cpu_flag(flag: str) -> bool

Check if CPU has a specific flag/feature.

Parameters:

Name Type Description Default
flag str

Flag name to check (e.g., "avx2", "sse4_2")

required

Returns:

Type Description
bool

True if CPU has the flag, False otherwise

Example

from provide.foundation.platform import has_cpu_flag has_cpu_flag('avx2') True has_cpu_flag('avx512f') False

Source code in provide/foundation/platform/cpu.py
def has_cpu_flag(flag: str) -> bool:
    """Check if CPU has a specific flag/feature.

    Args:
        flag: Flag name to check (e.g., "avx2", "sse4_2")

    Returns:
        True if CPU has the flag, False otherwise

    Example:
        >>> from provide.foundation.platform import has_cpu_flag
        >>> has_cpu_flag('avx2')
        True
        >>> has_cpu_flag('avx512f')
        False

    """
    return flag.lower() in [f.lower() for f in get_cpu_flags()]

has_cpuinfo

has_cpuinfo() -> bool

Check if py-cpuinfo is available.

Returns:

Type Description
bool

True if py-cpuinfo is available, False otherwise

Example

from provide.foundation.platform import has_cpuinfo if has_cpuinfo(): ... # Use detailed CPU features ... pass

Source code in provide/foundation/platform/cpu.py
def has_cpuinfo() -> bool:
    """Check if py-cpuinfo is available.

    Returns:
        True if py-cpuinfo is available, False otherwise

    Example:
        >>> from provide.foundation.platform import has_cpuinfo
        >>> if has_cpuinfo():
        ...     # Use detailed CPU features
        ...     pass

    """
    return _HAS_CPUINFO

has_systemd

has_systemd() -> bool

Check if systemd integration is available.

Returns:

Type Description
bool

True if running on Linux and sdnotify is installed, False otherwise

Example

from provide.foundation.platform import has_systemd if has_systemd(): ... # Use systemd features ... pass

Source code in provide/foundation/platform/systemd.py
def has_systemd() -> bool:
    """Check if systemd integration is available.

    Returns:
        True if running on Linux and sdnotify is installed, False otherwise

    Example:
        >>> from provide.foundation.platform import has_systemd
        >>> if has_systemd():
        ...     # Use systemd features
        ...     pass

    """
    return _HAS_SDNOTIFY

is_64bit

is_64bit() -> bool

Check if running on 64-bit architecture.

Source code in provide/foundation/platform/info.py
@cached()
def is_64bit() -> bool:
    """Check if running on 64-bit architecture."""
    return platform.machine().endswith("64") or sys.maxsize > 2**32

is_arm

is_arm() -> bool

Check if running on ARM architecture.

Source code in provide/foundation/platform/info.py
@cached()
def is_arm() -> bool:
    """Check if running on ARM architecture."""
    machine = platform.machine().lower()
    return "arm" in machine or "aarch" in machine

is_linux

is_linux() -> bool

Check if running on Linux.

Source code in provide/foundation/platform/info.py
@cached()
def is_linux() -> bool:
    """Check if running on Linux."""
    return sys.platform.startswith("linux")

is_macos

is_macos() -> bool

Check if running on macOS.

Source code in provide/foundation/platform/info.py
@cached()
def is_macos() -> bool:
    """Check if running on macOS."""
    return sys.platform == "darwin"

is_windows

is_windows() -> bool

Check if running on Windows.

Source code in provide/foundation/platform/info.py
@cached()
def is_windows() -> bool:
    """Check if running on Windows."""
    return sys.platform.startswith("win")

normalize_platform_components

normalize_platform_components(
    os_name: str, arch_name: str
) -> tuple[str, str]

Normalize OS and architecture names to standard format.

Parameters:

Name Type Description Default
os_name str

Operating system name

required
arch_name str

Architecture name

required

Returns:

Type Description
tuple[str, str]

Tuple of (normalized_os, normalized_arch)

Source code in provide/foundation/platform/detection.py
def normalize_platform_components(os_name: str, arch_name: str) -> tuple[str, str]:
    """Normalize OS and architecture names to standard format.

    Args:
        os_name: Operating system name
        arch_name: Architecture name

    Returns:
        Tuple of (normalized_os, normalized_arch)

    """
    # Normalize OS names
    os_map = {
        "linux": "linux",
        "darwin": "darwin",
        "macos": "darwin",
        "windows": "windows",
        "win32": "windows",
    }

    # Normalize architecture names
    arch_map = {
        "x86_64": "amd64",
        "amd64": "amd64",
        "aarch64": "arm64",
        "arm64": "arm64",
        "i686": "x86",
        "i586": "x86",
        "i486": "x86",
        "i386": "i386",
    }

    normalized_os = os_map.get(os_name.lower(), os_name.lower())
    normalized_arch = arch_map.get(arch_name.lower(), arch_name.lower())

    return normalized_os, normalized_arch

notify_error

notify_error(
    errno: int, message: str | None = None
) -> bool

Notify systemd of an error condition.

Parameters:

Name Type Description Default
errno int

Error number (errno value)

required
message str | None

Optional error message

None

Automatically disabled in test mode (via @skip_in_test_mode decorator).

Returns:

Type Description
bool

True if notification sent successfully, False if sdnotify not available

Example

from provide.foundation.platform import notify_error import errno notify_error(errno.ECONNREFUSED, "Failed to connect to database") True

Source code in provide/foundation/platform/systemd.py
@skip_in_test_mode(return_value=False, reason="systemd notifications not meaningful in tests")
def notify_error(errno: int, message: str | None = None) -> bool:
    """Notify systemd of an error condition.

    Args:
        errno: Error number (errno value)
        message: Optional error message

    Automatically disabled in test mode (via @skip_in_test_mode decorator).

    Returns:
        True if notification sent successfully, False if sdnotify not available

    Example:
        >>> from provide.foundation.platform import notify_error
        >>> import errno
        >>> notify_error(errno.ECONNREFUSED, "Failed to connect to database")
        True

    """
    if not _HAS_SDNOTIFY or _notifier is None:
        log.debug("Cannot notify systemd error - sdnotify not available")
        return False

    try:
        notification = f"ERRNO={errno}"
        _notifier.notify(notification)
        log.warning("Notified systemd error", errno=errno, message=message)
        return True
    except Exception as e:
        log.warning("Failed to notify systemd error", errno=errno, error=str(e))
        return False

notify_ready

notify_ready() -> bool

Notify systemd that the service is ready.

This should be called once the service has completed initialization and is ready to handle requests. For Type=notify services, systemd waits for this notification before considering the service started.

Automatically disabled in test mode (via @skip_in_test_mode decorator).

Returns:

Type Description
bool

True if notification sent successfully, False if sdnotify not available

bool

or running in test mode

Example

from provide.foundation.platform import notify_ready

After service initialization

notify_ready() True

Source code in provide/foundation/platform/systemd.py
@skip_in_test_mode(return_value=False, reason="systemd notifications not meaningful in tests")
def notify_ready() -> bool:
    """Notify systemd that the service is ready.

    This should be called once the service has completed initialization and is
    ready to handle requests. For Type=notify services, systemd waits for this
    notification before considering the service started.

    Automatically disabled in test mode (via @skip_in_test_mode decorator).

    Returns:
        True if notification sent successfully, False if sdnotify not available
        or running in test mode

    Example:
        >>> from provide.foundation.platform import notify_ready
        >>> # After service initialization
        >>> notify_ready()
        True

    """
    if not _HAS_SDNOTIFY or _notifier is None:
        log.debug(
            "Cannot notify systemd - sdnotify not available",
            hint="Install with: pip install provide-foundation[platform-linux]",
        )
        return False

    try:
        _notifier.notify("READY=1")
        log.info("Notified systemd: service ready")
        return True
    except Exception as e:
        log.warning("Failed to notify systemd ready status", error=str(e))
        return False

notify_reloading

notify_reloading() -> bool

Notify systemd that the service is reloading configuration.

Call this at the beginning of configuration reload, and call notify_ready() when reload is complete.

Automatically disabled in test mode (via @skip_in_test_mode decorator).

Returns:

Type Description
bool

True if notification sent successfully, False if sdnotify not available

Example

from provide.foundation.platform import notify_reloading, notify_ready notify_reloading() True

Reload configuration

notify_ready() True

Source code in provide/foundation/platform/systemd.py
@skip_in_test_mode(return_value=False, reason="systemd notifications not meaningful in tests")
def notify_reloading() -> bool:
    """Notify systemd that the service is reloading configuration.

    Call this at the beginning of configuration reload, and call notify_ready()
    when reload is complete.

    Automatically disabled in test mode (via @skip_in_test_mode decorator).

    Returns:
        True if notification sent successfully, False if sdnotify not available

    Example:
        >>> from provide.foundation.platform import notify_reloading, notify_ready
        >>> notify_reloading()
        True
        >>> # Reload configuration
        >>> notify_ready()
        True

    """
    if not _HAS_SDNOTIFY or _notifier is None:
        log.debug("Cannot notify systemd reload - sdnotify not available")
        return False

    try:
        _notifier.notify("RELOADING=1")
        log.info("Notified systemd: reloading")
        return True
    except Exception as e:
        log.warning("Failed to notify systemd reloading", error=str(e))
        return False

notify_status

notify_status(status: str) -> bool

Send status text to systemd.

The status will be visible in systemctl status output.

Automatically disabled in test mode (via @skip_in_test_mode decorator).

Parameters:

Name Type Description Default
status str

Status message to send to systemd

required

Returns:

Type Description
bool

True if notification sent successfully, False if sdnotify not available

Example

from provide.foundation.platform import notify_status notify_status("Processing requests: 42 active connections") True

Source code in provide/foundation/platform/systemd.py
@skip_in_test_mode(return_value=False, reason="systemd notifications not meaningful in tests")
def notify_status(status: str) -> bool:
    """Send status text to systemd.

    The status will be visible in systemctl status output.

    Automatically disabled in test mode (via @skip_in_test_mode decorator).

    Args:
        status: Status message to send to systemd

    Returns:
        True if notification sent successfully, False if sdnotify not available

    Example:
        >>> from provide.foundation.platform import notify_status
        >>> notify_status("Processing requests: 42 active connections")
        True

    """
    if not _HAS_SDNOTIFY or _notifier is None:
        log.debug(
            "Cannot notify systemd status - sdnotify not available",
            status=status,
        )
        return False

    try:
        _notifier.notify(f"STATUS={status}")
        log.debug("Notified systemd status", status=status)
        return True
    except Exception as e:
        log.warning("Failed to notify systemd status", status=status, error=str(e))
        return False

notify_stopping

notify_stopping() -> bool

Notify systemd that the service is stopping.

Call this at the beginning of graceful shutdown.

Automatically disabled in test mode (via @skip_in_test_mode decorator).

Returns:

Type Description
bool

True if notification sent successfully, False if sdnotify not available

Example

from provide.foundation.platform import notify_stopping

At shutdown

notify_stopping() True

Perform cleanup
Exit
Source code in provide/foundation/platform/systemd.py
@skip_in_test_mode(return_value=False, reason="systemd notifications not meaningful in tests")
def notify_stopping() -> bool:
    """Notify systemd that the service is stopping.

    Call this at the beginning of graceful shutdown.

    Automatically disabled in test mode (via @skip_in_test_mode decorator).

    Returns:
        True if notification sent successfully, False if sdnotify not available

    Example:
        >>> from provide.foundation.platform import notify_stopping
        >>> # At shutdown
        >>> notify_stopping()
        True
        >>> # Perform cleanup
        >>> # Exit

    """
    if not _HAS_SDNOTIFY or _notifier is None:
        log.debug("Cannot notify systemd stopping - sdnotify not available")
        return False

    try:
        _notifier.notify("STOPPING=1")
        log.info("Notified systemd: stopping")
        return True
    except Exception as e:
        log.warning("Failed to notify systemd stopping", error=str(e))
        return False

notify_watchdog

notify_watchdog() -> bool

Send watchdog keepalive to systemd.

If WatchdogSec is configured in the systemd service unit, the service must call this periodically to prevent systemd from considering it hung and restarting it.

Automatically disabled in test mode (via @skip_in_test_mode decorator).

Returns:

Type Description
bool

True if notification sent successfully, False if sdnotify not available

Example

from provide.foundation.platform import notify_watchdog import asyncio async def watchdog_loop(): ... while True: ... await asyncio.sleep(10) # Must be < WatchdogSec ... notify_watchdog()

Source code in provide/foundation/platform/systemd.py
@skip_in_test_mode(return_value=False, reason="systemd notifications not meaningful in tests")
def notify_watchdog() -> bool:
    """Send watchdog keepalive to systemd.

    If WatchdogSec is configured in the systemd service unit, the service must
    call this periodically to prevent systemd from considering it hung and
    restarting it.

    Automatically disabled in test mode (via @skip_in_test_mode decorator).

    Returns:
        True if notification sent successfully, False if sdnotify not available

    Example:
        >>> from provide.foundation.platform import notify_watchdog
        >>> import asyncio
        >>> async def watchdog_loop():
        ...     while True:
        ...         await asyncio.sleep(10)  # Must be < WatchdogSec
        ...         notify_watchdog()

    """
    if not _HAS_SDNOTIFY or _notifier is None:
        log.debug("Cannot notify systemd watchdog - sdnotify not available")
        return False

    try:
        _notifier.notify("WATCHDOG=1")
        log.debug("Notified systemd watchdog")
        return True
    except Exception as e:
        log.warning("Failed to notify systemd watchdog", error=str(e))
        return False