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
+33 -26
View File
@@ -7,6 +7,7 @@ import zipfile
from datetime import datetime
import requests
from pathlib import Path
from tqdm import tqdm
from werkzeug.utils import secure_filename
@@ -16,7 +17,7 @@ logger = logging.getLogger()
class JobImportHandler:
@classmethod
def validate_job_data(cls, new_job_data, upload_directory, uploaded_file=None):
def validate_job_data(cls, new_job_data: dict, upload_directory: Path, uploaded_file=None) -> dict:
loaded_project_local_path = None
# check for required keys
@@ -44,27 +45,34 @@ class JobImportHandler:
# Prepare the local filepath
cleaned_path_name = job_name.replace(' ', '-')
job_dir = os.path.join(upload_directory, '-'.join(
[cleaned_path_name, engine_name, datetime.now().strftime("%Y.%m.%d_%H.%M.%S")]))
timestamp = datetime.now().strftime("%Y.%m.%d_%H.%M.%S")
folder_name = f"{cleaned_path_name}-{engine_name}-{timestamp}"
job_dir = Path(upload_directory) / folder_name
os.makedirs(job_dir, exist_ok=True)
project_source_dir = os.path.join(job_dir, 'source')
project_source_dir = Path(job_dir) / 'source'
os.makedirs(project_source_dir, exist_ok=True)
# Move projects to their work directories
if uploaded_file and uploaded_file.filename:
loaded_project_local_path = os.path.join(project_source_dir, secure_filename(uploaded_file.filename))
uploaded_file.save(loaded_project_local_path)
logger.info(f"Transfer complete for {loaded_project_local_path.split(upload_directory)[-1]}")
elif project_url:
loaded_project_local_path = os.path.join(project_source_dir, referred_name)
shutil.move(downloaded_file_url, loaded_project_local_path)
logger.info(f"Download complete for {loaded_project_local_path.split(upload_directory)[-1]}")
elif local_path:
loaded_project_local_path = os.path.join(project_source_dir, referred_name)
shutil.copy(local_path, loaded_project_local_path)
logger.info(f"Import complete for {loaded_project_local_path.split(upload_directory)[-1]}")
# Handle file uploading
filename = secure_filename(uploaded_file.filename)
loaded_project_local_path = Path(project_source_dir) / filename
uploaded_file.save(str(loaded_project_local_path))
logger.info(f"Transfer complete for {loaded_project_local_path.relative_to(upload_directory)}")
if loaded_project_local_path.lower().endswith('.zip'):
elif project_url:
# Handle downloading project from a URL
loaded_project_local_path = Path(project_source_dir) / referred_name
shutil.move(str(downloaded_file_url), str(loaded_project_local_path))
logger.info(f"Download complete for {loaded_project_local_path.relative_to(upload_directory)}")
elif local_path:
# Handle local files
loaded_project_local_path = Path(project_source_dir) / referred_name
shutil.copy(str(local_path), str(loaded_project_local_path))
logger.info(f"Import complete for {loaded_project_local_path.relative_to(upload_directory)}")
if loaded_project_local_path.suffix == ".zip":
loaded_project_local_path = cls.process_zipped_project(loaded_project_local_path)
new_job_data["__loaded_project_local_path"] = loaded_project_local_path
@@ -72,7 +80,7 @@ class JobImportHandler:
return new_job_data
@staticmethod
def download_project_from_url(project_url):
def download_project_from_url(project_url: str):
# This nested function is to handle downloading from a URL
logger.info(f"Downloading project from url: {project_url}")
referred_name = os.path.basename(project_url)
@@ -101,7 +109,7 @@ class JobImportHandler:
return None, None
@staticmethod
def process_zipped_project(zip_path):
def process_zipped_project(zip_path: Path) -> Path:
"""
Processes a zipped project.
@@ -109,22 +117,21 @@ class JobImportHandler:
If the zip file contains more than one project file or none, an error is raised.
Args:
zip_path (str): The path to the zip file.
zip_path (Path): The path to the zip file.
Raises:
ValueError: If there's more than 1 project file or none in the zip file.
Returns:
str: The path to the main project file.
Path: The path to the main project file.
"""
work_path = os.path.dirname(zip_path)
work_path = zip_path.parent
try:
with zipfile.ZipFile(zip_path, 'r') as myzip:
myzip.extractall(work_path)
myzip.extractall(str(work_path))
project_files = [x for x in os.listdir(work_path) if os.path.isfile(os.path.join(work_path, x))]
project_files = [x for x in project_files if '.zip' not in x]
project_files = [p for p in work_path.iterdir() if p.is_file() and p.suffix.lower() != ".zip"]
logger.debug(f"Zip files: {project_files}")
@@ -134,9 +141,9 @@ class JobImportHandler:
# If there's more than 1 project file or none, raise an error
if len(project_files) != 1:
raise ValueError(f'Cannot find a valid project file in {os.path.basename(zip_path)}')
raise ValueError(f'Cannot find a valid project file in {zip_path.name}')
extracted_project_path = os.path.join(work_path, project_files[0])
extracted_project_path = work_path / project_files[0]
logger.info(f"Extracted zip file to {extracted_project_path}")
except (zipfile.BadZipFile, zipfile.LargeZipFile) as e: