Skip to content

EOF errors in Airfoil templates on MacOS #169

@ffelten

Description

@ffelten

How to reproduce: Run airfoil/v0.py on Mac.
Workaround: Run the script 2 times (one to create the folder, one to execute).

Problem

Likely linked to MacOS.

When I create a new Airfoil study (execute v0.py), I have an EOF error like:

File "/home/mdolabuser/mount/engibench/engibench_studies/problems/airfoil/study_0/airfoil_analysis.py", line 208
    
SyntaxError: unexpected EOF while parsing

Note: this file is mounted and executed inside the Docker container.

Now, we I re-run the same code and directory study_0 already exists on my machine, the EOF goes away. I think this is linked to some file system caching, and the Docker container does not see the latest version.

@fgvangessel-umd did you encounter something similar?

Things I've tried

I have tried this in files.py (look for HERE HERE HERE HERE comments in the code below). Does not seem to work.

"""Utility functions for file operations."""

import os
from pathlib import Path
import shutil
from string import Template
import time
from typing import Any


def _create_study_dir(study_dir: str) -> None:
    """Create a directory for the study.

    Args:
        study_dir (str): Path to the study directory.

    """
    print(f"Creating study directory: {study_dir}")
    if not os.path.exists(study_dir):
        os.makedirs(study_dir)


def clone_dir(source_dir: str, target_dir: str) -> None:
    """Clone the source directory to the study directory.

    Args:
        source_dir (str): Path to the source directory.
        target_dir (str): Path to the target directory.

    """
    if not os.path.exists(source_dir):
        msg = f"Source directory does not exist: {source_dir}"
        raise FileNotFoundError(msg)

    _create_study_dir(target_dir)
    print(f"Copying files from {source_dir} to {target_dir}")

    try:
        for root, _, files in os.walk(source_dir):
            for file in files:
                file_path = os.path.join(root, file)
                rel_path = os.path.relpath(file_path, source_dir)
                study_file_path = os.path.join(target_dir, rel_path)

                try:
                    if not os.path.exists(os.path.dirname(study_file_path)):
                        os.makedirs(os.path.dirname(study_file_path))
                    # touch the file to force sync to disk
                    Path(study_file_path).touch()
                    # Use shutil.copy2 to preserve metadata including permissions
                    shutil.copy2(file_path, study_file_path)
                    with open(study_file_path, "rb") as f:  # Force sync to disk HERE HERE HERE HERE
                        f.flush()
                        os.fsync(f.fileno())
                except OSError as e:
                    msg = f"Failed to copy file {file_path} to {study_file_path}: {e!s}"
                    raise RuntimeError(msg) from e
        time.sleep(1.5) # HERE HERE HERE HERE
    except Exception as e:
        msg = f"Failed to clone directory from {source_dir} to {target_dir}: {e!s}"
        raise RuntimeError(msg) from e


def replace_template_values(template_fname: str, values: dict[str, Any]) -> None:
    """Replace values in a template file.

    Args:
        template_fname (str): Path to the template file.
        values (dict[str, Any]): Dictionary with the values to replace.
    """
    if not os.path.exists(template_fname):
        msg = f"Template file does not exist: {template_fname}"
        raise FileNotFoundError(msg)

    try:
        with open(template_fname) as f:
            template = Template(f.read())
            try:
                content = template.substitute(values)
            except KeyError as e:
                msg = f"Missing required template value: {e}"
                raise ValueError(msg) from e
            except ValueError as e:
                msg = f"Invalid template value: {e}"
                raise ValueError(msg) from e

        with open(template_fname, "w") as f:
            f.write(content)
            f.flush()  # Force sync to disk HERE HERE HERE HERE 
            os.fsync(f.fileno())
    except OSError as e:
        msg = f"Failed to process template file {template_fname}: {e!s}"
        raise RuntimeError(msg) from e

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions