def testAPIBackwardsCompatibility(self):
    # Extract all API stuff.
    visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()

    public_api_visitor = public_api.PublicAPIVisitor(visitor)
    public_api_visitor.do_not_descend_map[''].append('contrib')
    traverse.traverse(tf, public_api_visitor)

    proto_dict = visitor.GetProtos()

    # Read all golden files.
    expression = os.path.join(
        resource_loader.get_root_dir_with_all_resources(),
        _KeyToFilePath('*'))
    golden_file_list = file_io.get_matching_files(expression)

    def _ReadFileToProto(filename):
      """Read a filename, create a protobuf from its contents."""
      ret_val = api_objects_pb2.TFAPIObject()
      text_format.Merge(file_io.read_file_to_string(filename), ret_val)
      return ret_val

    golden_proto_dict = {
        _FileNameToKey(filename): _ReadFileToProto(filename)
        for filename in golden_file_list
    }

    # Diff them. Do not fail if called with update.
    # If the test is run to update goldens, only report diffs but do not fail.
    self._AssertProtoDictEquals(
        golden_proto_dict,
        proto_dict,
        verbose=FLAGS.verbose_diffs,
        update_goldens=FLAGS.update_goldens)
예제 #2
0
  def checkBackwardsCompatibility(self, root, golden_file_pattern, api_version):
    # Extract all API stuff.
    visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()

    public_api_visitor = public_api.PublicAPIVisitor(visitor)
    public_api_visitor.do_not_descend_map['tf'].append('contrib')
    public_api_visitor.do_not_descend_map['tf.GPUOptions'] = ['Experimental']
    traverse.traverse(root, public_api_visitor)

    proto_dict = visitor.GetProtos()

    # Read all golden files.
    golden_file_list = file_io.get_matching_files(golden_file_pattern)

    def _ReadFileToProto(filename):
      """Read a filename, create a protobuf from its contents."""
      ret_val = api_objects_pb2.TFAPIObject()
      text_format.Merge(file_io.read_file_to_string(filename), ret_val)
      return ret_val

    golden_proto_dict = {
        _FileNameToKey(filename): _ReadFileToProto(filename)
        for filename in golden_file_list
    }

    # Diff them. Do not fail if called with update.
    # If the test is run to update goldens, only report diffs but do not fail.
    self._AssertProtoDictEquals(
        golden_proto_dict,
        proto_dict,
        verbose=FLAGS.verbose_diffs,
        update_goldens=FLAGS.update_goldens,
        api_version=api_version)
예제 #3
0
    def _checkBackwardsCompatibility(self,
                                     root,
                                     golden_file_patterns,
                                     api_version,
                                     additional_private_map=None,
                                     omit_golden_symbols_map=None):
        # Extract all API stuff.
        visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()

        public_api_visitor = public_api.PublicAPIVisitor(visitor)
        public_api_visitor.private_map['tf'].append('contrib')
        if api_version == 2:
            public_api_visitor.private_map['tf'].append('enable_v2_behavior')

        public_api_visitor.do_not_descend_map['tf.GPUOptions'] = [
            'Experimental'
        ]
        # Do not descend into these numpy classes because their signatures may be
        # different between internal and OSS.
        public_api_visitor.do_not_descend_map['tf.experimental.numpy'] = [
            'bool_', 'complex_', 'complex128', 'complex64', 'float_',
            'float16', 'float32', 'float64', 'inexact', 'int_', 'int16',
            'int32', 'int64', 'int8', 'object_', 'string_', 'uint16', 'uint32',
            'uint64', 'uint8', 'unicode_', 'iinfo'
        ]
        if FLAGS.only_test_core_api:
            public_api_visitor.do_not_descend_map['tf'].extend(
                _NON_CORE_PACKAGES)
        if additional_private_map:
            public_api_visitor.private_map.update(additional_private_map)

        traverse.traverse(root, public_api_visitor)
        proto_dict = visitor.GetProtos()

        # Read all golden files.
        golden_file_list = file_io.get_matching_files(golden_file_patterns)
        if FLAGS.only_test_core_api:
            golden_file_list = _FilterNonCoreGoldenFiles(golden_file_list)

        def _ReadFileToProto(filename):
            """Read a filename, create a protobuf from its contents."""
            ret_val = api_objects_pb2.TFAPIObject()
            text_format.Merge(file_io.read_file_to_string(filename), ret_val)
            return ret_val

        golden_proto_dict = {
            _FileNameToKey(filename): _ReadFileToProto(filename)
            for filename in golden_file_list
        }
        golden_proto_dict = _FilterGoldenProtoDict(golden_proto_dict,
                                                   omit_golden_symbols_map)

        # Diff them. Do not fail if called with update.
        # If the test is run to update goldens, only report diffs but do not fail.
        self._AssertProtoDictEquals(golden_proto_dict,
                                    proto_dict,
                                    verbose=FLAGS.verbose_diffs,
                                    update_goldens=FLAGS.update_goldens,
                                    api_version=api_version)
