Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/keras/src/utils/tf_inspect.py: 0%

136 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-05 06:32 +0000

1# Copyright 2017 The TensorFlow Authors. All Rights Reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================== 

15"""TFDecorator-aware replacements for the inspect module.""" 

16import collections 

17import functools 

18import inspect as _inspect 

19 

20import tensorflow.compat.v2 as tf 

21 

22if hasattr(_inspect, "ArgSpec"): 

23 ArgSpec = _inspect.ArgSpec 

24else: 

25 ArgSpec = collections.namedtuple( 

26 "ArgSpec", 

27 [ 

28 "args", 

29 "varargs", 

30 "keywords", 

31 "defaults", 

32 ], 

33 ) 

34 

35if hasattr(_inspect, "FullArgSpec"): 

36 FullArgSpec = _inspect.FullArgSpec 

37else: 

38 FullArgSpec = collections.namedtuple( 

39 "FullArgSpec", 

40 [ 

41 "args", 

42 "varargs", 

43 "varkw", 

44 "defaults", 

45 "kwonlyargs", 

46 "kwonlydefaults", 

47 "annotations", 

48 ], 

49 ) 

50 

51 

52def _convert_maybe_argspec_to_fullargspec(argspec): 

53 if isinstance(argspec, FullArgSpec): 

54 return argspec 

55 return FullArgSpec( 

56 args=argspec.args, 

57 varargs=argspec.varargs, 

58 varkw=argspec.keywords, 

59 defaults=argspec.defaults, 

60 kwonlyargs=[], 

61 kwonlydefaults=None, 

62 annotations={}, 

63 ) 

64 

65 

66if hasattr(_inspect, "getfullargspec"): 

67 _getfullargspec = _inspect.getfullargspec 

68 

69 def _getargspec(target): 

70 """A python3 version of getargspec. 

71 

72 Calls `getfullargspec` and assigns args, varargs, 

73 varkw, and defaults to a python 2/3 compatible `ArgSpec`. 

74 

75 The parameter name 'varkw' is changed to 'keywords' to fit the 

76 `ArgSpec` struct. 

77 

78 Args: 

79 target: the target object to inspect. 

80 

81 Returns: 

82 An ArgSpec with args, varargs, keywords, and defaults parameters 

83 from FullArgSpec. 

84 """ 

85 fullargspecs = getfullargspec(target) 

86 argspecs = ArgSpec( 

87 args=fullargspecs.args, 

88 varargs=fullargspecs.varargs, 

89 keywords=fullargspecs.varkw, 

90 defaults=fullargspecs.defaults, 

91 ) 

92 return argspecs 

93 

94else: 

95 _getargspec = _inspect.getargspec 

96 

97 def _getfullargspec(target): 

98 """A python2 version of getfullargspec. 

99 

100 Args: 

101 target: the target object to inspect. 

102 

103 Returns: 

104 A FullArgSpec with empty kwonlyargs, kwonlydefaults and annotations. 

105 """ 

106 return _convert_maybe_argspec_to_fullargspec(getargspec(target)) 

107 

108 

109def currentframe(): 

110 """TFDecorator-aware replacement for inspect.currentframe.""" 

111 return _inspect.stack()[1][0] 

112 

113 

114def getargspec(obj): 

115 """TFDecorator-aware replacement for `inspect.getargspec`. 

116 

117 Note: `getfullargspec` is recommended as the python 2/3 compatible 

118 replacement for this function. 

119 

120 Args: 

121 obj: A function, partial function, or callable object, possibly decorated. 

122 

123 Returns: 

124 The `ArgSpec` that describes the signature of the outermost decorator that 

125 changes the callable's signature, or the `ArgSpec` that describes 

126 the object if not decorated. 

127 

128 Raises: 

129 ValueError: When callable's signature can not be expressed with 

130 ArgSpec. 

131 TypeError: For objects of unsupported types. 

132 """ 

