From 91a53e2aa2b56d52112858e3d1abbb0f7c5184c3 Mon Sep 17 00:00:00 2001
From: Hartikainen Ari <ari.hartikainen@aalto.fi>
Date: Sat, 2 Feb 2019 11:00:30 +0200
Subject: [PATCH 1/5] fix stdout and stderr on windows and tempfolder

---
 httpstan/models.py | 60 +++++++++++++++++++++++++++++++---------------
 1 file changed, 41 insertions(+), 19 deletions(-)

diff --git a/httpstan/models.py b/httpstan/models.py
index 2e50686b6..10cfae9c5 100644
--- a/httpstan/models.py
+++ b/httpstan/models.py
@@ -12,6 +12,7 @@
 import os
 import pathlib
 import platform
+import shutil
 import string
 import sys
 import tempfile
@@ -31,6 +32,18 @@
 logger = logging.getLogger("httpstan")
 
 
+class TemporaryDirectory(tempfile.TemporaryDirectory):
+    """Patch TemporaryDirectory to ignore errors."""
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+    def cleanup(self):
+        """Ignore errors"""
+        if self._finalizer.detach():
+            shutil.rmtree(self.name, ignore_errors=True)
+
+
 def calculate_model_name(program_code: str) -> str:
     """Calculate model name from Stan program code.
 
@@ -152,7 +165,7 @@ def import_model_extension_module(model_name: str, module_bytes: bytes):
     module_filename = f"{module_name}.so"
     assert isinstance(module_bytes, bytes)
 
-    with tempfile.TemporaryDirectory() as temporary_directory:
+    with TemporaryDirectory() as temporary_directory:
         with open(os.path.join(temporary_directory, module_filename), "wb") as fh:
             fh.write(module_bytes)
         module_path = temporary_directory
@@ -193,21 +206,20 @@ def _build_extension_module(
     """
     # write files need for compilation in a temporary directory which will be
     # removed when this function exits.
-    with tempfile.TemporaryDirectory() as temporary_dir:
-        temporary_dir_path = pathlib.Path(temporary_dir)
-        cpp_filepath = temporary_dir_path / f"{module_name}.hpp"
-        pyx_filepath = temporary_dir_path / f"{module_name}.pyx"
+    with TemporaryDirectory() as temporary_dir:
+        temporary_dir = pathlib.Path(temporary_dir)
+        cpp_filepath = temporary_dir / f"{module_name}.hpp"
+        pyx_filepath = temporary_dir / f"{module_name}.pyx"
         pyx_code = string.Template(pyx_code_template).substitute(
             cpp_filename=cpp_filepath.as_posix()
         )
         for filepath, code in zip([cpp_filepath, pyx_filepath], [cpp_code, pyx_code]):
             with open(filepath, "w") as fh:
                 fh.write(code)
