Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/keras/utils/tf_inspect.py: 0%
139 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-05 06:32 +0000
« 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."""
17import collections
18import functools
19import inspect as _inspect
21from tensorflow.python.util import tf_decorator
23try:
24 ArgSpec = _inspect.ArgSpec
25except:
26 pass
29if hasattr(_inspect, 'FullArgSpec'):
30 FullArgSpec = _inspect.FullArgSpec # pylint: disable=invalid-name
31else:
32 FullArgSpec = collections.namedtuple('FullArgSpec', [
33 'args', 'varargs', 'varkw', 'defaults', 'kwonlyargs', 'kwonlydefaults',
34 'annotations'
35 ])
38def _convert_maybe_argspec_to_fullargspec(argspec):
39 if isinstance(argspec, FullArgSpec):
40 return argspec
41 return FullArgSpec(
42 args=argspec.args,
43 varargs=argspec.varargs,
44 varkw=argspec.keywords,
45 defaults=argspec.defaults,
46 kwonlyargs=[],
47 kwonlydefaults=None,
48 annotations={})
50if hasattr(_inspect, 'getfullargspec'):
51 _getfullargspec = _inspect.getfullargspec # pylint: disable=invalid-name
53 def _getargspec(target):
54 """A python3 version of getargspec.
56 Calls `getfullargspec` and assigns args, varargs,
57 varkw, and defaults to a python 2/3 compatible `ArgSpec`.
59 The parameter name 'varkw' is changed to 'keywords' to fit the
60 `ArgSpec` struct.
62 Args:
63 target: the target object to inspect.
65 Returns:
66 An ArgSpec with args, varargs, keywords, and defaults parameters
67 from FullArgSpec.
68 """
69 fullargspecs = getfullargspec(target)
70 if hasattr(_inspect, 'ArgSpec'):
71 argspecs = ArgSpec(
72 args=fullargspecs.args,
73 varargs=fullargspecs.varargs,
74 keywords=fullargspecs.varkw,
75 defaults=fullargspecs.defaults)
76 else:
77 argspecs = FullArgSpec(
78 args=fullargspecs.args,
79 varargs=fullargspecs.varargs,
80 varkw=fullargspecs.varkw,
81 defaults=fullargspecs.defaults,
82 kwonlyargs=[],
83 kwonlydefaults=None,
84 annotations={})
85 return argspecs
86else:
87 _getargspec = _inspect.getargspec
89 def _getfullargspec(target):
90 """A python2 version of getfullargspec.
92 Args:
93 target: the target object to inspect.
95 Returns:
96 A FullArgSpec with empty kwonlyargs, kwonlydefaults and annotations.
97 """
98 return _convert_maybe_argspec_to_fullargspec(getargspec(target))
101def currentframe():
102 """TFDecorator-aware replacement for inspect.currentframe."""
103 return _inspect.stack()[1][0]
106def getargspec(obj):
107 """TFDecorator-aware replacement for `inspect.getargspec`.
109 Note: `getfullargspec` is recommended as the python 2/3 compatible
110 replacement for this function.
112 Args:
113 obj: A function, partial function, or callable object, possibly decorated.
115 Returns:
116 The `ArgSpec` that describes the signature of the outermost decorator that
117 changes the callable's signature, or the `ArgSpec` that describes
118 the object if not decorated.
120 Raises:
121 ValueError: When callable's signature can not be expressed with
122 ArgSpec.
123 TypeError: For objects of unsupported types.
124 """
125 if isinstance(obj, functools.partial):
126 return _get_argspec_for_partial(obj)
128 decorators, target = tf_decorator.unwrap(obj)
130 spec = next((d.decorator_argspec
131 for d in decorators
132 if d.decorator_argspec is not None), None)
133 if spec:
134 return spec
136 try:
137 # Python3 will handle most callables here (not partial).
138 return _getargspec(target)
139 except TypeError:
140 pass
142 if isinstance(target, type):
143 try:
144 return _getargspec(target.__init__)
145 except TypeError:
146 pass
148 try:
149 return _getargspec(target.__new__)
150 except TypeError:
151 pass
153 # The `type(target)` ensures that if a class is received we don't return
154 # the signature of its __call__ method.
155 return _getargspec(type(target).__call__)
158def _get_argspec_for_partial(obj):
159 """Implements `getargspec` for `functools.partial` objects.
161 Args:
162 obj: The `functools.partial` object
163 Returns:
164 An `inspect.ArgSpec`
165 Raises:
166 ValueError: When callable's signature can not be expressed with
167 ArgSpec.
168 """
169 # When callable is a functools.partial object, we construct its ArgSpec with
170 # following strategy:
171 # - If callable partial contains default value for positional arguments (ie.
172 # object.args), then final ArgSpec doesn't contain those positional arguments.
173 # - If callable partial contains default value for keyword arguments (ie.
174 # object.keywords), then we merge them with wrapped target. Default values
175 # from callable partial takes precedence over those from wrapped target.
176 #
177 # However, there is a case where it is impossible to construct a valid
178 # ArgSpec. Python requires arguments that have no default values must be
179 # defined before those with default values. ArgSpec structure is only valid
180 # when this presumption holds true because default values are expressed as a
181 # tuple of values without keywords and they are always assumed to belong to
182 # last K arguments where K is number of default values present.
183 #
184 # Since functools.partial can give default value to any argument, this
185 # presumption may no longer hold in some cases. For example:
186 #
187 # def func(m, n):
188 # return 2 * m + n
189 # partialed = functools.partial(func, m=1)
190 #
191 # This example will result in m having a default value but n doesn't. This is
192 # usually not allowed in Python and can not be expressed in ArgSpec correctly.
193 #
194 # Thus, we must detect cases like this by finding first argument with default
195 # value and ensures all following arguments also have default values. When
196 # this is not true, a ValueError is raised.
198 n_prune_args = len(obj.args)
199 partial_keywords = obj.keywords or {}
201 args, varargs, keywords, defaults = getargspec(obj.func)
203 # Pruning first n_prune_args arguments.
204 args = args[n_prune_args:]
206 # Partial function may give default value to any argument, therefore length
207 # of default value list must be len(args) to allow each argument to
208 # potentially be given a default value.
209 no_default = object()
210 all_defaults = [no_default] * len(args)
212 if defaults:
213 all_defaults[-len(defaults):] = defaults
215 # Fill in default values provided by partial function in all_defaults.
216 for kw, default in partial_keywords.items():
217 if kw in args:
218 idx = args.index(kw)
219 all_defaults[idx] = default
220 elif not keywords:
221 raise ValueError('Function does not have **kwargs parameter, but '
222 'contains an unknown partial keyword.')
224 # Find first argument with default value set.
225 first_default = next(
226 (idx for idx, x in enumerate(all_defaults) if x is not no_default), None)
228 # If no default values are found, return ArgSpec with defaults=None.
229 if first_default is None:
230 return ArgSpec(args, varargs, keywords, None)
232 # Checks if all arguments have default value set after first one.
233 invalid_default_values = [
234 args[i] for i, j in enumerate(all_defaults)
235 if j is no_default and i > first_default
236 ]
238 if invalid_default_values:
239 raise ValueError('Some arguments %s do not have default value, but they '
240 'are positioned after those with default values. This can '
241 'not be expressed with ArgSpec.' % invalid_default_values)
243 return ArgSpec(args, varargs, keywords, tuple(all_defaults[first_default:]))
246def getfullargspec(obj):
247 """TFDecorator-aware replacement for `inspect.getfullargspec`.
249 This wrapper emulates `inspect.getfullargspec` in[^)]* Python2.
251 Args:
252 obj: A callable, possibly decorated.
254 Returns:
255 The `FullArgSpec` that describes the signature of
256 the outermost decorator that changes the callable's signature. If the
257 callable is not decorated, `inspect.getfullargspec()` will be called
258 directly on the callable.
259 """
260 decorators, target = tf_decorator.unwrap(obj)
262 for d in decorators:
263 if d.decorator_argspec is not None:
264 return _convert_maybe_argspec_to_fullargspec(d.decorator_argspec)
265 return _getfullargspec(target)
268def getcallargs(*func_and_positional, **named):
269 """TFDecorator-aware replacement for inspect.getcallargs.
271 Args:
272 *func_and_positional: A callable, possibly decorated, followed by any
273 positional arguments that would be passed to `func`.
274 **named: The named argument dictionary that would be passed to `func`.
276 Returns:
277 A dictionary mapping `func`'s named arguments to the values they would
278 receive if `func(*positional, **named)` were called.
280 `getcallargs` will use the argspec from the outermost decorator that provides
281 it. If no attached decorators modify argspec, the final unwrapped target's
282 argspec will be used.
283 """
284 func = func_and_positional[0]
285 positional = func_and_positional[1:]
286 argspec = getfullargspec(func)
287 call_args = named.copy()
288 this = getattr(func, 'im_self', None) or getattr(func, '__self__', None)
289 if ismethod(func) and this:
290 positional = (this,) + positional
291 remaining_positionals = [arg for arg in argspec.args if arg not in call_args]
292 call_args.update(dict(zip(remaining_positionals, positional)))
293 default_count = 0 if not argspec.defaults else len(argspec.defaults)
294 if default_count:
295 for arg, value in zip(argspec.args[-default_count:], argspec.defaults):
296 if arg not in call_args:
297 call_args[arg] = value
298 if argspec.kwonlydefaults is not None:
299 for k, v in argspec.kwonlydefaults.items():
300 if k not in call_args:
301 call_args[k] = v
302 return call_args
305def getframeinfo(*args, **kwargs):
306 return _inspect.getframeinfo(*args, **kwargs)
309def getdoc(object): # pylint: disable=redefined-builtin
310 """TFDecorator-aware replacement for inspect.getdoc.
312 Args:
313 object: An object, possibly decorated.
315 Returns:
316 The docstring associated with the object.
318 The outermost-decorated object is intended to have the most complete
319 documentation, so the decorated parameter is not unwrapped.
320 """
321 return _inspect.getdoc(object)
324def getfile(object): # pylint: disable=redefined-builtin
325 """TFDecorator-aware replacement for inspect.getfile."""
326 unwrapped_object = tf_decorator.unwrap(object)[1]
328 # Work around for the case when object is a stack frame
329 # and only .pyc files are used. In this case, getfile
330 # might return incorrect path. So, we get the path from f_globals
331 # instead.
332 if (hasattr(unwrapped_object, 'f_globals') and
333 '__file__' in unwrapped_object.f_globals):
334 return unwrapped_object.f_globals['__file__']
335 return _inspect.getfile(unwrapped_object)
338def getmembers(object, predicate=None): # pylint: disable=redefined-builtin
339 """TFDecorator-aware replacement for inspect.getmembers."""
340 return _inspect.getmembers(object, predicate)
343def getmodule(object): # pylint: disable=redefined-builtin
344 """TFDecorator-aware replacement for inspect.getmodule."""
345 return _inspect.getmodule(object)
348def getmro(cls):
349 """TFDecorator-aware replacement for inspect.getmro."""
350 return _inspect.getmro(cls)
353def getsource(object): # pylint: disable=redefined-builtin
354 """TFDecorator-aware replacement for inspect.getsource."""
355 return _inspect.getsource(tf_decorator.unwrap(object)[1])
358def getsourcefile(object): # pylint: disable=redefined-builtin
359 """TFDecorator-aware replacement for inspect.getsourcefile."""
360 return _inspect.getsourcefile(tf_decorator.unwrap(object)[1])
363def getsourcelines(object): # pylint: disable=redefined-builtin
364 """TFDecorator-aware replacement for inspect.getsourcelines."""
365 return _inspect.getsourcelines(tf_decorator.unwrap(object)[1])
368def isbuiltin(object): # pylint: disable=redefined-builtin
369 """TFDecorator-aware replacement for inspect.isbuiltin."""
370 return _inspect.isbuiltin(tf_decorator.unwrap(object)[1])
373def isclass(object): # pylint: disable=redefined-builtin
374 """TFDecorator-aware replacement for inspect.isclass."""
375 return _inspect.isclass(tf_decorator.unwrap(object)[1])
378def isfunction(object): # pylint: disable=redefined-builtin
379 """TFDecorator-aware replacement for inspect.isfunction."""
380 return _inspect.isfunction(tf_decorator.unwrap(object)[1])
383def isframe(object): # pylint: disable=redefined-builtin
384 """TFDecorator-aware replacement for inspect.ismodule."""
385 return _inspect.isframe(tf_decorator.unwrap(object)[1])
388def isgenerator(object): # pylint: disable=redefined-builtin
389 """TFDecorator-aware replacement for inspect.isgenerator."""
390 return _inspect.isgenerator(tf_decorator.unwrap(object)[1])
393def isgeneratorfunction(object): # pylint: disable=redefined-builtin
394 """TFDecorator-aware replacement for inspect.isgeneratorfunction."""
395 return _inspect.isgeneratorfunction(tf_decorator.unwrap(object)[1])
398def ismethod(object): # pylint: disable=redefined-builtin
399 """TFDecorator-aware replacement for inspect.ismethod."""
400 return _inspect.ismethod(tf_decorator.unwrap(object)[1])
403def ismodule(object): # pylint: disable=redefined-builtin
404 """TFDecorator-aware replacement for inspect.ismodule."""
405 return _inspect.ismodule(tf_decorator.unwrap(object)[1])
408def isroutine(object): # pylint: disable=redefined-builtin
409 """TFDecorator-aware replacement for inspect.isroutine."""
410 return _inspect.isroutine(tf_decorator.unwrap(object)[1])
413def stack(context=1):
414 """TFDecorator-aware replacement for inspect.stack."""
415 return _inspect.stack(context)[1:]