예제 #4
0
    def testNewAPIBackwardsCompatibility(self):
        # Extract all API stuff.
        visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()

        public_api_visitor = public_api.PublicAPIVisitor(visitor)
        public_api_visitor.do_not_descend_map['tf'].append('contrib')
        public_api_visitor.do_not_descend_map['tf.GPUOptions'] = [
            'Experimental'
        ]
        # TODO(annarev): Make slide_dataset available in API.
        public_api_visitor.private_map['tf'] = ['slide_dataset']
        traverse.traverse(api, public_api_visitor)

        proto_dict = visitor.GetProtos()

        # Read all golden files.
        expression = os.path.join(
            resource_loader.get_root_dir_with_all_resources(),
            _KeyToFilePath('*'))
        golden_file_list = file_io.get_matching_files(expression)

        def _ReadFileToProto(filename):
            """Read a filename, create a protobuf from its contents."""
            ret_val = api_objects_pb2.TFAPIObject()
            text_format.Merge(file_io.read_file_to_string(filename), ret_val)
            return ret_val

        golden_proto_dict = {
            _FileNameToKey(filename): _ReadFileToProto(filename)
            for filename in golden_file_list
        }

        # user_ops is an empty module. It is currently available in TensorFlow API
        # but we don't keep empty modules in the new API.
        # We delete user_ops from golden_proto_dict to make sure assert passes
        # when diffing new API against goldens.
        # TODO(annarev): remove user_ops from goldens once we switch to new API.
        tf_module = golden_proto_dict['tensorflow'].tf_module
        for i in range(len(tf_module.member)):
            if tf_module.member[i].name == 'user_ops':
                del tf_module.member[i]
                break

        # Diff them. Do not fail if called with update.
        # If the test is run to update goldens, only report diffs but do not fail.
        self._AssertProtoDictEquals(
            golden_proto_dict,
            proto_dict,
            verbose=FLAGS.verbose_diffs,
            update_goldens=False,
            additional_missing_object_message=
            'Check if tf_export decorator/call is missing for this symbol.')
예제 #5
0
    def _checkBackwardsCompatibility(
        self,
        root,
        golden_file_patterns,
        api_version,
        additional_private_map=None,
        omit_golden_symbols_map=None,
    ):
        # Extract all API stuff.
        visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor(
            default_path="tensorflow.keras")

        public_api_visitor = public_api.PublicAPIVisitor(visitor)
        if additional_private_map:
            public_api_visitor.private_map.update(additional_private_map)
        public_api_visitor.set_root_name("tf.keras")

        traverse.traverse(root, public_api_visitor)
        proto_dict = visitor.GetProtos()

        # Read all golden files.
        golden_file_list = tf.compat.v1.gfile.Glob(golden_file_patterns)

        def _ReadFileToProto(filename):
            """Read a filename, create a protobuf from its contents."""
            ret_val = api_objects_pb2.TFAPIObject()
            text_format.Merge(file_io.read_file_to_string(filename), ret_val)
            return ret_val

        golden_proto_dict = {
            _FileNameToKey(filename): _ReadFileToProto(filename)
            for filename in golden_file_list
        }
        golden_proto_dict = _FilterGoldenProtoDict(golden_proto_dict,
                                                   omit_golden_symbols_map)

        # Diff them. Do not fail if called with update.
        # If the test is run to update goldens, only report diffs but do not
        # fail.
        self._AssertProtoDictEquals(
            golden_proto_dict,
            proto_dict,
            verbose=FLAGS.verbose_diffs,
            update_goldens=FLAGS.update_goldens,
            api_version=api_version,
        )
  def testAPIBackwardsCompatibility(self):
    # Extract all API stuff.
    visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()

    public_api_visitor = public_api.PublicAPIVisitor(visitor)
    public_api_visitor.do_not_descend_map['tf'].append('contrib')
    public_api_visitor.do_not_descend_map['tf.GPUOptions'] = ['Experimental']
    traverse.traverse(tf, public_api_visitor)

    proto_dict = visitor.GetProtos()

    # Read all golden files.
    expression = os.path.join(
        resource_loader.get_root_dir_with_all_resources(),
        _KeyToFilePath('*'))
    golden_file_list = file_io.get_matching_files(expression)

    def _ReadFileToProto(filename):
      """Read a filename, create a protobuf from its contents."""
      ret_val = api_objects_pb2.TFAPIObject()
      text_format.Merge(file_io.read_file_to_string(filename), ret_val)
      return ret_val

    golden_proto_dict = {
        _FileNameToKey(filename): _ReadFileToProto(filename)
        for filename in golden_file_list
    }

    # TODO(annarev): remove once we switch to using tf_export decorators.
    tf_module = golden_proto_dict['tensorflow'].tf_module
    for i in range(len(tf_module.member)):
      if tf_module.member[i].name == 'math':
        del tf_module.member[i]
        break

    # Diff them. Do not fail if called with update.
    # If the test is run to update goldens, only report diffs but do not fail.
    self._AssertProtoDictEquals(
        golden_proto_dict,
        proto_dict,
        verbose=FLAGS.verbose_diffs,
        update_goldens=FLAGS.update_goldens)
  def testNewAPIBackwardsCompatibility(self):
    # Extract all API stuff.
    visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()

    public_api_visitor = public_api.PublicAPIVisitor(visitor)
    public_api_visitor.do_not_descend_map['tf'].append('contrib')
    public_api_visitor.do_not_descend_map['tf.GPUOptions'] = ['Experimental']
    # TODO(annarev): Make slide_dataset available in API.
    public_api_visitor.private_map['tf'] = ['slide_dataset']
    traverse.traverse(api, public_api_visitor)

    proto_dict = visitor.GetProtos()

    # Read all golden files.
    expression = os.path.join(
        resource_loader.get_root_dir_with_all_resources(),
        _KeyToFilePath('*'))
    golden_file_list = file_io.get_matching_files(expression)

    def _ReadFileToProto(filename):
      """Read a filename, create a protobuf from its contents."""
      ret_val = api_objects_pb2.TFAPIObject()
      text_format.Merge(file_io.read_file_to_string(filename), ret_val)
      return ret_val

    golden_proto_dict = {
        _FileNameToKey(filename): _ReadFileToProto(filename)
        for filename in golden_file_list
    }

    # Diff them. Do not fail if called with update.
    # If the test is run to update goldens, only report diffs but do not fail.
    self._AssertProtoDictEquals(
        golden_proto_dict,
        proto_dict,
        verbose=FLAGS.verbose_diffs,
        update_goldens=False,
        additional_missing_object_message=
        'Check if tf_export decorator/call is missing for this symbol.')
예제 #8
0
  def testAPIDefCompatibility(self):
    # Get base ApiDef
    name_to_base_api_def = self._GetBaseApiMap()
    snake_to_camel_graph_op_names = {
        self._GenerateLowerCaseOpName(name): name
        for name in name_to_base_api_def.keys()}
    # Extract Python API
    visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()
    public_api_visitor = public_api.PublicAPIVisitor(visitor)
    public_api_visitor.do_not_descend_map['tf'].append('contrib')
    traverse.traverse(tf, public_api_visitor)
    proto_dict = visitor.GetProtos()

    # Map from file path to Python ApiDefs.
    new_api_defs_map = defaultdict(api_def_pb2.ApiDefs)
    # We need to override all endpoints even if 1 endpoint differs from base
    # ApiDef. So, we first create a map from an op to all its endpoints.
    op_to_endpoint_name = defaultdict(list)

    # Generate map from generated python op to endpoint names.
    for public_module, value in proto_dict.items():
      module_obj = _GetSymbol(public_module)
      for sym in value.tf_module.member_method:
        obj = getattr(module_obj, sym.name)

        # Check if object is defined in gen_* module. That is,
        # the object has been generated from OpDef.
        if hasattr(obj, '__module__') and _IsGenModule(obj.__module__):
          if obj.__name__ not in snake_to_camel_graph_op_names:
            # Symbol might be defined only in Python and not generated from
            # C++ api.
            continue
          relative_public_module = public_module[len('tensorflow.'):]
          full_name = (relative_public_module + '.' + sym.name
                       if relative_public_module else sym.name)
          op_to_endpoint_name[obj].append(full_name)

    # Generate Python ApiDef overrides.
    for op, endpoint_names in op_to_endpoint_name.items():
      graph_op_name = snake_to_camel_graph_op_names[op.__name__]
      api_def = self._CreatePythonApiDef(
          name_to_base_api_def[graph_op_name], endpoint_names)

      if api_def:
        file_path = _GetApiDefFilePath(graph_op_name)
        api_defs = new_api_defs_map[file_path]
        api_defs.op.extend([api_def])

    self._AddHiddenOpOverrides(name_to_base_api_def, new_api_defs_map)

    old_api_defs_map = _GetGoldenApiDefs()
    for file_path, new_api_defs in new_api_defs_map.items():
      # Get new ApiDef string.
      new_api_defs_str = str(new_api_defs)

      # Get current ApiDef for the given file.
      old_api_defs_str = (
          old_api_defs_map[file_path] if file_path in old_api_defs_map else '')

      if old_api_defs_str == new_api_defs_str:
        continue

      if FLAGS.update_goldens:
        logging.info('Updating %s...' % file_path)
        file_io.write_string_to_file(file_path, new_api_defs_str)
      else:
        self.assertMultiLineEqual(
            old_api_defs_str, new_api_defs_str,
            'To update golden API files, run api_compatibility_test locally '
            'with --update_goldens=True flag.')

    for file_path in set(old_api_defs_map) - set(new_api_defs_map):
      if FLAGS.update_goldens:
        logging.info('Deleting %s...' % file_path)
        file_io.delete_file(file_path)
      else:
        self.fail(
            '%s file is no longer needed and should be removed.'
            'To update golden API files, run api_compatibility_test locally '
            'with --update_goldens=True flag.' % file_path)
    def testAPIDefCompatibility(self):
        # Get base ApiDef
        name_to_base_api_def = self._GetBaseApiMap()
        # Extract Python API
        visitor = python_object_to_proto_visitor.PythonObjectToProtoVisitor()
        public_api_visitor = public_api.PublicAPIVisitor(visitor)
        public_api_visitor.do_not_descend_map['tf'].append('contrib')
        traverse.traverse(tf, public_api_visitor)
        proto_dict = visitor.GetProtos()

        # Map from first character of op name to Python ApiDefs.
        api_def_map = defaultdict(api_def_pb2.ApiDefs)
        # We need to override all endpoints even if 1 endpoint differs from base
        # ApiDef. So, we first create a map from an op to all its endpoints.
        op_to_endpoint_name = defaultdict(list)

        # Generate map from generated python op to endpoint names.
        for public_module, value in proto_dict.items():
            module_obj = _GetSymbol(public_module)
            for sym in value.tf_module.member_method:
                obj = getattr(module_obj, sym.name)

                # Check if object is defined in gen_* module. That is,
                # the object has been generated from OpDef.
                if hasattr(obj, '__module__') and _IsGenModule(obj.__module__):
                    if obj.__name__ not in name_to_base_api_def:
                        # Symbol might be defined only in Python and not generated from
                        # C++ api.
                        continue
                    relative_public_module = public_module[len('tensorflow.'):]
                    full_name = (relative_public_module + '.' + sym.name
                                 if relative_public_module else sym.name)
                    op_to_endpoint_name[obj].append(full_name)

        # Generate Python ApiDef overrides.
        for op, endpoint_names in op_to_endpoint_name.items():
            api_def = self._CreatePythonApiDef(
                name_to_base_api_def[op.__name__], endpoint_names)
            if api_def:
                api_defs = api_def_map[op.__name__[0].upper()]
                api_defs.op.extend([api_def])

        for key in _ALPHABET:
            # Get new ApiDef for the given key.
            new_api_defs_str = ''
            if key in api_def_map:
                new_api_defs = api_def_map[key]
                new_api_defs.op.sort(key=attrgetter('graph_op_name'))
                new_api_defs_str = str(new_api_defs)

            # Get current ApiDef for the given key.
            api_defs_file_path = os.path.join(_PYTHON_API_DIR,
                                              'api_def_%s.pbtxt' % key)
            old_api_defs_str = ''
            if file_io.file_exists(api_defs_file_path):
                old_api_defs_str = file_io.read_file_to_string(
                    api_defs_file_path)

            if old_api_defs_str == new_api_defs_str:
                continue

            if FLAGS.update_goldens:
                if not new_api_defs_str:
                    logging.info('Deleting %s...' % api_defs_file_path)
                    file_io.delete_file(api_defs_file_path)
                else:
                    logging.info('Updating %s...' % api_defs_file_path)
                    file_io.write_string_to_file(api_defs_file_path,
                                                 new_api_defs_str)
            else:
                self.assertMultiLineEqual(
                    old_api_defs_str, new_api_defs_str,
                    'To update golden API files, run api_compatibility_test locally '
                    'with --update_goldens=True flag.')