Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/imageio-2.35.1-py3.8.egg/imageio/core/findlib.py: 76%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

74 statements  

1# -*- coding: utf-8 -*- 

2# Copyright (c) 2015-1018, imageio contributors 

3# Copyright (C) 2013, Zach Pincus, Almar Klein and others 

4 

5""" This module contains generic code to find and load a dynamic library. 

6""" 

7 

8import os 

9import sys 

10import ctypes 

11 

12 

13LOCALDIR = os.path.abspath(os.path.dirname(__file__)) 

14 

15# Flag that can be patched / set to True to disable loading non-system libs 

16SYSTEM_LIBS_ONLY = False 

17 

18 

19def looks_lib(fname): 

20 """Returns True if the given filename looks like a dynamic library. 

21 Based on extension, but cross-platform and more flexible. 

22 """ 

23 fname = fname.lower() 

24 if sys.platform.startswith("win"): 

25 return fname.endswith(".dll") 

26 elif sys.platform.startswith("darwin"): 

27 return fname.endswith(".dylib") 

28 else: 

29 return fname.endswith(".so") or ".so." in fname 

30 

31 

32def generate_candidate_libs(lib_names, lib_dirs=None): 

33 """Generate a list of candidate filenames of what might be the dynamic 

34 library corresponding with the given list of names. 

35 Returns (lib_dirs, lib_paths) 

36 """ 

37 lib_dirs = lib_dirs or [] 

38 

39 # Get system dirs to search 

40 sys_lib_dirs = [ 

41 "/lib", 

42 "/usr/lib", 

43 "/usr/lib/x86_64-linux-gnu", 

44 "/usr/lib/aarch64-linux-gnu", 

45 "/usr/local/lib", 

46 "/opt/local/lib", 

47 ] 

48 

49 # Get Python dirs to search (shared if for Pyzo) 

50 py_sub_dirs = ["bin", "lib", "DLLs", "Library/bin", "shared"] 

51 py_lib_dirs = [os.path.join(sys.prefix, d) for d in py_sub_dirs] 

52 if hasattr(sys, "base_prefix"): 

53 py_lib_dirs += [os.path.join(sys.base_prefix, d) for d in py_sub_dirs] 

54 

55 # Get user dirs to search (i.e. HOME) 

56 home_dir = os.path.expanduser("~") 

57 user_lib_dirs = [os.path.join(home_dir, d) for d in ["lib"]] 

58 

59 # Select only the dirs for which a directory exists, and remove duplicates 

60 potential_lib_dirs = lib_dirs + sys_lib_dirs + py_lib_dirs + user_lib_dirs 

61 lib_dirs = [] 

62 for ld in potential_lib_dirs: 

63 if os.path.isdir(ld) and ld not in lib_dirs: 

64 lib_dirs.append(ld) 

65 

66 # Now attempt to find libraries of that name in the given directory 

67 # (case-insensitive) 

68 lib_paths = [] 

69 for lib_dir in lib_dirs: 

70 # Get files, prefer short names, last version 

71 files = os.listdir(lib_dir) 

72 files = reversed(sorted(files)) 

73 files = sorted(files, key=len) 

74 for lib_name in lib_names: 

75 # Test all filenames for name and ext 

76 for fname in files: 

77 if fname.lower().startswith(lib_name) and looks_lib(fname): 

78 lib_paths.append(os.path.join(lib_dir, fname)) 

79 

80 # Return (only the items which are files) 

81 lib_paths = [lp for lp in lib_paths if os.path.isfile(lp)] 

82 return lib_dirs, lib_paths 

83 

84 

85def load_lib(exact_lib_names, lib_names, lib_dirs=None): 

86 """load_lib(exact_lib_names, lib_names, lib_dirs=None) 

87 

88 Load a dynamic library. 

89 

90 This function first tries to load the library from the given exact 

91 names. When that fails, it tries to find the library in common 

92 locations. It searches for files that start with one of the names 

93 given in lib_names (case insensitive). The search is performed in 

94 the given lib_dirs and a set of common library dirs. 

95 

96 Returns ``(ctypes_library, library_path)`` 

97 """ 

98 

99 # Checks 

100 assert isinstance(exact_lib_names, list) 

101 assert isinstance(lib_names, list) 

102 if lib_dirs is not None: 

103 assert isinstance(lib_dirs, list) 

104 exact_lib_names = [n for n in exact_lib_names if n] 

105 lib_names = [n for n in lib_names if n] 

106 

107 # Get reference name (for better messages) 

108 if lib_names: 

109 the_lib_name = lib_names[0] 

110 elif exact_lib_names: 

111 the_lib_name = exact_lib_names[0] 

112 else: 

113 raise ValueError("No library name given.") 

114 

115 # Collect filenames of potential libraries 

116 # First try a few bare library names that ctypes might be able to find 

117 # in the default locations for each platform. 

118 if SYSTEM_LIBS_ONLY: 

119 lib_dirs, lib_paths = [], [] 

120 else: 

121 lib_dirs, lib_paths = generate_candidate_libs(lib_names, lib_dirs) 

122 lib_paths = exact_lib_names + lib_paths 

123 

124 # Select loader 

125 if sys.platform.startswith("win"): 

126 loader = ctypes.windll 

127 else: 

128 loader = ctypes.cdll 

129 

130 # Try to load until success 

131 the_lib = None 

132 errors = [] 

133 for fname in lib_paths: 

134 try: 

135 the_lib = loader.LoadLibrary(fname) 

136 break 

137 except Exception as err: 

138 # Don't record errors when it couldn't load the library from an 

139 # exact name -- this fails often, and doesn't provide any useful 

140 # debugging information anyway, beyond "couldn't find library..." 

141 if fname not in exact_lib_names: 

142 errors.append((fname, err)) 

143 

144 # No success ... 

145 if the_lib is None: 

146 if errors: 

147 # No library loaded, and load-errors reported for some 

148 # candidate libs 

149 err_txt = ["%s:\n%s" % (lib, str(e)) for lib, e in errors] 

150 msg = ( 

151 "One or more %s libraries were found, but " 

152 + "could not be loaded due to the following errors:\n%s" 

153 ) 

154 raise OSError(msg % (the_lib_name, "\n\n".join(err_txt))) 

155 else: 

156 # No errors, because no potential libraries found at all! 

157 msg = "Could not find a %s library in any of:\n%s" 

158 raise OSError(msg % (the_lib_name, "\n".join(lib_dirs))) 

159 

160 # Done 

161 return the_lib, fname