Skip to content

Commit 2eda47f

Browse files
committed
Merge remote-tracking branch 'upstream/master' into pr-add-createobject-behavior
2 parents 33a34c1 + cfd8709 commit 2eda47f

30 files changed

+317
-113
lines changed

.github/workflows/macos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
os: [macos-10.15]
16-
sofa_branch: [master, v21.06]
16+
sofa_branch: [master]
1717
env:
1818
SOFA_ROOT: /opt/sofa
1919
SOFA_OS: MacOS

.github/workflows/ubuntu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
os: [ubuntu-20.04]
16-
sofa_branch: [master, v21.06]
16+
sofa_branch: [master]
1717
env:
1818
SOFA_ROOT: /opt/sofa
1919
SOFA_OS: Linux

Plugin/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ add_library(SofaPython3::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
4848

4949
target_compile_definitions(${PROJECT_NAME} PRIVATE "-DSOFA_BUILD_SOFAPYTHON3")
5050

51-
target_link_libraries(${PROJECT_NAME} PUBLIC SofaCore SofaDefaultType SofaSimulationCore SofaSimulationGraph SofaHelper)
51+
target_link_libraries(${PROJECT_NAME} PUBLIC SofaCore SofaDefaultType SofaSimulationCore SofaSimulationGraph Sofa.Helper)
5252
target_link_libraries(${PROJECT_NAME} PUBLIC pybind11::module pybind11::embed)
5353

5454
if(SP3_BUILD_TEST AND Sofa.Testing_FOUND)

Plugin/src/SofaPython3/PythonEnvironment.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,15 @@ void PythonEnvironment::Init()
233233
// Lastly, we (try to) add modules from the root of SOFA
234234
addPythonModulePathsFromDirectory( Utils::getSofaPathPrefix() );
235235

236-
py::module::import("SofaRuntime");
236+
try
237+
{
238+
py::module::import("SofaRuntime");
239+
}
240+
catch (pybind11::error_already_set)
241+
{
242+
msg_error("SofaPython3") << "Could not import SofaRuntime module, initializing python3 for SOFA is not possible";
243+
return;
244+
}
237245
getStaticData()->m_sofamodule = py::module::import("Sofa");
238246

239247

@@ -255,20 +263,43 @@ void PythonEnvironment::Init()
255263
pluginLibraryPath = elem.first;
256264
}
257265
}
266+
267+
s_isInitialized = true;
258268
}
259269

260-
void PythonEnvironment::executePython(std::function<void()> cb)
270+
// Single implementation for the three different versions
271+
template<class T>
272+
void executePython_(const T& emitter, std::function<void()> cb)
261273
{
262274
sofapython3::PythonEnvironment::gil acquire;
263275

264276
try{
265277
cb();
266-
}catch(std::exception& e)
278+
}catch(py::error_already_set& e)
267279
{
268-
msg_error("SofaPython3") << e.what() ;
280+
std::stringstream tmp;
281+
tmp << "Unable to execute code." << msgendl
282+
<< "Python exception:" << msgendl
283+
<< " " << e.what()
284+
<< PythonEnvironment::getPythonCallingPointString();
285+
msg_error(emitter) << tmp.str();
269286
}
270287
}
271288

289+
void PythonEnvironment::executePython(const std::string& emitter, std::function<void()> cb)
290+
{
291+
return executePython_(emitter, cb);
292+
}
293+
294+
void PythonEnvironment::executePython(std::function<void()> cb)
295+
{
296+
return executePython_("SofaPython3::executePython", cb);
297+
}
298+
299+
void PythonEnvironment::executePython(const sofa::core::objectmodel::Base* b, std::function<void()> cb)
300+
{
301+
return executePython_(b, cb);
302+
}
272303

