11"""Platform specific helpers to manage locating native dynamic libraries
22
3- This module hosts features similar to https://github.com/rdotnet/dynamic-interop-dll/blob/master /DynamicInterop/PlatformUtility.cs
3+ This module hosts features similar to https://github.com/rdotnet/dynamic-interop-dll/blob/main /DynamicInterop/PlatformUtility.cs
44
55"""
66
77import os
88import sys
9- from glob import glob
10-
119from ctypes .util import find_library as ctypes_find_library
10+ from glob import glob
1211from typing import List , Optional , Union
1312
1413
15- def library_short_filename (library_name : str , platform :Optional [str ] = None ) -> str :
14+ def library_short_filename (library_name : str , platform : Optional [str ] = None ) -> str :
1615 """Based on the library name, return the platform-specific expected library short file name
1716
1817 Args:
19- library_name (str): name of the library, for instance 'R', which results out of this
18+ library_name (str): name of the library, for instance 'R', which results out of this
2019 function as 'libR.so' on Linux and 'R.dll' on Windows
2120
2221 Raises:
@@ -39,8 +38,9 @@ def library_short_filename(library_name: str, platform:Optional[str] = None) ->
3938 else :
4039 raise NotImplementedError (f"Platform '{ platform } ' is not (yet) supported" )
4140
42- def find_full_path (name : str , prefix :Optional [str ]= None ) -> Union [str , None ]:
43- """Find the full path of a library in under the python
41+
42+ def find_full_path (name : str , prefix : Optional [str ] = None ) -> Union [str , None ]:
43+ """Find the full path of a library in under the python
4444 installation directory, or as devised by ctypes.find_library
4545
4646 Args:
@@ -55,7 +55,7 @@ def find_full_path(name: str, prefix:Optional[str]=None) -> Union[str, None]:
5555 '/home/xxxyyy/anaconda3/envs/wqml/lib/libgfortran.so'
5656 >>> find_full_path('R')
5757 'libR.so'
58- """
58+ """
5959 full_libpath = None
6060 if prefix is None :
6161 prefix = sys .prefix
@@ -81,7 +81,7 @@ def find_full_path(name: str, prefix:Optional[str]=None) -> Union[str, None]:
8181
8282# Returns:
8383# List[str]: zero or more matches, full paths to candidate files
84- # """
84+ # """
8585# if directories is None:
8686# directories = []
8787# full_paths = [os.path.join(d, dll_short_name) for d in directories]
@@ -109,9 +109,12 @@ def find_full_path(name: str, prefix:Optional[str]=None) -> Union[str, None]:
109109
110110
111111def augment_path_env (
112- added_paths : Union [str , List [str ]], subfolder : str = None , to_env : str = "PATH" , prepend :bool = False
112+ added_paths : Union [str , List [str ]],
113+ subfolder : str = None ,
114+ to_env : str = "PATH" ,
115+ prepend : bool = False ,
113116) -> str :
114- """Build a new list of directory paths, prepending prior to an existing env var with paths.
117+ """Build a new list of directory paths, prepending prior to an existing env var with paths.
115118
116119 New paths are prepended only if they do already exist.
117120
@@ -131,11 +134,13 @@ def augment_path_env(
131134 prior_paths = prior_path_env .split (path_sep )
132135 else :
133136 prior_paths = []
137+
134138 def _my_path_join (x , subfolder ): # avoid trailing path separator
135139 if subfolder is not None and subfolder != "" :
136140 return os .path .join (x , subfolder )
137141 else :
138142 return x
143+
139144 if subfolder is not None :
140145 added_paths = [_my_path_join (x , subfolder ) for x in added_paths ]
141146 added_paths = [x for x in added_paths if os .path .exists (x )]
@@ -147,6 +152,7 @@ def _my_path_join(x, subfolder): # avoid trailing path separator
147152 new_env_val = path_sep .join (new_paths )
148153 return new_env_val
149154
155+
150156# TODO: is that of any use still?? refactored out from uchronia and co. , but appears unused.
151157# def find_first_full_path(native_lib_file_name, readable_lib_name = "native library", env_var_name = ""):
152158# if os.path.isabs(native_lib_file_name):
@@ -193,24 +199,26 @@ def _my_path_join(x, subfolder): # avoid trailing path separator
193199
194200
195201# # The following is useful, but idiosyncratic. Consider and rethink.
196- def _win_architecture (platform :str = None ):
202+ def _win_architecture (platform : str = None ):
197203 platform = sys .platform if platform is None else platform
198204 if platform == "win32" :
199205 arch = os .environ ["PROCESSOR_ARCHITECTURE" ]
200- return "64" if arch == ' AMD64' else '32'
206+ return "64" if arch == " AMD64" else "32"
201207 else :
202208 return ""
203209
204210
205- def build_new_path_env (from_env :str = 'LIBRARY_PATH' , to_env :str = 'PATH' , platform :str = None ) -> str :
211+ def build_new_path_env (
212+ from_env : str = "LIBRARY_PATH" , to_env : str = "PATH" , platform : str = None
213+ ) -> str :
206214 """Propose an update to an existing environment variable, based on the path(s) specified in another environment variable. This function is effectively meant to be useful on Windows only.
207215
208216 Args:
209217 from_env (str, optional): name of the source environment variable specifying the location(s) of custom libraries to load. Defaults to 'LIBRARY_PATH'.
210218 to_env (str, optional): environment variable to update, most likely the Windows PATH env var. Defaults to 'PATH'.
211219
212220 Returns:
213- str: the proposed updated content for the 'to_env' environment variable.
221+ str: the proposed updated content for the 'to_env' environment variable.
214222 """
215223 platform = sys .platform if platform is None else platform
216224 path_sep = os .pathsep
@@ -221,14 +229,19 @@ def build_new_path_env (from_env:str='LIBRARY_PATH', to_env:str='PATH', platform
221229 shared_lib_paths_vec = shared_lib_paths .split (path_sep )
222230 return augment_path_env (shared_lib_paths_vec , subfolder , to_env = to_env )
223231 else :
224- print ("WARNING: a function was called to look for environment variable '{0}' to update the environment variable '{1}', but was not found. This may be fine, but if the package fails to load because a native library is not found, this is a likely cause." .format (from_env , to_env ))
232+ print (
233+ "WARNING: a function was called to look for environment variable '{0}' to update the environment variable '{1}', but was not found. This may be fine, but if the package fails to load because a native library is not found, this is a likely cause." .format (
234+ from_env , to_env
235+ )
236+ )
225237 prior_path_env = os .environ .get (to_env )
226238 if prior_path_env is not None :
227239 return prior_path_env
228240 else :
229241 return ""
230242
231- def update_path_windows (from_env :str = 'LIBRARY_PATH' , to_env :str = 'PATH' ) -> None :
243+
244+ def update_path_windows (from_env : str = "LIBRARY_PATH" , to_env : str = "PATH" ) -> None :
232245 """If called on Windows, append an environment variable, based on the path(s) specified in another environment variable. This function is effectively meant to be useful on Windows only.
233246
234247 Args:
@@ -238,10 +251,5 @@ def update_path_windows (from_env:str='LIBRARY_PATH', to_env:str='PATH') -> None
238251 Returns:
239252 None
240253 """
241- if ( sys .platform == ' win32' ) :
254+ if sys .platform == " win32" :
242255 os .environ [to_env ] = build_new_path_env (from_env , to_env , sys .platform )
243-
244-
245-
246-
247-
0 commit comments