




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
SCREAMING_SNAKE_CASE:     Optional[Any]									= '''.'''

# Internal TensorFlow ops that can be safely ignored (mostly specific to a saved model)
SCREAMING_SNAKE_CASE:     Optional[Any]									= [
    '''Assert''',
    '''AssignVariableOp''',
    '''EmptyTensorList''',
    '''MergeV2Checkpoints''',
    '''ReadVariableOp''',
    '''ResourceGather''',
    '''RestoreV2''',
    '''SaveV2''',
    '''ShardedFilename''',
    '''StatefulPartitionedCall''',
    '''StaticRegexFullMatch''',
    '''VarHandleOp''',
]


def 					_a							(					lowerCAmelCase    ,						lowerCAmelCase    ,						lowerCAmelCase )->	List[Any]:
		SCREAMING_SNAKE_CASE_					      =							SavedModel()
		SCREAMING_SNAKE_CASE_					      =							[]

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

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

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

		SCREAMING_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
		SCREAMING_SNAKE_CASE_					      =							sorted(lowerCAmelCase )
		SCREAMING_SNAKE_CASE_					      =							[]

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

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


if __name__ == "__main__":
						SCREAMING_SNAKE_CASE:     Tuple									= argparse.ArgumentParser()
						parser.add_argument('''--saved_model_path''', help='''Path of the saved model to check (the .pb file).''')
						parser.add_argument(
						    '''--opset''', default=1_2, 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)'''
						)
						SCREAMING_SNAKE_CASE:     List[Any]									= parser.parse_args()

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





def 					_a							(					lowerCAmelCase    ,						lowerCAmelCase )->	List[str]:
		SCREAMING_SNAKE_CASE_					      =							[1]
		for i in range(2    ,						lowerCAmelCase ):
				factorials.append(factorials[-1] * i )
		assert 0 <= k < factorials[-1] * n, "k out of bounds"

		SCREAMING_SNAKE_CASE_					      =							[]
		SCREAMING_SNAKE_CASE_					      =							list(range(lowerCAmelCase ) )

		# Find permutation
		while factorials:
				SCREAMING_SNAKE_CASE_					      =							factorials.pop()
				SCREAMING_SNAKE_CASE_      ,				SCREAMING_SNAKE_CASE_					      =							divmod(lowerCAmelCase    ,						lowerCAmelCase )
				permutation.append(elements[number] )
				elements.remove(elements[number] )
		permutation.append(elements[0] )

		return permutation


if __name__ == "__main__":
						import doctest

						doctest.testmod()