273304
void PythonEnvironment::Release()
274305
{

Plugin/src/SofaPython3/PythonEnvironment.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ class SOFAPYTHON3_API PythonEnvironment
5959
static void Init();
6060
static void Release();
6161

62+
static bool isInitialized()
63+
{
64+
return s_isInitialized;
65+
};
66+
6267
static pybind11::module importFromFile(const std::string& module,
6368
const std::string& path,
6469
pybind11::object* globals = nullptr);
@@ -104,7 +109,11 @@ class SOFAPYTHON3_API PythonEnvironment
104109
/// excluding a module from automatic reload
105110
static void excludeModuleFromReload( const std::string& moduleName );
106111

107-
static void executePython(std::function<void()>);
112+
/// execute a function 'f' after acquiring the GIL and having installed
113+
/// an handler to catch python exception.
114+
static void executePython(std::function<void()> f);
115+
static void executePython(const sofa::core::objectmodel::Base* emitter, std::function<void()> f);
116+
static void executePython(const std::string& emitter, std::function<void()> cb);
108117

109118
/// to be able to react when a scene is loaded
110119
struct SceneLoaderListerner : public SceneLoader::Listener
@@ -146,6 +155,7 @@ class SOFAPYTHON3_API PythonEnvironment
146155
private:
147156
static PythonEnvironmentData* getStaticData() ;
148157
static std::string pluginLibraryPath;
158+
static inline bool s_isInitialized{false};
149159
};
150160

151161
} // namespace sofapython3

Plugin/src/SofaPython3/SceneLoaderPY3.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ void SceneLoaderPY3::loadSceneWithArguments(const char *filename,
106106

107107
py::object createScene = module.attr("createScene");
108108
createScene( PythonFactory::toPython(root_out.get()) );
109-
}catch(std::exception& e)
109+
}catch(py::error_already_set& e)
110110
{
111-
msg_error() << e.what();
111+
msg_error() << "Unable to completely load the scene from file '"<< filename << "'." << msgendl
112+
<< "Python exception: " << msgendl
113+
<< " " << e.what();
112114
}
113115

114116
}

Plugin/src/SofaPython3/initModule.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ SOFAPYTHON3_API const char* getModuleVersion();
3737
SOFAPYTHON3_API const char* getModuleLicense();
3838
SOFAPYTHON3_API const char* getModuleDescription();
3939
SOFAPYTHON3_API const char* getModuleComponentList();
40+
SOFAPYTHON3_API bool moduleIsInitialized();
4041

4142
void initExternalModule()
4243
{
@@ -80,4 +81,9 @@ const char* getModuleComponentList()
8081
return "";
8182
}
8283

84+
bool moduleIsInitialized()
85+
{
86+
return PythonEnvironment::isInitialized();
87+
}
88+
8389
}

bindings/Modules/tests/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ find_package(SofaFramework REQUIRED)
1414

1515
enable_testing()
1616
add_executable(${PROJECT_NAME} ${SOURCE_FILES} ${PYTHON_FILES})
17-
target_link_libraries(${PROJECT_NAME} SofaGTestMain SofaHelper SofaPython3::Plugin)
17+
target_link_libraries(${PROJECT_NAME} SofaGTestMain Sofa.Helper SofaPython3::Plugin)
1818
target_compile_definitions(${PROJECT_NAME} PRIVATE "PYTHON_TESTFILES_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\"")
1919
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "Bindings/Tests")
2020

bindings/Sofa/package/__init__.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,72 @@
3434
import traceback
3535
import importlib
3636

