From e5e649ce9c816dae76b12b9df614d0f63d6920a7 Mon Sep 17 00:00:00 2001
From: Lars Bilke <lars.bilke@ufz.de>
Date: Thu, 15 Aug 2024 14:53:58 +0200
Subject: [PATCH 1/3] [py] ogs.callbacks-module is only used in wheels.

---
 Applications/Python/CMakeLists.txt | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt
index 6d0f1171608..b15a9c06c75 100644
--- a/Applications/Python/CMakeLists.txt
+++ b/Applications/Python/CMakeLists.txt
@@ -11,12 +11,14 @@ endif()
 add_subdirectory(ogs)
 add_subdirectory(ogs.simulator)
 add_subdirectory(ogs.mesh)
-add_subdirectory(ogs.callbacks)
+if(OGS_BUILD_WHEEL)
+    add_subdirectory(ogs.callbacks)
+endif()
 
 if(OGS_USE_PIP)
     set_target_properties(
-        simulator mesh callbacks PROPERTIES LIBRARY_OUTPUT_DIRECTORY
-                                            ${_py_build_location}
+        simulator mesh PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+                                  ${_py_build_location}
     )
     file(
         COPY ogs/.

From 38989b7c8a09812c47c35277c7c9e5d058d3dbc8 Mon Sep 17 00:00:00 2001
From: Lars Bilke <lars.bilke@ufz.de>
Date: Thu, 15 Aug 2024 14:56:54 +0200
Subject: [PATCH 2/3] [py] Added error message when trying to import
 ogs.callbacks from the embedded interpreter.

This can happen if you have the ogs-wheel installed but are running a local ogs binary. In this case use `import OpenGeoSys` or uninstall the wheel.
---
 .../Python/ogs.callbacks/ogs_callbacks_module.cpp    | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Applications/Python/ogs.callbacks/ogs_callbacks_module.cpp b/Applications/Python/ogs.callbacks/ogs_callbacks_module.cpp
index c2e0789138c..45b1bfedbef 100644
--- a/Applications/Python/ogs.callbacks/ogs_callbacks_module.cpp
+++ b/Applications/Python/ogs.callbacks/ogs_callbacks_module.cpp
@@ -8,9 +8,11 @@
  *
  */
 
-#include <algorithm>
+#include <pybind11/eval.h>
 #include <pybind11/pybind11.h>
 
+#include <algorithm>
+
 #include "ProcessLib/BoundaryConditionAndSourceTerm/Python/BHEInflowPythonBoundaryConditionModule.h"
 #include "ProcessLib/BoundaryConditionAndSourceTerm/Python/PythonBoundaryConditionModule.h"
 #include "ProcessLib/BoundaryConditionAndSourceTerm/Python/PythonSourceTermModule.h"
@@ -21,4 +23,12 @@ PYBIND11_MODULE(callbacks, m)
     ProcessLib::pythonBindBoundaryCondition(m);
     ProcessLib::bheInflowpythonBindBoundaryCondition(m);
     ProcessLib::SourceTerms::Python::pythonBindSourceTerm(m);
+
+    pybind11::exec(R"(
+        try:
+            import OpenGeoSys
+            raise ImportError("The Python interpreter seems to be running inside the OGS binary, but you are about to import a Python module from OGS's Python bindings. Please do not import ogs.callbacks, but use the OpenGeoSys module, instead.")
+        except ModuleNotFoundError:
+            pass
+    )");
 }

From eaeeaf1c19197f00cd8abe9d9d4861507239a011 Mon Sep 17 00:00:00 2001
From: Lars Bilke <lars.bilke@ufz.de>
Date: Thu, 15 Aug 2024 15:06:02 +0200
Subject: [PATCH 3/3] [py] Detect activated venv at runtime in embedded
 interpreter.

Removed hard-coded build-time venv.
---
 Applications/ApplicationsLib/ProjectData.cpp |  3 ---
 Applications/CLI/ogs_embedded_python.cpp     | 16 +++++++++++++++-
 InfoLib/CMakeInfo.cpp.in                     |  1 -
 InfoLib/CMakeInfo.h                          |  1 -
 4 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/Applications/ApplicationsLib/ProjectData.cpp b/Applications/ApplicationsLib/ProjectData.cpp
