Skip to content

Platform Base

base

Abstract base class for platform-specific operations.

This abstraction layer enables cross-platform support by defining a common interface for operations that differ between Windows, Linux, and macOS.

Platform

Bases: ABC

Abstract base class for platform-specific operations.

name abstractmethod property

Platform name (e.g. 'windows', 'linux', 'macos').

Create a directory link (junction on Windows, symlink on Unix).

The default implementation creates a POSIX symlink. WindowsPlatform overrides this with NTFS junctions.

Parameters:

Name Type Description Default
source Path

The link path to create (inside ComfyUI).

required
target Path

The target path (external folder).

required
log InstallerLogger | None

Optional logger instance. Falls back to the singleton.

None

Raises:

Type Description
RuntimeError

If link creation fails.

Source code in src/platform/base.py
def create_link(self, source: Path, target: Path, log: InstallerLogger | None = None) -> None:
    """
    Create a directory link (junction on Windows, symlink on Unix).

    The default implementation creates a POSIX symlink.
    WindowsPlatform overrides this with NTFS junctions.

    Args:
        source: The link path to create (inside ComfyUI).
        target: The target path (external folder).
        log: Optional logger instance. Falls back to the singleton.

    Raises:
        RuntimeError: If link creation fails.
    """
    from src.utils.logging import get_logger

    if log is None:
        log = get_logger()

    if source.exists():
        if self.is_link(source):
            log.info(f"Symlink already exists: {source.name}")
            return
        raise RuntimeError(
            f"Cannot create symlink: '{source}' already exists and is not a symlink. "
            "Please remove it manually."
        )

    try:
        os.symlink(str(target), str(source))
    except OSError as e:
        raise RuntimeError(f"Failed to create symlink '{source}' → '{target}': {e}") from e

    if not source.exists():
        raise RuntimeError(f"Symlink creation returned success but '{source}' does not exist.")

    log.sub(f"Linked {source.name}{target.name} (External)", style="cyan")

is_admin() abstractmethod

Check if the current process has administrator/root privileges.

Source code in src/platform/base.py
@abstractmethod
def is_admin(self) -> bool:
    """Check if the current process has administrator/root privileges."""
    ...

enable_long_paths(log=None) abstractmethod

Enable support for long file paths (>260 chars).

Returns:

Type Description
bool

True if long paths were enabled or already enabled.

Source code in src/platform/base.py
@abstractmethod
def enable_long_paths(self, log: InstallerLogger | None = None) -> bool:
    """
    Enable support for long file paths (>260 chars).

    Returns:
        True if long paths were enabled or already enabled.
    """
    ...

detect_python(version='3.13', log=None) abstractmethod

Detect a specific Python version on the system.

Parameters:

Name Type Description Default
version str

The Python version to look for (e.g. "3.13").

'3.13'
log InstallerLogger | None

Optional logger instance.

None

Returns:

Type Description
Path | None

Path to the Python executable, or None if not found.

Source code in src/platform/base.py
@abstractmethod
def detect_python(self, version: str = "3.13", log: InstallerLogger | None = None) -> Path | None:
    """
    Detect a specific Python version on the system.

    Args:
        version: The Python version to look for (e.g. "3.13").
        log: Optional logger instance.

    Returns:
        Path to the Python executable, or None if not found.
    """
    ...

get_app_data_dir() abstractmethod

Get the platform-specific application data directory.

Source code in src/platform/base.py
@abstractmethod
def get_app_data_dir(self) -> Path:
    """Get the platform-specific application data directory."""
    ...

Check if a path is a link (junction or symlink).

Source code in src/platform/base.py
def is_link(self, path: Path) -> bool:
    """Check if a path is a link (junction or symlink)."""
    import os
    if path.is_symlink():
        return True
    if not path.exists():
        return False

    # Path.is_junction() is Python 3.12+
    if hasattr(path, "is_junction"):
        return path.is_junction()
    # Fallback to os.path for Python 3.11
    if hasattr(os.path, "isjunction"):
        return os.path.isjunction(str(path))

    return False

get_platform()

Detect and return the appropriate Platform implementation.

Returns:

Type Description
Platform

A Platform instance for the current OS.

Raises:

Type Description
NotImplementedError

If the current OS is not supported.

Source code in src/platform/base.py
def get_platform() -> Platform:
    """
    Detect and return the appropriate Platform implementation.

    Returns:
        A Platform instance for the current OS.

    Raises:
        NotImplementedError: If the current OS is not supported.
    """
    if sys.platform == "win32":
        from src.platform.windows import WindowsPlatform

        return WindowsPlatform()
    elif sys.platform == "linux":
        from src.platform.linux import LinuxPlatform

        return LinuxPlatform()
    elif sys.platform == "darwin":
        from src.platform.macos import MacOSPlatform

        return MacOSPlatform()
    else:
        raise NotImplementedError(f"Platform '{sys.platform}' is not supported.")