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)
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)
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)
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.')
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.')
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.')