133 if isinstance(obj, functools.partial): 

134 return _get_argspec_for_partial(obj) 

135 

136 decorators, target = tf.__internal__.decorator.unwrap(obj) 

137 

138 spec = next( 

139 ( 

140 d.decorator_argspec 

141 for d in decorators 

142 if d.decorator_argspec is not None 

143 ), 

144 None, 

145 ) 

146 if spec: 

147 return spec 

148 

149 try: 

150 # Python3 will handle most callables here (not partial). 

151 return _getargspec(target) 

152 except TypeError: 

153 pass 

154 

155 if isinstance(target, type): 

156 try: 

157 return _getargspec(target.__init__) 

158 except TypeError: 

159 pass 

160 

161 try: 

162 return _getargspec(target.__new__) 

163 except TypeError: 

164 pass 

165 

166 # The `type(target)` ensures that if a class is received we don't return 

167 # the signature of its __call__ method. 

168 return _getargspec(type(target).__call__) 

169 

170 

171def _get_argspec_for_partial(obj): 

172 """Implements `getargspec` for `functools.partial` objects. 

173 

174 Args: 

175 obj: The `functools.partial` object 

176 Returns: 

177 An `inspect.ArgSpec` 

178 Raises: 

179 ValueError: When callable's signature can not be expressed with 

180 ArgSpec. 

181 """ 

182 # When callable is a functools.partial object, we construct its ArgSpec with 

183 # following strategy: 

184 # - If callable partial contains default value for positional arguments (ie. 

185 # object.args), then final ArgSpec doesn't contain those positional 

186 # arguments. 

187 # - If callable partial contains default value for keyword arguments (ie. 

188 # object.keywords), then we merge them with wrapped target. Default values 

189 # from callable partial takes precedence over those from wrapped target. 

190 # 

191 # However, there is a case where it is impossible to construct a valid 

192 # ArgSpec. Python requires arguments that have no default values must be 

193 # defined before those with default values. ArgSpec structure is only valid 

194 # when this presumption holds true because default values are expressed as a 

195 # tuple of values without keywords and they are always assumed to belong to 

196 # last K arguments where K is number of default values present. 

197 # 

198 # Since functools.partial can give default value to any argument, this 

199 # presumption may no longer hold in some cases. For example: 

200 # 

201 # def func(m, n): 

202 # return 2 * m + n 

203 # partialed = functools.partial(func, m=1) 

204 # 

205 # This example will result in m having a default value but n doesn't. This 

206 # is usually not allowed in Python and can not be expressed in ArgSpec 

207 # correctly. 

208 # 

209 # Thus, we must detect cases like this by finding first argument with 

210 # default value and ensures all following arguments also have default 

211 # values. When this is not true, a ValueError is raised. 

212 

213 n_prune_args = len(obj.args) 

214 partial_keywords = obj.keywords or {} 

215 

216 args, varargs, keywords, defaults = getargspec(obj.func) 

217 

218 # Pruning first n_prune_args arguments. 

219 args = args[n_prune_args:] 

220 

221 # Partial function may give default value to any argument, therefore length 

222 # of default value list must be len(args) to allow each argument to 

223 # potentially be given a default value. 

224 no_default = object() 

225 all_defaults = [no_default] * len(args) 

226 

227 if defaults: 

228 all_defaults[-len(defaults) :] = defaults 

229 

230 # Fill in default values provided by partial function in all_defaults. 

231 for kw, default in partial_keywords.items(): 

232 if kw in args: 

233 idx = args.index(kw) 

234 all_defaults[idx] = default 

235 elif not keywords: 

236 raise ValueError( 

237 "Function does not have **kwargs parameter, but " 

238 "contains an unknown partial keyword." 

239 ) 

240 

241 # Find first argument with default value set. 

242 first_default = next( 

243 (idx for idx, x in enumerate(all_defaults) if x is not no_default), None 

244 ) 

