dashboard sync app
This commit is contained in:
352
src/utils/platform.py
Normal file
352
src/utils/platform.py
Normal file
@@ -0,0 +1,352 @@
|
||||
"""Cross-platform compatibility utilities."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
def get_platform_info() -> Dict[str, str]:
|
||||
"""Get platform information for compatibility checks."""
|
||||
return {
|
||||
"system": platform.system(),
|
||||
"release": platform.release(),
|
||||
"version": platform.version(),
|
||||
"machine": platform.machine(),
|
||||
"processor": platform.processor(),
|
||||
"python_version": platform.python_version(),
|
||||
"python_implementation": platform.python_implementation(),
|
||||
}
|
||||
|
||||
|
||||
def is_supported_platform() -> bool:
|
||||
"""Check if the current platform is supported."""
|
||||
system = platform.system()
|
||||
python_version = tuple(map(int, platform.python_version().split(".")))
|
||||
|
||||
# Check Python version
|
||||
if python_version < (3, 12):
|
||||
return False
|
||||
|
||||
# Check operating system
|
||||
supported_systems = ["Darwin", "Linux", "Windows"]
|
||||
return system in supported_systems
|
||||
|
||||
|
||||
def get_default_config_dir() -> Path:
|
||||
"""Get platform-specific config directory."""
|
||||
system = platform.system()
|
||||
|
||||
if system == "Darwin": # macOS
|
||||
return Path.home() / "Library" / "Application Support" / "luk"
|
||||
elif system == "Linux":
|
||||
config_dir = os.environ.get("XDG_CONFIG_HOME")
|
||||
if config_dir:
|
||||
return Path(config_dir) / "luk"
|
||||
return Path.home() / ".config" / "luk"
|
||||
elif system == "Windows":
|
||||
return Path(os.environ.get("APPDATA", "")) / "luk"
|
||||
else:
|
||||
# Fallback to ~/.config
|
||||
return Path.home() / ".config" / "luk"
|
||||
|
||||
|
||||
def get_default_data_dir() -> Path:
|
||||
"""Get platform-specific data directory."""
|
||||
system = platform.system()
|
||||
|
||||
if system == "Darwin": # macOS
|
||||
return Path.home() / "Library" / "Application Support" / "luk"
|
||||
elif system == "Linux":
|
||||
data_dir = os.environ.get("XDG_DATA_HOME")
|
||||
if data_dir:
|
||||
return Path(data_dir) / "luk"
|
||||
return Path.home() / ".local" / "share" / "luk"
|
||||
elif system == "Windows":
|
||||
return Path(os.environ.get("LOCALAPPDATA", "")) / "luk"
|
||||
else:
|
||||
# Fallback to ~/.local/share
|
||||
return Path.home() / ".local" / "share" / "luk"
|
||||
|
||||
|
||||
def get_default_log_dir() -> Path:
|
||||
"""Get platform-specific log directory."""
|
||||
system = platform.system()
|
||||
|
||||
if system == "Darwin": # macOS
|
||||
return Path.home() / "Library" / "Logs" / "luk"
|
||||
elif system == "Linux":
|
||||
data_dir = os.environ.get("XDG_DATA_HOME")
|
||||
if data_dir:
|
||||
return Path(data_dir) / "luk" / "logs"
|
||||
return Path.home() / ".local" / "share" / "luk" / "logs"
|
||||
elif system == "Windows":
|
||||
return Path(os.environ.get("LOCALAPPDATA", "")) / "luk" / "logs"
|
||||
else:
|
||||
# Fallback to ~/.local/share/logs
|
||||
return Path.home() / ".local" / "share" / "luk" / "logs"
|
||||
|
||||
|
||||
def get_default_maildir_path() -> Path:
|
||||
"""Get platform-specific default Maildir path."""
|
||||
system = platform.system()
|
||||
|
||||
if system == "Darwin": # macOS
|
||||
return Path.home() / "Library" / "Mail"
|
||||
elif system == "Linux":
|
||||
return Path.home() / "Mail"
|
||||
elif system == "Windows":
|
||||
return Path.home() / "Mail"
|
||||
else:
|
||||
return Path.home() / "Mail"
|
||||
|
||||
|
||||
def check_dependencies() -> Dict[str, bool]:
|
||||
"""Check if required system dependencies are available."""
|
||||
dependencies = {
|
||||
"python": True, # We're running Python
|
||||
"pip": False,
|
||||
"git": False,
|
||||
"curl": False,
|
||||
"wget": False,
|
||||
}
|
||||
|
||||
# Check for pip
|
||||
try:
|
||||
subprocess.run(["pip", "--version"], capture_output=True, check=True)
|
||||
dependencies["pip"] = True
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
# Check for git
|
||||
try:
|
||||
subprocess.run(["git", "--version"], capture_output=True, check=True)
|
||||
dependencies["git"] = True
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
# Check for curl
|
||||
try:
|
||||
subprocess.run(["curl", "--version"], capture_output=True, check=True)
|
||||
dependencies["curl"] = True
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
# Check for wget
|
||||
try:
|
||||
subprocess.run(["wget", "--version"], capture_output=True, check=True)
|
||||
dependencies["wget"] = True
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
return dependencies
|
||||
|
||||
|
||||
def get_shell_info() -> Dict[str, str]:
|
||||
"""Get shell information for completion setup."""
|
||||
shell = os.environ.get("SHELL", "")
|
||||
shell_name = Path(shell).name if shell else "unknown"
|
||||
|
||||
return {
|
||||
"shell_path": shell,
|
||||
"shell_name": shell_name,
|
||||
"config_file": get_shell_config_file(shell_name),
|
||||
}
|
||||
|
||||
|
||||
def get_shell_config_file(shell_name: str) -> str:
|
||||
"""Get the config file for a given shell."""
|
||||
shell_configs = {
|
||||
"bash": "~/.bashrc",
|
||||
"zsh": "~/.zshrc",
|
||||
"fish": "~/.config/fish/config.fish",
|
||||
"ksh": "~/.kshrc",
|
||||
"csh": "~/.cshrc",
|
||||
"tcsh": "~/.tcshrc",
|
||||
}
|
||||
|
||||
return shell_configs.get(shell_name, "~/.profile")
|
||||
|
||||
|
||||
def setup_platform_specific() -> None:
|
||||
"""Setup platform-specific configurations."""
|
||||
system = platform.system()
|
||||
|
||||
if system == "Darwin":
|
||||
setup_macos()
|
||||
elif system == "Linux":
|
||||
setup_linux()
|
||||
elif system == "Windows":
|
||||
setup_windows()
|
||||
|
||||
|
||||
def setup_macos() -> None:
|
||||
"""Setup macOS-specific configurations."""
|
||||
# Ensure macOS-specific directories exist
|
||||
config_dir = get_default_config_dir()
|
||||
data_dir = get_default_data_dir()
|
||||
log_dir = get_default_log_dir()
|
||||
|
||||
for directory in [config_dir, data_dir, log_dir]:
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def setup_linux() -> None:
|
||||
"""Setup Linux-specific configurations."""
|
||||
# Ensure XDG directories exist
|
||||
config_dir = get_default_config_dir()
|
||||
data_dir = get_default_data_dir()
|
||||
log_dir = get_default_log_dir()
|
||||
|
||||
for directory in [config_dir, data_dir, log_dir]:
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def setup_windows() -> None:
|
||||
"""Setup Windows-specific configurations."""
|
||||
# Ensure Windows-specific directories exist
|
||||
config_dir = get_default_config_dir()
|
||||
data_dir = get_default_data_dir()
|
||||
log_dir = get_default_log_dir()
|
||||
|
||||
for directory in [config_dir, data_dir, log_dir]:
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def get_platform_specific_commands() -> Dict[str, str]:
|
||||
"""Get platform-specific command equivalents."""
|
||||
system = platform.system()
|
||||
|
||||
if system == "Darwin" or system == "Linux":
|
||||
return {
|
||||
"open": "open" if system == "Darwin" else "xdg-open",
|
||||
"copy": "pbcopy" if system == "Darwin" else "xclip -selection clipboard",
|
||||
"notify": "osascript -e 'display notification \"%s\"'"
|
||||
if system == "Darwin"
|
||||
else 'notify-send "%s"',
|
||||
}
|
||||
elif system == "Windows":
|
||||
return {
|
||||
"open": "start",
|
||||
"copy": "clip",
|
||||
"notify": "powershell -Command \"Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('%s')\"",
|
||||
}
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
def check_terminal_compatibility() -> Dict[str, bool]:
|
||||
"""Check terminal compatibility for TUI features."""
|
||||
return {
|
||||
"color_support": sys.stdout.isatty(),
|
||||
"unicode_support": True, # Most modern terminals support Unicode
|
||||
"mouse_support": check_mouse_support(),
|
||||
"textual_support": check_textual_support(),
|
||||
}
|
||||
|
||||
|
||||
def check_mouse_support() -> bool:
|
||||
"""Check if terminal supports mouse events."""
|
||||
# This is a basic check - actual mouse support depends on the terminal
|
||||
return sys.stdout.isatty()
|
||||
|
||||
|
||||
def check_textual_support() -> bool:
|
||||
"""Check if Textual TUI framework can run."""
|
||||
try:
|
||||
import textual
|
||||
|
||||
return True
|
||||
except ImportError:
|
||||
return False
|
||||
|
||||
|
||||
def get_platform_recommendations() -> list[str]:
|
||||
"""Get platform-specific recommendations."""
|
||||
system = platform.system()
|
||||
recommendations = []
|
||||
|
||||
if system == "Darwin":
|
||||
recommendations.extend(
|
||||
[
|
||||
"Install iTerm2 or Terminal.app for best TUI experience",
|
||||
"Enable 'Terminal > Preferences > Profiles > Text > Unicode Normalization Form' set to 'None'",
|
||||
"Consider using Homebrew for package management: brew install python3",
|
||||
]
|
||||
)
|
||||
elif system == "Linux":
|
||||
recommendations.extend(
|
||||
[
|
||||
"Use a modern terminal emulator like GNOME Terminal, Konsole, or Alacritty",
|
||||
"Ensure UTF-8 locale is set: export LANG=en_US.UTF-8",
|
||||
"Install system packages: sudo apt-get install python3-pip python3-venv",
|
||||
]
|
||||
)
|
||||
elif system == "Windows":
|
||||
recommendations.extend(
|
||||
[
|
||||
"Use Windows Terminal for best TUI experience",
|
||||
"Enable UTF-8 support in Windows Terminal settings",
|
||||
"Consider using WSL2 for better Unix compatibility",
|
||||
"Install Python from python.org or Microsoft Store",
|
||||
]
|
||||
)
|
||||
|
||||
return recommendations
|
||||
|
||||
|
||||
def validate_environment() -> Dict[str, Any]:
|
||||
"""Validate the current environment for compatibility."""
|
||||
platform_info = get_platform_info()
|
||||
dependencies = check_dependencies()
|
||||
terminal_compat = check_terminal_compatibility()
|
||||
|
||||
return {
|
||||
"platform_supported": is_supported_platform(),
|
||||
"platform_info": platform_info,
|
||||
"dependencies": dependencies,
|
||||
"terminal_compatibility": terminal_compat,
|
||||
"recommendations": get_platform_recommendations(),
|
||||
"config_dir": str(get_default_config_dir()),
|
||||
"data_dir": str(get_default_data_dir()),
|
||||
"log_dir": str(get_default_log_dir()),
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Print environment validation
|
||||
env_info = validate_environment()
|
||||
|
||||
print("Platform Compatibility Check")
|
||||
print("=" * 40)
|
||||
print(
|
||||
f"Platform: {env_info['platform_info']['system']} {env_info['platform_info']['release']}"
|
||||
)
|
||||
print(
|
||||
f"Python: {env_info['platform_info']['python_version']} ({env_info['platform_info']['python_implementation']})"
|
||||
)
|
||||
print(f"Supported: {'✓' if env_info['platform_supported'] else '✗'}")
|
||||
print()
|
||||
|
||||
print("Dependencies:")
|
||||
for dep, available in env_info["dependencies"].items():
|
||||
print(f" {dep}: {'✓' if available else '✗'}")
|
||||
print()
|
||||
|
||||
print("Terminal Compatibility:")
|
||||
for feature, supported in env_info["terminal_compatibility"].items():
|
||||
print(f" {feature}: {'✓' if supported else '✗'}")
|
||||
print()
|
||||
|
||||
print("Directories:")
|
||||
print(f" Config: {env_info['config_dir']}")
|
||||
print(f" Data: {env_info['data_dir']}")
|
||||
print(f" Logs: {env_info['log_dir']}")
|
||||
print()
|
||||
|
||||
if env_info["recommendations"]:
|
||||
print("Recommendations:")
|
||||
for rec in env_info["recommendations"]:
|
||||
print(f" • {rec}")
|
||||
Reference in New Issue
Block a user