# Path: tensorflow_transform/py_func/pyfunc_helper.py
# _PYFUNC_COLLECTION_KEY = 'pyfuncs'
# class _PyFuncDef(tfx_namedtuple.namedtuple('_PyFuncDef', ['token', 'func'])):
#   def from_proto(attr_value, import_scope=None):
#   def from_proto_string(proto_str, import_scope=None):
#   def to_proto(self, export_scope=None):
# def insert_pyfunc(func, Tout, stateful, name, *args):  # pylint: disable=invalid-name
# def register_pyfuncs_from_saved_transform(graph, meta_graph, loaded_in_tf2):
# 
# Path: tensorflow_transform/saved/constants.py
# TRANSFORM_TAG = 'transform'
# TRANSFORM_SIGNATURE = 'transform_signature'
# 
# Path: tensorflow_transform/saved/saved_model_loader.py
# def parse_saved_model(saved_model_dir):
# def _choose_meta_graph_def_internal(saved_model, tags):
# def choose_meta_graph_def(saved_model):
# def choose_meta_graph_def_and_raise(saved_model):
# def get_asset_tensors(saved_model_dir, meta_graph_def_to_load):


import importlib
import os
import re
import tensorflow as tf
from tensorflow_transform.py_func import pyfunc_helper
from tensorflow_transform.saved import constants
from tensorflow_transform.saved import saved_model_loader
from tensorflow.core.protobuf import struct_pb2
from tensorflow.python.framework import ops
from tensorflow.python.saved_model import nested_structure_coder
from tensorflow.python.training import saver as tf_saver
  # Check for inputs that were not part of the input signature.
  unexpected_inputs = (
      set(logical_input_map.keys()) - set(input_signature.keys()))
  if unexpected_inputs:
    raise ValueError('Unexpected inputs '
                     'to transform: {}'.format(unexpected_inputs))

  # Create a map from tensor names in the graph to be imported, to the tensors
  # specified in `input_tensors`.
  input_map = _expand_input_map(logical_input_map, input_signature)

  input_map.update(asset_tensor_dict)
  if tensor_replacement_map:
    input_map.update(tensor_replacement_map)

  # unique_name may produce e.g. transform_5.  The result has no trailing slash.
  scope = graph.unique_name('transform', mark_as_used=False)

  # unique_name returns an "absolute" name while we want a name relative to the
  # current scope.  Therefore, we check if the current name stack is non-empty,
  # and if so, strip out the existing name scope.
  if graph.get_name_scope():
    current_name_scope = graph.get_name_scope() + '/'
    assert scope.startswith(current_name_scope)
    import_scope = scope[len(current_name_scope):]
  else:
    import_scope = scope

  # If the saved_model contained py_funcs, will reinsert them in the graph
  # here and update their associated token in the model.

# Path: tensorflow_transform/py_func/pyfunc_helper.py
# _PYFUNC_COLLECTION_KEY = 'pyfuncs'
# class _PyFuncDef(tfx_namedtuple.namedtuple('_PyFuncDef', ['token', 'func'])):
#   def from_proto(attr_value, import_scope=None):
#   def from_proto_string(proto_str, import_scope=None):
#   def to_proto(self, export_scope=None):
# def insert_pyfunc(func, Tout, stateful, name, *args):  # pylint: disable=invalid-name
# def register_pyfuncs_from_saved_transform(graph, meta_graph, loaded_in_tf2):
# 
# Path: tensorflow_transform/saved/constants.py
# TRANSFORM_TAG = 'transform'
# TRANSFORM_SIGNATURE = 'transform_signature'
# 
# Path: tensorflow_transform/saved/saved_model_loader.py
# def parse_saved_model(saved_model_dir):
# def _choose_meta_graph_def_internal(saved_model, tags):
# def choose_meta_graph_def(saved_model):
# def choose_meta_graph_def_and_raise(saved_model):
# def get_asset_tensors(saved_model_dir, meta_graph_def_to_load):


# Path: tensorflow_transform/saved/saved_transform_io.py
import importlib
import os
import re
import tensorflow as tf
from tensorflow_transform.py_func import pyfunc_helper
from tensorflow_transform.saved import constants
from tensorflow_transform.saved import saved_model_loader
from tensorflow.core.protobuf import struct_pb2
from tensorflow.python.framework import ops
from tensorflow.python.saved_model import nested_structure_coder
from tensorflow.python.training import saver as tf_saver

  # Check for inputs that were not part of the input signature.
  unexpected_inputs = (
      set(logical_input_map.keys()) - set(input_signature.keys()))
  if unexpected_inputs:
    raise ValueError('Unexpected inputs '
                     'to transform: {}'.format(unexpected_inputs))

  # Create a map from tensor names in the graph to be imported, to the tensors
  # specified in `input_tensors`.
  input_map = _expand_input_map(logical_input_map, input_signature)

  input_map.update(asset_tensor_dict)
  if tensor_replacement_map:
    input_map.update(tensor_replacement_map)

  # unique_name may produce e.g. transform_5.  The result has no trailing slash.
  scope = graph.unique_name('transform', mark_as_used=False)

  # unique_name returns an "absolute" name while we want a name relative to the
  # current scope.  Therefore, we check if the current name stack is non-empty,
  # and if so, strip out the existing name scope.
  if graph.get_name_scope():
    current_name_scope = graph.get_name_scope() + '/'
    assert scope.startswith(current_name_scope)
    import_scope = scope[len(current_name_scope):]
  else:
    import_scope = scope

  # If the saved_model contained py_funcs, will reinsert them in the graph
  # here and update their associated token in the model.

  _ = pyfunc_helper.register_pyfuncs_from_saved_transform(