





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
A_												=     "."

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





def    __UpperCamelCase      (    a,     a,     a) ->List[Any]:
					lowerCamelCase__       =       SavedModel()
					lowerCamelCase__       =       []

					with open(os.path.join(a,     "utils",     "tf_ops",     "onnx.json")) as f:
										lowerCamelCase__       =       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())

					lowerCamelCase__       =       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
					lowerCamelCase__       =       sorted(a)
					lowerCamelCase__       =       []

					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__":
						A_												=     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)"
						)
						A_												=     parser.parse_args()

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








def    __UpperCamelCase      (    a,     a) ->Optional[int]:
					lowerCamelCase__       =       [1]
					for i in range(2,     a):
										factorials.append(factorials[-1] * i)
					assert 0 <= k < factorials[-1] * n, "k out of bounds"

					lowerCamelCase__       =       []
					lowerCamelCase__       =       list(range(a))

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

					return permutation


if __name__ == "__main__":
						import doctest

						doctest.testmod()

