Skip to content

Commit 9b244d4

Browse files
authored
Refactored Windows-specific code under if sofa_root and sys.platform == 'win32' to improve readability and robustness. Added helper functions to reduce duplication and handle missing SOFAPYTHON3_ROOT safely. Maintained existing behavior while preventing potential crashes and improving compatibility. (sofa-framework#539)
1 parent 77a39c6 commit 9b244d4

File tree

1 file changed

+64
-48
lines changed

1 file changed

+64
-48
lines changed

bindings/Sofa/package/__init__.py

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -61,88 +61,104 @@
6161
else:
6262
print("Warning: cannot guess SOFAPYTHON3_ROOT",
6363
"Loading SofaPython3 modules will likely fail.")
64+
sofapython3_root = None # ensure downstream code handles the absence safely
65+
66+
# Helper functions for readability and robustness
67+
def _collect_build_candidates(bin_path, modes):
68+
candidates = [bin_path]
69+
dev_candidates = []
70+
for mode in modes:
71+
mode_path = os.path.abspath(os.path.join(bin_path, mode))
72+
if os.path.isdir(mode_path):
73+
dev_candidates.append(mode_path)
74+
return candidates, dev_candidates
75+
76+
def _select_bin_with_dll(candidates, dll_names):
77+
selected = None
78+
found_file = ""
79+
for candidate in candidates:
80+
for dll in dll_names:
81+
test = os.path.join(candidate, dll)
82+
if os.path.isfile(test):
83+
print(f"Found {dll} in {candidate}")
84+
selected = candidate
85+
found_file = test
86+
break
87+
if selected:
88+
break
89+
return selected, found_file
6490

65-
# Windows-only: starting from python 3.8, python wont read the env. variable PATH to get SOFA's dlls.
91+
# Windows-only: starting from python 3.8, python won't read the env. variable PATH to get SOFA's dlls.
6692
# os.add_dll_directory() is the new way to add paths for python to get external libraries.
6793
sofa_bin_path = os.path.join(sofa_root, "bin")
68-
sofapython3_bin_path = os.path.join(sofapython3_root, "bin")
94+
sofapython3_bin_path = os.path.join(sofapython3_root, "bin") if sofapython3_root else None
6995

7096
# A user using a build configuration could have a multiple-configuration type build
7197
# which is typical on Windows and MSVC; and MacOS with XCode
7298
# If the user set the env.var SOFA_BUILD_CONFIGURATION, he can choose a preferred configuration.
7399
# If it is not found, it is considered as an error.
74100
sofa_build_configuration = os.environ.get('SOFA_BUILD_CONFIGURATION')
75-
compilation_modes = []
76101
if sofa_build_configuration:
77102
print("SOFA_BUILD_CONFIGURATION is set to " + sofa_build_configuration)
78103
compilation_modes = [sofa_build_configuration]
79104
else:
80-
compilation_modes = ["Release", "RelWithDebInfo", "Debug", "MinSizeRel"] # Standard multi-configuration modes in CMake
105+
compilation_modes = ["Release", "RelWithDebInfo", "Debug", "MinSizeRel"] # Standard multi-configuration modes in CMake
81106

82-
sofa_bin_compilation_modes = []
83-
sofapython3_bin_compilation_modes = []
84-
for mode in compilation_modes:
85-
if os.path.isdir(os.path.abspath(os.path.join(sofa_bin_path, mode))):
86-
sofa_bin_compilation_modes.append(os.path.join(sofa_bin_path, mode))
87-
if os.path.isdir(os.path.abspath(os.path.join(sofapython3_bin_path, mode))):
88-
sofapython3_bin_compilation_modes.append(os.path.join(sofapython3_bin_path, mode))
107+
# Collect candidates
108+
sofa_base_candidates, sofa_dev_candidates = _collect_build_candidates(sofa_bin_path, compilation_modes)
109+
if sofapython3_bin_path:
110+
sp3_base_candidates, sp3_dev_candidates = _collect_build_candidates(sofapython3_bin_path, compilation_modes)
111+
else:
112+
sp3_base_candidates, sp3_dev_candidates = [], []
89113

90-
if sofa_bin_compilation_modes:
114+
if sofa_dev_candidates:
91115
print("Detected SOFA development build")
92-
if sofapython3_bin_compilation_modes:
116+
if sp3_dev_candidates:
93117
print("Detected SofaPython3 development build")
94118

95-
sofa_bin_candidates = [sofa_bin_path] + sofa_bin_compilation_modes
96-
sofapython3_bin_candidates = [sofapython3_bin_path] + sofapython3_bin_compilation_modes
119+
sofa_bin_candidates = sofa_base_candidates + sofa_dev_candidates
120+
sofapython3_bin_candidates = sp3_base_candidates + sp3_dev_candidates
97121

122+
# Look for expected DLLs to pick the right bin folder
98123
sofa_helper_dll = ["Sofa.Helper.dll", "Sofa.Helper_d.dll"]
99-
sofa_file_test = ""
100-
for candidate in sofa_bin_candidates:
101-
for dll in sofa_helper_dll:
102-
sofa_file_test = os.path.join(candidate, dll)
103-
if os.path.isfile(sofa_file_test):
104-
print(f"Found {dll} in {candidate}")
105-
sofa_bin_path = candidate
106-
break
107-
else:
108-
continue
109-
break
124+
sofa_selected, sofa_file_test = _select_bin_with_dll(sofa_bin_candidates, sofa_helper_dll)
125+
if sofa_selected:
126+
sofa_bin_path = sofa_selected
110127

111128
sofa_python3_dll = ["SofaPython3.dll", "SofaPython3_d.dll"]
112-
113129
sofapython3_file_test = ""
114-
for candidate in sofapython3_bin_candidates:
115-
for dll in sofa_python3_dll:
116-
sofapython3_file_test = os.path.join(candidate, dll)
117-
if os.path.isfile(sofapython3_file_test):
118-
print(f"Found {dll} in {candidate}")
119-
sofapython3_bin_path = candidate
120-
break
121-
else:
122-
continue
123-
break
130+
if sofapython3_bin_candidates:
131+
sp3_selected, sofapython3_file_test = _select_bin_with_dll(sofapython3_bin_candidates, sofa_python3_dll)
132+
if sp3_selected:
133+
sofapython3_bin_path = sp3_selected
124134

125-
if not os.path.isfile(sofa_file_test):
135+
# Warnings if not found
136+
if not sofa_file_test:
126137
print("Warning: environment variable SOFA_ROOT is set but seems invalid.",
127138
"Loading SOFA libraries will likely fail.")
128139
print("SOFA_ROOT is currently: " + sofa_root)
129-
if not os.path.isfile(sofapython3_file_test):
130-
print("Warning: cannot find SofaPython3.dll at path: " + sofapython3_bin_path)
140+
if not sofapython3_file_test:
141+
if sofapython3_bin_path:
142+
print("Warning: cannot find SofaPython3.dll at path: " + str(sofapython3_bin_path))
143+
else:
144+
print("Warning: SOFAPYTHON3_ROOT is not set or invalid; SofaPython3 DLL path cannot be determined.")
131145
print("This path will NOT be added to the DLL search path.",
132146
"Loading SofaPython3 python modules will likely fail.")
133147

134-
if sys.version_info.minor >= 8:
135-
# Starting from python3.8 we need to explicitly find SOFA libraries
136-
if os.path.isfile(sofa_file_test):
148+
# Add directories to DLL search path or PATH depending on Python version capabilities
149+
add_dll_dir_available = hasattr(os, 'add_dll_directory')
150+
if add_dll_dir_available:
151+
# Starting from Python 3.8 we need to explicitly register directories for DLL loading
152+
if sofa_file_test:
137153
os.add_dll_directory(sofa_bin_path)
138-
if os.path.isfile(sofapython3_file_test):
154+
if sofapython3_file_test and sofapython3_bin_path:
139155
os.add_dll_directory(sofapython3_bin_path)
140156
else:
141157
# Add temporarily the bin/lib path to the env variable PATH
142-
if os.path.isfile(sofa_file_test):
143-
os.environ['PATH'] = sofa_bin_path + os.pathsep + os.environ['PATH']
144-
if os.path.isfile(sofapython3_file_test):
145-
os.environ['PATH'] = sofapython3_bin_path + os.pathsep + os.environ['PATH']
158+
if sofa_file_test:
159+
os.environ['PATH'] = sofa_bin_path + os.pathsep + os.environ.get('PATH', '')
160+
if sofapython3_file_test and sofapython3_bin_path:
161+
os.environ['PATH'] = sofapython3_bin_path + os.pathsep + os.environ.get('PATH', '')
146162

147163
print("---------------------------------------")
148164
sys.stdout.flush()

0 commit comments

Comments
 (0)