




'''simple docstring'''


import argparse
import json
import os

from tensorflow.core.protobuf.saved_model_pba import SavedModel


# All paths are set with the intent you should run this script from the root of the repo with the command
# python utils/check_copies.py
_lowercase  =			"""."""

# Internal TensorFlow ops that can be safely ignored (mostly specific to a saved model)
_lowercase  =			[
    """Assert""",
    """AssignVariableOp""",
    """EmptyTensorList""",
    """MergeV2Checkpoints""",
    """ReadVariableOp""",
    """ResourceGather""",
    """RestoreV2""",
    """SaveV2""",
    """ShardedFilename""",
    """StatefulPartitionedCall""",
    """StaticRegexFullMatch""",
    """VarHandleOp""",
]
def 						lowerCamelCase__   (				a    ,	a    ,	a							):
						__snake_case						 =   SavedModel()
						__snake_case						 =   []

						with open(os.path.join(a    ,	'utils'    ,	'tf_ops'    ,	'onnx.json'							)							) as f:
												__snake_case						 =   json.load(a							)['opsets']

						for i in range(1    ,	opset + 1							):
												onnx_ops.extend(onnx_opsets[str(a							)]							)

						with open(a    ,	'rb'							) as f:
												saved_model.ParseFromString(f.read()							)

						__snake_case						 =   set()

						# Iterate over every metagraph in case there is more than one (a saved model can contain multiple graphs)
						for meta_graph in saved_model.meta_graphs:
												# Add operations in the graph definition
												model_op_names.update(node.op for node in meta_graph.graph_def.node							)

												# Go through the functions in the graph definition
												for func in meta_graph.graph_def.library.function:
																		# Add operations in each function
																		model_op_names.update(node.op for node in func.node_def							)

    # Convert to list, sorted if you want
						__snake_case						 =   sorted(a							)
						__snake_case						 =   []

						for op in model_op_names:
												if op not in onnx_ops and op not in INTERNAL_OPS:
																		incompatible_ops.append(a							)

						if strict and len(a							) > 0:
												raise Exception(f'Found the following incompatible ops for the opset {opset}:\n' + incompatible_ops							)
						elif len(a							) > 0:
												print(f'Found the following incompatible ops for the opset {opset}:'							)
												print(*a    ,	sep='\n'							)
						else:
												print(f'The saved model {saved_model_path} can properly be converted with ONNX.'							)


if __name__ == "__main__":
	_lowercase  =			argparse.ArgumentParser()
	parser.add_argument("""--saved_model_path""", help="""Path of the saved model to check (the .pb file).""")
	parser.add_argument(
	    """--opset""", default=12, type=int, help="""The ONNX opset against which the model has to be tested."""
	)
	parser.add_argument(
	    """--framework""", choices=["""onnx"""], default="""onnx""", help="""Frameworks against which to test the saved model."""
	)
	parser.add_argument(
	    """--strict""", action="""store_true""", help="""Whether make the checking strict (raise errors) or not (raise warnings)"""
	)
	_lowercase  =			parser.parse_args()

	if args.framework == "onnx":
		onnx_compliancy(args.saved_model_path, args.strict, args.opset)







'''simple docstring'''


def 						lowerCamelCase__   (				a							):
						assert (
						    isinstance(a    ,	a							) and number_of_steps > 0
						), f'number_of_steps needs to be positive integer, your input {number_of_steps}'
						if number_of_steps == 1:
												return 1
						__snake_case ,       __snake_case						 =   1, 1
						for _ in range(number_of_steps - 1							):
												__snake_case ,       __snake_case						 =   current + previous, current
						return current


if __name__ == "__main__":
	import doctest

	doctest.testmod()

