Source code for pyelink.version

"""Python version compatibility checking for eyelink-wrapper backends.

This module provides runtime checks to ensure that the Python version is compatible
with the requested visualization backend before attempting to import it.
"""

import sys
import warnings

# Version requirements for each backend
# Based on official documentation and testing as of 2025
BACKEND_REQUIREMENTS = {
    "psychopy": {
        "min_python": (3, 9),
        "max_python": (3, 11),
        "package": "psychopy",
        "reason": "PsychoPy officially supports Python 3.9-3.11",
    },
    "pygame": {
        "min_python": (3, 9),
        "max_python": (3, 14),
        "package": "pygame",
        "reason": "pygame supports Python 3.9-3.14",
    },
    "pyglet": {
        "min_python": (3, 8),
        "max_python": (3, 14),
        "package": "pyglet",
        "reason": "pyglet supports modern Python versions",
    },
}


[docs] def check_python_version(backend_name: str) -> tuple[bool, str]: """Check if current Python version is compatible with the requested backend. Args: backend_name: Name of the backend ('psychopy', 'pygame', 'pyglet') Returns: tuple: (is_compatible: bool, message: str) - is_compatible: True if Python version is compatible - message: Status message or error description """ if backend_name not in BACKEND_REQUIREMENTS: return False, f"Unknown backend: {backend_name}" req = BACKEND_REQUIREMENTS[backend_name] current_version = sys.version_info[:2] if current_version < req["min_python"]: min_ver = ".".join(map(str, req["min_python"])) current_ver = sys.version.split()[0] return False, ( f"{backend_name} requires Python >={min_ver} but you're using {current_ver}. Reason: {req['reason']}" ) if current_version > req["max_python"]: max_ver = ".".join(map(str, req["max_python"])) current_ver = sys.version.split()[0] return False, ( f"{backend_name} requires Python <={max_ver} but you're using {current_ver}. Reason: {req['reason']}" ) return True, "Compatible"
[docs] def warn_if_incompatible(backend_name: str) -> bool: """Warn user if Python version is incompatible with backend. This function will issue a UserWarning if the Python version is not compatible with the requested backend, providing clear guidance on what to do. Args: backend_name: Name of the backend to check Returns: bool: True if compatible, False otherwise """ is_compatible, message = check_python_version(backend_name) if not is_compatible: warnings.warn( f"\n{'=' * 60}\nWARNING: {message}\n{'=' * 60}\n", UserWarning, stacklevel=2, ) return is_compatible
[docs] def get_incompatible_reason(backend_name: str) -> str | None: """Get the reason why a backend is incompatible with current Python version. Args: backend_name: Name of the backend Returns: str | None: Reason for incompatibility, or None if compatible """ is_compatible, message = check_python_version(backend_name) if is_compatible: return None return message