Windows path fixes (#129)

* Change uses of os.path to use Pathlib

* Add return types and type hints

* Add more docstrings

* Add missing import to api_server
This commit is contained in:
2026-01-18 00:18:43 -06:00
committed by GitHub
parent ee9f44e4c4
commit 74dce5cc3d
15 changed files with 536 additions and 262 deletions

View File

@@ -1,4 +1,6 @@
import os
from pathlib import Path
import yaml
from src.utilities.misc_helper import current_system_os, copy_directory_contents
@@ -23,7 +25,7 @@ class Config:
with open(config_path, 'r') as ymlfile:
cfg = yaml.safe_load(ymlfile)
cls.upload_folder = os.path.expanduser(cfg.get('upload_folder', cls.upload_folder))
cls.upload_folder = str(Path(cfg.get('upload_folder', cls.upload_folder)).expanduser())
cls.update_engines_on_launch = cfg.get('update_engines_on_launch', cls.update_engines_on_launch)
cls.max_content_path = cfg.get('max_content_path', cls.max_content_path)
cls.server_log_level = cfg.get('server_log_level', cls.server_log_level)
@@ -37,14 +39,14 @@ class Config:
cls.download_timeout_seconds = cfg.get('download_timeout_seconds', cls.download_timeout_seconds)
@classmethod
def config_dir(cls):
def config_dir(cls) -> Path:
# Set up the config path
if current_system_os() == 'macos':
local_config_path = os.path.expanduser('~/Library/Application Support/Zordon')
local_config_path = Path('~/Library/Application Support/Zordon').expanduser()
elif current_system_os() == 'windows':
local_config_path = os.path.join(os.environ['APPDATA'], 'Zordon')
local_config_path = Path(os.environ['APPDATA']) / 'Zordon'
else:
local_config_path = os.path.expanduser('~/.config/Zordon')
local_config_path = Path('~/.config/Zordon').expanduser()
return local_config_path
@classmethod
@@ -61,10 +63,9 @@ class Config:
# Determine the template path
resource_environment_path = os.environ.get('RESOURCEPATH')
if resource_environment_path:
template_path = os.path.join(resource_environment_path, 'config')
template_path = Path(resource_environment_path) / 'config'
else:
template_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'config')
template_path = Path(__file__).resolve().parents[2] / 'config'
# Copy contents from the template to the local configuration directory
copy_directory_contents(template_path, local_config_dir)

View File

@@ -9,11 +9,12 @@ import string
import subprocess
import sys
from datetime import datetime
from typing import Optional, List, Dict, Any
logger = logging.getLogger()
def launch_url(url):
def launch_url(url: str) -> None:
logger = logging.getLogger(__name__)
if shutil.which('xdg-open'):
@@ -37,7 +38,7 @@ def launch_url(url):
logger.error(f"Failed to launch URL: {url}. Error: {e}")
def file_exists_in_mounts(filepath):
def file_exists_in_mounts(filepath: str) -> Optional[str]:
"""
Check if a file exists in any mounted directory.
It searches for the file in common mount points like '/Volumes', '/mnt', and '/media'.
@@ -78,7 +79,7 @@ def file_exists_in_mounts(filepath):
return possible_mount_path
def get_time_elapsed(start_time=None, end_time=None):
def get_time_elapsed(start_time: Optional[datetime] = None, end_time: Optional[datetime] = None) -> str:
def strfdelta(tdelta, fmt='%H:%M:%S'):
days = tdelta.days
@@ -105,7 +106,7 @@ def get_time_elapsed(start_time=None, end_time=None):
return elapsed_time_string
def get_file_size_human(file_path):
def get_file_size_human(file_path: str) -> str:
size_in_bytes = os.path.getsize(file_path)
# Convert size to a human-readable format
@@ -121,26 +122,19 @@ def get_file_size_human(file_path):
return f"{size_in_bytes / 1024 ** 4:.2f} TB"
# Convert path to the appropriate format for the current platform
def system_safe_path(path):
if platform.system().lower() == "windows":
return os.path.normpath(path)
return path.replace("\\", "/")
def current_system_os():
def current_system_os() -> str:
return platform.system().lower().replace('darwin', 'macos')
def current_system_os_version():
return platform.mac_ver()[0] if current_system_os() == 'macos' else platform.release().lower()
def current_system_os_version() -> str:
return platform.release()
def current_system_cpu():
# convert all x86 64 to "x64"
return platform.machine().lower().replace('amd64', 'x64').replace('x86_64', 'x64')
def current_system_cpu() -> str:
return platform.machine().lower().replace('amd64', 'x64')
def current_system_cpu_brand():
def current_system_cpu_brand() -> str:
"""Fast cross-platform CPU brand string"""
if sys.platform.startswith('darwin'): # macOS
try:
@@ -175,28 +169,21 @@ def current_system_cpu_brand():
# Ultimate fallback
return platform.processor() or 'Unknown CPU'
def resources_dir():
resource_environment_path = os.environ.get('RESOURCEPATH', None)
if resource_environment_path: # running inside resource bundle
return os.path.join(resource_environment_path, 'resources')
else:
return os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'resources')
def resources_dir() -> str:
return os.path.join(os.path.dirname(__file__), '..', '..', 'resources')
def copy_directory_contents(src_dir, dst_dir):
"""
Copy the contents of the source directory (src_dir) to the destination directory (dst_dir).
"""
def copy_directory_contents(src_dir: str, dst_dir: str) -> None:
for item in os.listdir(src_dir):
src_path = os.path.join(src_dir, item)
dst_path = os.path.join(dst_dir, item)
if os.path.isdir(src_path):
shutil.copytree(src_path, dst_path, dirs_exist_ok=True)
shutil.copytree(src_path, dst_path)
else:
shutil.copy2(src_path, dst_path)
def check_for_updates(repo_name, repo_owner, app_name, current_version):
def check_for_updates(repo_name: str, repo_owner: str, app_name: str, current_version: str) -> Optional[Dict[str, Any]]:
def get_github_releases(owner, repo):
import requests
url = f"https://api.github.com/repos/{owner}/{repo}/releases"
@@ -223,33 +210,15 @@ def check_for_updates(repo_name, repo_owner, app_name, current_version):
return latest_version
return None
def is_localhost(comparison_hostname):
# this is necessary because socket.gethostname() does not always include '.local' - This is a sanitized comparison
try:
comparison_hostname = comparison_hostname.lower().replace('.local', '')
local_hostname = socket.gethostname().lower().replace('.local', '')
return comparison_hostname == local_hostname
except AttributeError:
return False
def is_localhost(comparison_hostname: str) -> bool:
return comparison_hostname in ['localhost', '127.0.0.1', socket.gethostname()]
def num_to_alphanumeric(num):
# List of possible alphanumeric characters
characters = string.ascii_letters + string.digits
# Make sure number is positive
num = abs(num)
# Convert number to alphanumeric
result = ""
while num > 0:
num, remainder = divmod(num, len(characters))
result += characters[remainder]
return result[::-1] # Reverse the result to get the correct alphanumeric string
def num_to_alphanumeric(num: int) -> str:
return string.ascii_letters[num % 26] + str(num // 26)
def get_gpu_info():
def get_gpu_info() -> List[Dict[str, Any]]:
"""Cross-platform GPU information retrieval"""
def get_windows_gpu_info():