-
         httpstan_dir = os.path.dirname(__file__)
         include_dirs = [
             httpstan_dir,  # for queue_writer.hpp and queue_logger.hpp
-            temporary_dir_path.as_posix(),
+            temporary_dir.as_posix(),
             os.path.join(httpstan_dir, "lib", "stan", "src"),
             os.path.join(httpstan_dir, "lib", "stan", "lib", "stan_math"),
             os.path.join(httpstan_dir, "lib", "stan", "lib", "stan_math", "lib", "eigen_3.3.3"),
@@ -261,12 +273,18 @@ def _redirect_stdout() -> int:
             orig_stderr: copy of original stderr file descriptor
             """
             sys.stdout.flush()
-            stdout_fileno = sys.stdout.fileno()
-            orig_stdout = os.dup(stdout_fileno)
-            devnull = os.open(os.devnull, os.O_WRONLY)
-            os.dup2(devnull, stdout_fileno)
-            os.close(devnull)
-            return orig_stdout
+            if platform.system() == "Windows":
+                orig_stdout = sys.stdout
+                devnull = open(os.devnull, "w")
+                sys.stdout = devnull
+                return orig_stdout, devnull
+            else:
+                stdout_fileno = sys.stdout.fileno()
+                orig_stdout = os.dup(stdout_fileno)
+                devnull = os.open(os.devnull, os.O_WRONLY)
+                os.dup2(devnull, stdout_fileno)
+                os.close(devnull)
+                return orig_stdout
 
         def _redirect_stderr_to(stream: IO[Any]) -> int:
             """Redirect stderr for subprocesses to /dev/null.
@@ -289,12 +307,11 @@ def _redirect_stderr_to(stream: IO[Any]) -> int:
         if redirect_stderr:
             orig_stdout = _redirect_stdout()
             orig_stderr = _redirect_stderr_to(stream)
-
         try:
             build_extension.extensions = Cython.Build.cythonize(
                 [extension], include_path=cython_include_path
             )
-            build_extension.build_temp = build_extension.build_lib = temporary_dir_path.as_posix()
+            build_extension.build_temp = build_extension.build_lib = temporary_dir.as_posix()
             build_extension.run()
         finally:
             if redirect_stderr:
@@ -303,9 +320,14 @@ def _redirect_stderr_to(stream: IO[Any]) -> int:
                 stream.close()
                 # restore
                 os.dup2(orig_stderr, sys.stderr.fileno())
-                os.dup2(orig_stdout, sys.stdout.fileno())
-
+                if platform.system() == "Windows":
+                    orig_stdout, devnull = orig_stdout
+                    sys.stdout = orig_stdout
+                    devnull.close()
+                else:
+                    os.dup2(orig_stderr, sys.stderr.fileno())
         module = _import_module(module_name, build_extension.build_lib)
+        assert module.__name__ == module_name, (module.__name__, module_name)
         with open(module.__file__, "rb") as fh:  # type: ignore  # see mypy#3062
-            assert module.__name__ == module_name, (module.__name__, module_name)
-            return fh.read(), compiler_output  # type: ignore  # see mypy#3062
+            module_bytes = fh.read()  # type: ignore  # see mypy#3062
+    return module_bytes, compiler_output

From 44bc380a59957cc23f2d9ef6c60d29bdfd06b2c6 Mon Sep 17 00:00:00 2001
From: Ari Hartikainen <ahartikainen@users.noreply.github.com>
Date: Sun, 3 Feb 2019 15:06:05 +0200
Subject: [PATCH 2/5] Keep tempfolder open.

---
 httpstan/models.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/httpstan/models.py b/httpstan/models.py
index 10cfae9c5..bc8beab2f 100644
--- a/httpstan/models.py
+++ b/httpstan/models.py
@@ -330,4 +330,4 @@ def _redirect_stderr_to(stream: IO[Any]) -> int:
         assert module.__name__ == module_name, (module.__name__, module_name)
         with open(module.__file__, "rb") as fh:  # type: ignore  # see mypy#3062
             module_bytes = fh.read()  # type: ignore  # see mypy#3062
-    return module_bytes, compiler_output
+        return module_bytes, compiler_output

From 52a8cb6c51472423beed51d35672bac38ccc16d2 Mon Sep 17 00:00:00 2001
From: Allen Riddell <riddella+stan@indiana.edu>
Date: Mon, 4 Mar 2019 12:38:54 -0500
Subject: [PATCH 3/5] WIP actually test something

---
 .appveyor.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.appveyor.yml b/.appveyor.yml
index 80c1c9610..9153217af 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -37,5 +37,4 @@ build: false
 test_script:
   - mkdir empty_folder
   - cd empty_folder
-  # eventually `- python -m pytest ../tests`
-  - python -c "import httpstan"
+  - python -m pytest ../tests/test_bernoulli.py

From 4cb66e75911e940d392f03c3200d1cbe7291c24a Mon Sep 17 00:00:00 2001
From: Allen Riddell <riddella+stan@indiana.edu>
Date: Mon, 4 Mar 2019 15:53:27 -0500
Subject: [PATCH 4/5] wip try adding -static

---
 httpstan/models.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/httpstan/models.py b/httpstan/models.py
index bc8beab2f..f736351e8 100644
--- a/httpstan/models.py
+++ b/httpstan/models.py
@@ -242,6 +242,7 @@ def _build_extension_module(
             if platform.system() == "Windows":
                 # -D_hypot=hypot, MinGW fix, https://github.com/python/cpython/pull/11283
                 extra_compile_args.append("-D_hypot=hypot")
+                extra_compile_args.append("-static")
 
         cython_include_path = [os.path.dirname(httpstan_dir)]
         extension = setuptools.Extension(

From 1e181e2c2eea7e1d08dbfadcf8d460983cc43923 Mon Sep 17 00:00:00 2001
From: Allen Riddell <riddella+stan@indiana.edu>
Date: Mon, 4 Mar 2019 16:29:02 -0500
Subject: [PATCH 5/5] WIP try -static-libgcc

---
 httpstan/models.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/httpstan/models.py b/httpstan/models.py
index f736351e8..c48d49170 100644
--- a/httpstan/models.py
+++ b/httpstan/models.py
@@ -242,7 +242,7 @@ def _build_extension_module(
             if platform.system() == "Windows":
                 # -D_hypot=hypot, MinGW fix, https://github.com/python/cpython/pull/11283
                 extra_compile_args.append("-D_hypot=hypot")
-                extra_compile_args.append("-static")
+                extra_compile_args.append("-static-libgcc")
 
         cython_include_path = [os.path.dirname(httpstan_dir)]
         extension = setuptools.Extension(
