Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/joblib/backports.py: 27%

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

99 statements  

1""" 

2Backports of fixes for joblib dependencies 

3""" 

4 

5import os 

6import re 

7import time 

8from multiprocessing import util 

9from os.path import basename 

10 

11 

12class Version: 

13 """Backport from deprecated distutils 

14 

15 We maintain this backport to avoid introducing a new dependency on 

16 `packaging`. 

17 

18 We might rexplore this choice in the future if all major Python projects 

19 introduce a dependency on packaging anyway. 

20 """ 

21 

22 def __init__(self, vstring=None): 

23 if vstring: 

24 self.parse(vstring) 

25 

26 def __repr__(self): 

27 return "%s ('%s')" % (self.__class__.__name__, str(self)) 

28 

29 def __eq__(self, other): 

30 c = self._cmp(other) 

31 if c is NotImplemented: 

32 return c 

33 return c == 0 

34 

35 def __lt__(self, other): 

36 c = self._cmp(other) 

37 if c is NotImplemented: 

38 return c 

39 return c < 0 

40 

41 def __le__(self, other): 

42 c = self._cmp(other) 

43 if c is NotImplemented: 

44 return c 

45 return c <= 0 

46 

47 def __gt__(self, other): 

48 c = self._cmp(other) 

49 if c is NotImplemented: 

50 return c 

51 return c > 0 

52 

53 def __ge__(self, other): 

54 c = self._cmp(other) 

55 if c is NotImplemented: 

56 return c 

57 return c >= 0 

58 

59 

60class LooseVersion(Version): 

61 """Backport from deprecated distutils 

62 

63 We maintain this backport to avoid introducing a new dependency on 

64 `packaging`. 

65 

66 We might rexplore this choice in the future if all major Python projects 

67 introduce a dependency on packaging anyway. 

68 """ 

69 

70 component_re = re.compile(r"(\d+ | [a-z]+ | \.)", re.VERBOSE) 

71 

72 def __init__(self, vstring=None): 

73 if vstring: 

74 self.parse(vstring) 

75 

76 def parse(self, vstring): 

77 # I've given up on thinking I can reconstruct the version string 

78 # from the parsed tuple -- so I just store the string here for 

79 # use by __str__ 

80 self.vstring = vstring 

81 components = [x for x in self.component_re.split(vstring) if x and x != "."] 

82 for i, obj in enumerate(components): 

83 try: 

84 components[i] = int(obj) 

85 except ValueError: 

86 pass 

87 

88 self.version = components 

89 

90 def __str__(self): 

91 return self.vstring 

92 

93 def __repr__(self): 

94 return "LooseVersion ('%s')" % str(self) 

95 

96 def _cmp(self, other): 

97 if isinstance(other, str): 

98 other = LooseVersion(other) 

99 elif not isinstance(other, LooseVersion): 

100 return NotImplemented 

101 

102 if self.version == other.version: 

103 return 0 

104 if self.version < other.version: 

105 return -1 

106 if self.version > other.version: 

107 return 1 

108 

109 

110try: 

111 import numpy as np 

112 

113 def make_memmap( 

114 filename, 

115 dtype="uint8", 

116 mode="r+", 

117 offset=0, 

118 shape=None, 

119 order="C", 

120 unlink_on_gc_collect=False, 

121 ): 

122 """Custom memmap constructor compatible with numpy.memmap. 

123 

124 This function: 

125 - is a backport the numpy memmap offset fix (See 

126 https://github.com/numpy/numpy/pull/8443 for more details. 

127 The numpy fix is available starting numpy 1.13) 

128 - adds ``unlink_on_gc_collect``, which specifies explicitly whether 

129 the process re-constructing the memmap owns a reference to the 

130 underlying file. If set to True, it adds a finalizer to the 

131 newly-created memmap that sends a maybe_unlink request for the 

132 memmaped file to resource_tracker. 

133 """ 

134 util.debug( 

135 "[MEMMAP READ] creating a memmap (shape {}, filename {}, pid {})".format( 

136 shape, basename(filename), os.getpid() 

137 ) 

138 ) 

139 

140 mm = np.memmap( 

141 filename, dtype=dtype, mode=mode, offset=offset, shape=shape, order=order 

142 ) 

143 if LooseVersion(np.__version__) < "1.13": 

144 mm.offset = offset 

145 if unlink_on_gc_collect: 

146 from ._memmapping_reducer import add_maybe_unlink_finalizer 

147 

148 add_maybe_unlink_finalizer(mm) 

149 return mm 

150except ImportError: 

151 

152 def make_memmap( 

153 filename, 

154 dtype="uint8", 

155 mode="r+", 

156 offset=0, 

157 shape=None, 

158 order="C", 

159 unlink_on_gc_collect=False, 

160 ): 

161 raise NotImplementedError( 

162 "'joblib.backports.make_memmap' should not be used " 

163 "if numpy is not installed." 

164 ) 

165 

166 

167if os.name == "nt": 

168 # https://github.com/joblib/joblib/issues/540 

169 access_denied_errors = (5, 13) 

170 from os import replace 

171 

172 def concurrency_safe_rename(src, dst): 

173 """Renames ``src`` into ``dst`` overwriting ``dst`` if it exists. 

174 

175 On Windows os.replace can yield permission errors if executed by two 

176 different processes. 

177 """ 

178 max_sleep_time = 1 

179 total_sleep_time = 0 

180 sleep_time = 0.001 

181 while total_sleep_time < max_sleep_time: 

182 try: 

183 replace(src, dst) 

184 break 

185 except Exception as exc: 

186 if getattr(exc, "winerror", None) in access_denied_errors: 

187 time.sleep(sleep_time) 

188 total_sleep_time += sleep_time 

189 sleep_time *= 2 

190 else: 

191 raise 

192 else: 

193 raise 

194else: 

195 from os import replace as concurrency_safe_rename # noqa