feat: initial commit
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Runtime Compatibility Module
|
||||
|
||||
Provides cross-platform compatibility utilities for Noma.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def enable_windows_utf8_stdio(skip_in_pytest: bool = False):
|
||||
"""
|
||||
Enable UTF-8 mode for Windows stdout/stderr.
|
||||
|
||||
On Windows, the console defaults to the system code page encoding,
|
||||
which doesn't support UTF-8 well. This function attempts to
|
||||
configure the console for UTF-8 operation.
|
||||
|
||||
Args:
|
||||
skip_in_pytest: If True, skip UTF-8 configuration when running in pytest.
|
||||
This prevents interference with pytest's output capture.
|
||||
"""
|
||||
if sys.platform != "win32":
|
||||
return
|
||||
|
||||
# Skip if running in pytest
|
||||
if skip_in_pytest and "pytest" in sys.modules:
|
||||
return
|
||||
|
||||
try:
|
||||
# Windows-specific setup for UTF-8
|
||||
import ctypes
|
||||
import io
|
||||
|
||||
# Try to set console mode to enable UTF-8
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
|
||||
# Get stdout handle
|
||||
stdout_handle = kernel32.GetStdHandle(-11) # STD_OUTPUT_HANDLE
|
||||
stderr_handle = kernel32.GetStdHandle(-12) # STD_ERROR_HANDLE
|
||||
|
||||
# Enable UTF-8 mode by setting code page
|
||||
kernel32.SetConsoleOutputCP(65001) # UTF-8 code page
|
||||
kernel32.SetConsoleCP(65001)
|
||||
|
||||
# Reconfigure stdout/stderr as UTF-8 text streams
|
||||
if sys.stdout.encoding != 'utf-8':
|
||||
sys.stdout = io.TextIOWrapper(
|
||||
sys.stdout.buffer,
|
||||
encoding='utf-8',
|
||||
errors='replace'
|
||||
)
|
||||
if sys.stderr.encoding != 'utf-8':
|
||||
sys.stderr = io.TextIOWrapper(
|
||||
sys.stderr.buffer,
|
||||
encoding='utf-8',
|
||||
errors='replace'
|
||||
)
|
||||
|
||||
# 设置环境变量,确保 Python 使用 UTF-8
|
||||
os.environ.setdefault('PYTHONIOENCODING', 'utf-8')
|
||||
except Exception as e:
|
||||
# 记录警告但不中断程序
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.warning(f"Failed to enable Windows UTF-8 mode: {e}")
|
||||
|
||||
|
||||
def normalize_windows_path(path: str) -> Path:
|
||||
"""
|
||||
Normalize a path for Windows compatibility.
|
||||
|
||||
Converts forward slashes to backslashes and resolves
|
||||
environment variables.
|
||||
|
||||
Args:
|
||||
path: Path string to normalize (can also be a Path object)
|
||||
|
||||
Returns:
|
||||
Normalized Path object
|
||||
"""
|
||||
if isinstance(path, Path):
|
||||
return path
|
||||
|
||||
path_str = str(path)
|
||||
|
||||
if sys.platform != "win32":
|
||||
return Path(path_str)
|
||||
|
||||
# Convert forward slashes to backslashes
|
||||
path_str = path_str.replace('/', '\\')
|
||||
|
||||
# Expand environment variables
|
||||
path_str = os.path.expandvars(path_str)
|
||||
|
||||
# Return as Path object
|
||||
return Path(path_str)
|
||||
|
||||
|
||||
def get_system_encoding() -> str:
|
||||
"""Get the system encoding."""
|
||||
if sys.platform == "win32":
|
||||
import ctypes
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
return f"cp{kernel32.GetConsoleCP()}"
|
||||
return sys.getdefaultencoding()
|
||||
|
||||
|
||||
def ensure_directory_exists(path: str) -> bool:
|
||||
"""
|
||||
Ensure a directory exists, creating it if necessary.
|
||||
|
||||
Args:
|
||||
path: Directory path
|
||||
|
||||
Returns:
|
||||
True if directory exists or was created successfully
|
||||
"""
|
||||
try:
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
Reference in New Issue
Block a user