index f9c14720486..0d542c996a5 100644
--- a/Applications/ApplicationsLib/ProjectData.cpp
+++ b/Applications/ApplicationsLib/ProjectData.cpp
@@ -367,9 +367,6 @@ ProjectData::ProjectData(BaseLib::ConfigTree const& project_config,
         // Append to python's module search path
         auto py_path = py::module::import("sys").attr("path");
         py_path.attr("append")(script_directory);  // .prj or -s directory
-        // virtualenv
-        py_path.attr("append")(
-            CMakeInfoLib::CMakeInfo::python_virtualenv_sitepackages);
 
         auto const script_path =
             BaseLib::copyPathToFileName(*python_script, script_directory);
diff --git a/Applications/CLI/ogs_embedded_python.cpp b/Applications/CLI/ogs_embedded_python.cpp
index 1a16f5afb3d..dc7946f9d1e 100644
--- a/Applications/CLI/ogs_embedded_python.cpp
+++ b/Applications/CLI/ogs_embedded_python.cpp
@@ -10,9 +10,10 @@
 
 #include "ogs_embedded_python.h"
 
-#include <algorithm>
 #include <pybind11/embed.h>
 
+#include <algorithm>
+
 #include "BaseLib/Logging.h"
 #include "ProcessLib/BoundaryConditionAndSourceTerm/Python/BHEInflowPythonBoundaryConditionModule.h"
 #include "ProcessLib/BoundaryConditionAndSourceTerm/Python/PythonBoundaryConditionModule.h"
@@ -25,6 +26,19 @@ PYBIND11_EMBEDDED_MODULE(OpenGeoSys, m)
     ProcessLib::pythonBindBoundaryCondition(m);
     ProcessLib::bheInflowpythonBindBoundaryCondition(m);
     ProcessLib::SourceTerms::Python::pythonBindSourceTerm(m);
+
+    // Check for activated virtual environment and add it to sys.path
+    pybind11::exec(R"(
+        import os
+        import sys
+        if "VIRTUAL_ENV" in os.environ:
+            venv_site_packages_path = f"{os.environ['VIRTUAL_ENV']}/lib/python{sys.version_info.major}.{sys.version_info.minor}/site-packages"
+            if os.path.exists(venv_site_packages_path):
+                print(
+                    f"Virtual environment detected, adding {venv_site_packages_path} to sys.path."
+                )
+                sys.path.insert(0, venv_site_packages_path)
+    )");
 }
 
 #ifndef OGS_BUILD_SHARED_LIBS
diff --git a/InfoLib/CMakeInfo.cpp.in b/InfoLib/CMakeInfo.cpp.in
index 2a600268fc1..a0b292ed959 100644
--- a/InfoLib/CMakeInfo.cpp.in
+++ b/InfoLib/CMakeInfo.cpp.in
@@ -17,7 +17,6 @@ namespace CMakeInfoLib
 
 namespace CMakeInfo
 {
-const std::string python_virtualenv_sitepackages("@Python_SITEARCH_NATIVE@");
 const std::string cmake_args("@CMAKE_ARGS_ESCAPED@");
 }  // namespace CMakeInfo
 }  // namespace CMakeInfoLib
diff --git a/InfoLib/CMakeInfo.h b/InfoLib/CMakeInfo.h
index db27c0236d0..93b335821d1 100644
--- a/InfoLib/CMakeInfo.h
+++ b/InfoLib/CMakeInfo.h
@@ -21,7 +21,6 @@ namespace CMakeInfoLib
 
 namespace CMakeInfo
 {
-extern CMAKEINFOLIB_EXPORT const std::string python_virtualenv_sitepackages;
 extern CMAKEINFOLIB_EXPORT const std::string cmake_args;
 }  // namespace CMakeInfo
 }  // namespace CMakeInfoLib