Beispiel #1
0
    def visit_Call(self, node):
        full_name = str(anno.getanno(node.func, anno.Basic.QN, default=''))
        function_context_name = self.state[_Function].context_name
        node = self.generic_visit(node)

        # TODO(mdan): Refactor converted_call as a 'Call' operator.

        # Calls to the internal 'ag__' module are never converted (though their
        # arguments might be).
        if full_name.startswith('ag__.'):
            return node

        # Calls to the function context manager (inserted by function_scopes) are
        # also safe.
        if full_name.startswith(function_context_name + '.'):
            return node

        # Calls to pdb.set_trace or ipdb.set_trace are never converted. We don't use
        # the normal mechanisms to bypass these literals because they are sensitive
        # to the frame they are being called from.
        # TODO(mdan): Generalize this to a "static allowlist" config.
        if full_name in ('pdb.set_trace', 'ipdb.set_trace', 'breakpoint'):
            global set_trace_warned
            if not set_trace_warned:
                # TODO(mdan): Update and shorten once available on tensorflow.org.
                ag_logging.warning(
                    'Detected `pdb.set_trace()` in user code. The code'
                    ' generated by AutoGraph is not optimized for step-by-step'
                    ' debugging. See https://github.com/tensorflow/tensorflow/'
                    'blob/master/tensorflow/python/autograph/g3doc/reference/'
                    'debugging.md.')
                set_trace_warned = True
            return node

        if (full_name == 'print' and not self.ctx.user.options.uses(
                converter.Feature.BUILTIN_FUNCTIONS)):
            return node

        template = """
      ag__.converted_call(func, args, kwargs, function_ctx)
    """
        new_call = templates.replace_as_expression(
            template,
            func=node.func,
            args=self._args_to_tuple(node),
            kwargs=self._kwargs_to_dict(node),
            function_ctx=function_context_name)

        return new_call
Beispiel #2
0
def is_unsupported(o):
    """Checks whether an entity is supported by AutoGraph at all."""

    # TODO(b/122265385): Remove this bypass.
    if (_is_known_loaded_type(o, 'wrapt', 'FunctionWrapper')
            or _is_known_loaded_type(o, 'wrapt', 'BoundFunctionWrapper')):
        logging.warning(
            '{} appears to be decorated by wrapt, which is not yet supported'
            ' by AutoGraph. The function will run as-is.'
            ' You may still apply AutoGraph before the wrapt decorator.'.
            format(o))
        logging.log(2, 'Permanently allowed: %s: wrapt decorated', o)
        return True

    if _is_known_loaded_type(o, 'functools', '_lru_cache_wrapper'):
        logging.log(2, 'Permanently allowed: %s: lru_cache', o)
        return True

    # Constructors are permanently allowed.
    # TODO(mdan): Toggle as experimental feature instead.
    # TODO(b/124016764): Remove this limitation.
    if inspect_utils.isconstructor(o):
        logging.log(2, 'Permanently allowed: %s: constructor', o)
        return True

    # Other built-in modules are permanently allowed.
    # TODO(mdan): Figure out how to do this consistently for all stdlib modules.
    if any(
            _is_of_known_loaded_module(o, m)
            for m in ('collections', 'pdb', 'copy', 'inspect', 're')):
        logging.log(2, 'Permanently allowed: %s: part of builtin module', o)
        return True

    # Custom ops and kernels are also permanently allowed.
    # See tensorflow.framework.load_library.
    if (hasattr(o, '__module__')
            and hasattr(o.__module__, '_IS_TENSORFLOW_PLUGIN')):
        logging.log(2, 'Permanently allowed: %s: TensorFlow plugin', o)
        return True

    return False
Beispiel #3
0
  def _verify_inefficient_unroll(self):
    """Checks for possibly-inefficient creation of ops in a Python loop."""
    assert self.ops_before_iteration is not None
    ops_after_iteration = self._get_ops()
    new_ops = tuple(
        op for op in ops_after_iteration if op not in self.ops_before_iteration)

    if len(new_ops) < INEFFICIENT_UNROLL_MIN_OPS:
      return False

    ag_logging.warning(
        'Large unrolled loop detected. Did you mean to use a TF loop?'
        ' The following ops were created after iteration %s: %s'
        '\nSee'
        ' https://github.com/tensorflow/tensorflow/blob/master/'
        'tensorflow/python/autograph/g3doc/reference/common_errors.md'
        '#warning-large-unrolled-loop-detected'
        '\n'
        'Location:'
        '\n%s'
        '', self.iterations, new_ops, '\n'.join(traceback.format_stack()))
    return True
Beispiel #4
0
def _fall_back_unconverted(f, args, kwargs, options, exc):
    """Falls back to calling the function unconverted, in case of error."""
    # TODO(mdan): Consider adding an internal metric.
    warning_template = (
        'AutoGraph could not transform %s and will run it as-is.\n'
        '%s'
        'Cause: %s\n'
        'To silence this warning, decorate the function with'
        ' @tf.autograph.experimental.do_not_convert')
    if isinstance(exc, errors.InaccessibleSourceCodeError):
        if ag_ctx.INSPECT_SOURCE_SUPPORTED:
            logging.warning(warning_template, f, '', exc)
    elif isinstance(exc, errors.UnsupportedLanguageElementError):
        if not conversion.is_in_allowlist_cache(f, options):
            logging.warning(warning_template, f, '', exc)
    else:
        file_bug_message = (
            'Please report this to the TensorFlow team. When filing the bug, set'
            ' the verbosity to 10 (on Linux, `export AUTOGRAPH_VERBOSITY=10`) and'
            ' attach the full output.\n')
        logging.warning(warning_template, f, file_bug_message, exc)

    return _call_unconverted(f, args, kwargs, options)
Beispiel #5
0
    def __exit__(self, unused_type, unused_value, unused_traceback):
        assert _control_ctx()[-1] is self
        _control_ctx().pop()


class NullCtx(object):
    """Helper substitute for contextlib.nullcontext."""
    def __enter__(self):
        pass

    def __exit__(self, unused_type, unused_value, unused_traceback):
        pass


def _default_control_status_ctx():
    return ControlStatusCtx(status=Status.UNSPECIFIED)


INSPECT_SOURCE_SUPPORTED = True
try:
    inspect.getsource(ag_logging.log)
except OSError:
    INSPECT_SOURCE_SUPPORTED = False
    ag_logging.warning(
        'AutoGraph is not available in this environment: functions lack code'
        ' information. This is typical of some environments like the interactive'
        ' Python shell. See'
        ' https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/limitations.md#access-to-source-code'
        ' for more information.')