37+
print("---------------------------------------")
38+
print("Checking SOFA_ROOT and SOFAPYTHON3_ROOT")
39+
40+
# check if SOFA_ROOT has been (well) set
41+
sofa_root = os.environ.get('SOFA_ROOT')
42+
if sofa_root:
43+
print("Using environment variable SOFA_ROOT: " + sofa_root)
44+
else:
45+
print("Warning: environment variable SOFA_ROOT is empty. Trying to guess it.")
46+
# try a guess from <sofa_root>/plugins/SofaPython3/lib/python3/site-packages/Sofa
47+
sofa_root_guess = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + '/../../../../../..')
48+
if os.path.isdir(os.path.abspath(sofa_root_guess + '/lib' )):
49+
print("Guessed SOFA_ROOT: " + sofa_root_guess)
50+
sofa_root = sofa_root_guess
51+
else:
52+
print("Warning: cannot guess SOFA_ROOT",
53+
"Loading SOFA libraries will likely fail and/or SOFA won't find its resources.")
54+
55+
# check if SOFAPYTHON3_ROOT has been (well) set
56+
sofapython3_root = os.environ.get('SOFAPYTHON3_ROOT')
57+
if sofapython3_root:
58+
print("Using environment variable SOFAPYTHON3_ROOT: " + sofapython3_root)
59+
else:
60+
print("Warning: environment variable SOFAPYTHON3_ROOT is empty. Trying to guess it.")
61+
# try a guess from <sofapython3_root>/lib/python3/site-packages/Sofa
62+
sofapython3_root_guess = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + '/../../../..')
63+
if os.path.isdir(os.path.abspath(sofapython3_root_guess + '/lib' )):
64+
print("Guessed SOFAPYTHON3_ROOT: " + sofapython3_root_guess)
65+
sofapython3_root = sofapython3_root_guess
66+
else:
67+
print("Warning: cannot guess SOFAPYTHON3_ROOT",
68+
"Loading SofaPython3 modules will likely fail.")
69+
70+
if sofa_root and sys.platform == 'win32':
71+
# Windows-only: starting from python 3.8, python wont read the env. variable PATH to get SOFA's dlls.
72+
# os.add_dll_directory() is the new way to add paths for python to get external libraries.
73+
sofa_bin_path = sofa_root + "\\bin"
74+
sofa_file_test = sofa_bin_path + "\\Sofa.Helper.dll"
75+
sofapython3_bin_path = sofapython3_root + "\\bin"
76+
sofapython3_file_test = sofapython3_bin_path + "\\SofaPython3.dll"
77+
78+
if not os.path.isfile(sofa_file_test):
79+
print("Warning: environment variable SOFA_ROOT is set but seems invalid.",
80+
"Loading SOFA libraries will likely fail.")
81+
print("SOFA_ROOT is currently: " + sofa_root)
82+
if not os.path.isfile(sofapython3_file_test):
83+
print("Warning: cannot find SofaPython3.dll at path: " + sofapython3_bin_path)
84+
print("This path will NOT be added to the DLL search path.",
85+
"Loading SofaPython3 python modules will likely fail.")
86+
87+
if sys.version_info.minor >= 8:
88+
# Starting from python3.8 we need to explicitly find SOFA libraries
89+
if os.path.isfile(sofa_file_test):
90+
os.add_dll_directory(sofa_bin_path)
91+
if os.path.isfile(sofapython3_file_test):
92+
os.add_dll_directory(sofapython3_bin_path)
93+
else:
94+
# Add temporarily the bin/lib path to the env variable PATH
95+
if os.path.isfile(sofa_file_test):
96+
os.environ['PATH'] = sofa_bin_path + os.pathsep + os.environ['PATH']
97+
if os.path.isfile(sofapython3_file_test):
98+
os.environ['PATH'] = sofapython3_bin_path + os.pathsep + os.environ['PATH']
99+
100+
print("---------------------------------------")
101+
sys.stdout.flush()
102+
37103
import Sofa.constants
38104
import Sofa.Helper
39105
import Sofa.Core

bindings/Sofa/src/SofaPython3/Sofa/Components/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ SP3_add_python_module(
1717
DESTINATION Sofa
1818
SOURCES ${SOURCE_FILES}
1919
HEADERS ${HEADER_FILES}
20-
DEPENDS SofaCore SofaHelper SofaSimulationCore SofaPython3::Plugin
21-
)
20+
DEPENDS Sofa.Core Sofa.Helper Sofa.SimulationCore SofaPython3::Plugin
21+
)

0 commit comments

Comments
 (0)