| 225 | } |
| 226 | |
| 227 | void initPython(EnergyPlusData &state, fs::path const &pathToPythonPackages) |
| 228 | { |
| 229 | PyStatus status; |
| 230 | |
| 231 | // first pre-config Python so that it can speak UTF-8 |
| 232 | PyPreConfig preConfig; |
| 233 | // This is the other related line that caused Decent CI to start having trouble. I'm putting it back to |
| 234 | // PyPreConfig_InitPythonConfig, even though I think it should be isolated. Will deal with this after IO freeze. |
| 235 | PyPreConfig_InitPythonConfig(&preConfig); |
| 236 | // PyPreConfig_InitIsolatedConfig(&preConfig); |
| 237 | preConfig.utf8_mode = 1; |
| 238 | status = Py_PreInitialize(&preConfig); |
| 239 | if (PyStatus_Exception(status) != 0) { |
| 240 | ShowFatalError(state, EnergyPlus::format("Could not pre-initialize Python to speak UTF-8... {}", status)); |
| 241 | } |
| 242 | |
| 243 | PyConfig config; |
| 244 | PyConfig_InitIsolatedConfig(&config); |
| 245 | config.isolated = 1; |
| 246 | |
| 247 | status = PyConfig_SetBytesString(&config, &config.program_name, PluginManagement::programName); |
| 248 | if (PyStatus_Exception(status) != 0) { |
| 249 | ShowFatalError(state, EnergyPlus::format("Could not initialize program_name on PyConfig... {}", status)); |
| 250 | } |
| 251 | |
| 252 | status = PyConfig_Read(&config); |
| 253 | if (PyStatus_Exception(status) != 0) { |
| 254 | ShowFatalError(state, EnergyPlus::format("Could not read back the PyConfig... {}", status)); |
| 255 | } |
| 256 | |
| 257 | if constexpr (std::is_same_v<typename fs::path::value_type, wchar_t>) { |
| 258 | // PyConfig_SetString copies the wide character string str into *config_str. |
| 259 | std::wstring const ws = pathToPythonPackages.generic_wstring(); |
| 260 | const wchar_t *wcharPath = ws.c_str(); |
| 261 | |
| 262 | status = PyConfig_SetString(&config, &config.home, wcharPath); |
| 263 | if (PyStatus_Exception(status) != 0) { |
| 264 | ShowFatalError(state, |
| 265 | EnergyPlus::format("Could not set home to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); |
| 266 | } |
| 267 | status = PyConfig_SetString(&config, &config.base_prefix, wcharPath); |
| 268 | if (PyStatus_Exception(status) != 0) { |
| 269 | ShowFatalError( |
| 270 | state, EnergyPlus::format("Could not set base_prefix to {} on PyConfig... {}", pathToPythonPackages.generic_string(), status)); |
| 271 | } |
| 272 | config.module_search_paths_set = 1; |
| 273 | status = PyWideStringList_Append(&config.module_search_paths, wcharPath); |
| 274 | if (PyStatus_Exception(status) != 0) { |
| 275 | ShowFatalError( |
| 276 | state, |
| 277 | EnergyPlus::format("Could not add {} to module_search_paths on PyConfig... {}", pathToPythonPackages.generic_string(), status)); |
| 278 | } |
| 279 | |
| 280 | } else { |
| 281 | // PyConfig_SetBytesString takes a `const char * str` and decodes str using Py_DecodeLocale() and set the result into *config_str |
| 282 | // But we want to avoid doing it three times, so we PyDecodeLocale manually |
| 283 | // Py_DecodeLocale can be called because Python has been PreInitialized. |
| 284 | wchar_t *wcharPath = Py_DecodeLocale(pathToPythonPackages.generic_string().c_str(), nullptr); // This allocates! |
no test coverage detected