245 

246 # If no default values are found, return ArgSpec with defaults=None. 

247 if first_default is None: 

248 return ArgSpec(args, varargs, keywords, None) 

249 

250 # Checks if all arguments have default value set after first one. 

251 invalid_default_values = [ 

252 args[i] 

253 for i, j in enumerate(all_defaults) 

254 if j is no_default and i > first_default 

255 ] 

256 

257 if invalid_default_values: 

258 raise ValueError( 

259 f"Some arguments {invalid_default_values} do not have " 

260 "default value, but they are positioned after those with " 

261 "default values. This can not be expressed with ArgSpec." 

262 ) 

263 

264 return ArgSpec(args, varargs, keywords, tuple(all_defaults[first_default:])) 

265 

266 

267def getfullargspec(obj): 

268 """TFDecorator-aware replacement for `inspect.getfullargspec`. 

269 

270 This wrapper emulates `inspect.getfullargspec` in[^)]* Python2. 

271 

272 Args: 

273 obj: A callable, possibly decorated. 

274 

275 Returns: 

276 The `FullArgSpec` that describes the signature of 

277 the outermost decorator that changes the callable's signature. If the 

278 callable is not decorated, `inspect.getfullargspec()` will be called 

279 directly on the callable. 

280 """ 

281 decorators, target = tf.__internal__.decorator.unwrap(obj) 

282 

283 for d in decorators: 

284 if d.decorator_argspec is not None: 

285 return _convert_maybe_argspec_to_fullargspec(d.decorator_argspec) 

286 return _getfullargspec(target) 

287 

288 

289def getcallargs(*func_and_positional, **named): 

290 """TFDecorator-aware replacement for inspect.getcallargs. 

291 

292 Args: 

293 *func_and_positional: A callable, possibly decorated, followed by any 

294 positional arguments that would be passed to `func`. 

295 **named: The named argument dictionary that would be passed to `func`. 

296 

297 Returns: 

298 A dictionary mapping `func`'s named arguments to the values they would 

299 receive if `func(*positional, **named)` were called. 

300 

301 `getcallargs` will use the argspec from the outermost decorator that 

302 provides it. If no attached decorators modify argspec, the final unwrapped 

303 target's argspec will be used. 

304 """ 

305 func = func_and_positional[0] 

306 positional = func_and_positional[1:] 

307 argspec = getfullargspec(func) 

308 call_args = named.copy() 

309 this = getattr(func, "im_self", None) or getattr(func, "__self__", None) 

310 if ismethod(func) and this: 

311 positional = (this,) + positional 

312 remaining_positionals = [ 

313 arg for arg in argspec.args if arg not in call_args 

314 ] 

315 call_args.update(dict(zip(remaining_positionals, positional))) 

316 default_count = 0 if not argspec.defaults else len(argspec.defaults) 

317 if default_count: 

318 for arg, value in zip(argspec.args[-default_count:], argspec.defaults): 

319 if arg not in call_args: 

320 call_args[arg] = value 

321 if argspec.kwonlydefaults is not None: 

322 for k, v in argspec.kwonlydefaults.items(): 

323 if k not in call_args: 

324 call_args[k] = v 

325 return call_args 

326 

327 

328def getframeinfo(*args, **kwargs): 

329 return _inspect.getframeinfo(*args, **kwargs) 

330 

331 

332def getdoc(obj): 

333 """TFDecorator-aware replacement for inspect.getdoc. 

334 

335 Args: 

336 obj: An object, possibly decorated. 

337 

338 Returns: 

339 The docstring associated with the object. 

340 

341 The outermost-decorated object is intended to have the most complete 

342 documentation, so the decorated parameter is not unwrapped. 

343 """ 

344 return _inspect.getdoc(obj) 

345 

346 

347def getfile(obj): 

348 """TFDecorator-aware replacement for inspect.getfile.""" 

349 unwrapped_object = tf.__internal__.decorator.unwrap(obj)[1] 

350 

351 # Work around for the case when object is a stack frame 

352 # and only .pyc files are used. In this case, getfile 

353 # might return incorrect path. So, we get the path from f_globals 

354 # instead. 

355 if ( 

356 hasattr(unwrapped_object, "f_globals") 

357 and "__file__" in unwrapped_object.f_globals 

358 ): 

359 return unwrapped_object.f_globals["__file__"] 

360 return _inspect.getfile(unwrapped_object) 

361 

362 

363def getmembers(obj, predicate=None): 

364 """TFDecorator-aware replacement for inspect.getmembers.""" 

365 return _inspect.getmembers(obj, predicate) 

366 

367 

368def getmodule(obj): 

369 """TFDecorator-aware replacement for inspect.getmodule.""" 

370 return _inspect.getmodule(obj) 

371 

372 

373def getmro(cls): 

374 """TFDecorator-aware replacement for inspect.getmro.""" 

375 return _inspect.getmro(cls) 

376 

377 

378def getsource(obj): 

379 """TFDecorator-aware replacement for inspect.getsource.""" 

380 return _inspect.getsource(tf.__internal__.decorator.unwrap(obj)[1]) 

381 

382 

383def getsourcefile(obj): 

384 """TFDecorator-aware replacement for inspect.getsourcefile.""" 

385 return _inspect.getsourcefile(tf.__internal__.decorator.unwrap(obj)[1]) 

386 

387 

388def getsourcelines(obj): 

389 """TFDecorator-aware replacement for inspect.getsourcelines.""" 

390 return _inspect.getsourcelines(tf.__internal__.decorator.unwrap(obj)[1]) 

391 

392 

393def isbuiltin(obj): 

394 """TFDecorator-aware replacement for inspect.isbuiltin.""" 

395 return _inspect.isbuiltin(tf.__internal__.decorator.unwrap(obj)[1]) 

396 

397 

398def isclass(obj): 

399 """TFDecorator-aware replacement for inspect.isclass.""" 

400 return _inspect.isclass(tf.__internal__.decorator.unwrap(obj)[1]) 

401 

402 

403def isfunction(obj): 

404 """TFDecorator-aware replacement for inspect.isfunction.""" 

405 return _inspect.isfunction(tf.__internal__.decorator.unwrap(obj)[1]) 

406 

407 

408def isframe(obj): 

409 """TFDecorator-aware replacement for inspect.ismodule.""" 

410 return _inspect.isframe(tf.__internal__.decorator.unwrap(obj)[1]) 

411 

412 

413def isgenerator(obj): 

414 """TFDecorator-aware replacement for inspect.isgenerator.""" 

415 return _inspect.isgenerator(tf.__internal__.decorator.unwrap(obj)[1]) 

416 

417 

418def isgeneratorfunction(obj): 

419 """TFDecorator-aware replacement for inspect.isgeneratorfunction.""" 

420 return _inspect.isgeneratorfunction( 

421 tf.__internal__.decorator.unwrap(obj)[1] 

422 ) 

423 

424 

425def ismethod(obj): 

426 """TFDecorator-aware replacement for inspect.ismethod.""" 

427 return _inspect.ismethod(tf.__internal__.decorator.unwrap(obj)[1]) 

428 

429 

430def ismodule(obj): 

431 """TFDecorator-aware replacement for inspect.ismodule.""" 

432 return _inspect.ismodule(tf.__internal__.decorator.unwrap(obj)[1]) 

433 

434 

435def isroutine(obj): 

436 """TFDecorator-aware replacement for inspect.isroutine.""" 

437 return _inspect.isroutine(tf.__internal__.decorator.unwrap(obj)[1]) 

438 

439 

440def stack(context=1): 

441 """TFDecorator-aware replacement for inspect.stack.""" 

442 return _inspect.stack(context)[1:] 

443