# Path: tensorflow_transform/nodes.py
# class ValueNode(
#     tfx_namedtuple.namedtuple('ValueNode',
#                               ['parent_operation', 'value_index'])):
# class OperationDef(metaclass=abc.ABCMeta):
# class OperationNode:
# class Visitor(metaclass=abc.ABCMeta):
# class Traverser:
# class _PrintGraphVisitor(Visitor):
#   def __init__(self, parent_operation, value_index: int):
#   def __iter__(self):
#   def num_outputs(self) -> int:
#   def label(self) -> str:
#   def get_field_str(self, field_name: str) -> str:
#   def is_partitionable(self) -> bool:
#   def cache_coder(self) -> Optional[object]:
#   def __init__(self, operation_def, inputs):
#   def __repr__(self):
#   def operation_def(self):
#   def inputs(self):
#   def outputs(self):
# def apply_operation(operation_def_cls, *args, **kwargs):
# def apply_multi_output_operation(operation_def_cls, *args, **kwargs):
#   def validate_value(self, value):
#   def visit(self, operation_def, input_values):
#   def __init__(self, visitor: Visitor):
#   def visit_value_node(self, value_node: ValueNode):
#   def _maybe_visit_value_node(self, value_node: ValueNode):
#   def _visit_operation(self, operation: OperationNode):
# def _escape(line: str) -> str:
#   def __init__(self):
#   def get_dot_graph(self) -> pydot.Dot:
#   def visit(self, operation_def, input_nodes) -> Tuple[pydot.Node, ...]:
#   def validate_value(self, value: pydot.Node):
# def get_dot_graph(leaf_nodes: Collection[ValueNode]) -> pydot.Dot:


import tensorflow as tf
from tensorflow_transform import nodes
from tfx_bsl.types import tfx_namedtuple
system is used to register implementations of each individual `OperationDef`.
The `OperationDef`s defined by the user in their preprocessing_fn are all
subclasses of `AnayzerDef` (except `TensorSource`, which gets converted to
`ExtractFromDict` in `tensorflow_transform.beam.analysis_graph_builder.build`).
The subclasses of `AnalyzerDef` are defined in
`tensorflow_transform.analyzer_nodes` and are implemented in
`tensorflow_transform.beam.analyzer_impls`.

This module contains the nodes that are created by
`tensorflow_transform.beam.analysis_graph_builder.build`.  These nodes define
the parts of the beam graph that run a TensorFlow graph in a `beam.ParDo`,
extract `PCollections` containing tuples of tensors required by analyzers,
run the analyzers, and then create a new (deferred) TensorFlow graph where
the results of analyzers are replaced by constant tensors.  This happens in a
number of phases, since an analyzer might depend on a tensor that in turn
depends on the result of another analyzer.

The `OperationDef` subclasses defined here are implemented in
`tensorflow_transform.beam.impl`.
"""

# TODO(https://issues.apache.org/jira/browse/SPARK-22674): Switch to
# `collections.namedtuple` or `typing.NamedTuple` once the Spark issue is
# resolved.


class CreateTensorBinding(
    tfx_namedtuple.namedtuple(
        'CreateTensorBinding',
        ['tensor_name', 'dtype_enum', 'is_asset_filepath', 'label']),

# Path: tensorflow_transform/nodes.py
# class ValueNode(
#     tfx_namedtuple.namedtuple('ValueNode',
#                               ['parent_operation', 'value_index'])):
# class OperationDef(metaclass=abc.ABCMeta):
# class OperationNode:
# class Visitor(metaclass=abc.ABCMeta):
# class Traverser:
# class _PrintGraphVisitor(Visitor):
#   def __init__(self, parent_operation, value_index: int):
#   def __iter__(self):
#   def num_outputs(self) -> int:
#   def label(self) -> str:
#   def get_field_str(self, field_name: str) -> str:
#   def is_partitionable(self) -> bool:
#   def cache_coder(self) -> Optional[object]:
#   def __init__(self, operation_def, inputs):
#   def __repr__(self):
#   def operation_def(self):
#   def inputs(self):
#   def outputs(self):
# def apply_operation(operation_def_cls, *args, **kwargs):
# def apply_multi_output_operation(operation_def_cls, *args, **kwargs):
#   def validate_value(self, value):
#   def visit(self, operation_def, input_values):
#   def __init__(self, visitor: Visitor):
#   def visit_value_node(self, value_node: ValueNode):
#   def _maybe_visit_value_node(self, value_node: ValueNode):
#   def _visit_operation(self, operation: OperationNode):
# def _escape(line: str) -> str:
#   def __init__(self):
#   def get_dot_graph(self) -> pydot.Dot:
#   def visit(self, operation_def, input_nodes) -> Tuple[pydot.Node, ...]:
#   def validate_value(self, value: pydot.Node):
# def get_dot_graph(leaf_nodes: Collection[ValueNode]) -> pydot.Dot:


# Path: tensorflow_transform/beam/beam_nodes.py
import tensorflow as tf
from tensorflow_transform import nodes
from tfx_bsl.types import tfx_namedtuple

system is used to register implementations of each individual `OperationDef`.
The `OperationDef`s defined by the user in their preprocessing_fn are all
subclasses of `AnayzerDef` (except `TensorSource`, which gets converted to
`ExtractFromDict` in `tensorflow_transform.beam.analysis_graph_builder.build`).
The subclasses of `AnalyzerDef` are defined in
`tensorflow_transform.analyzer_nodes` and are implemented in
`tensorflow_transform.beam.analyzer_impls`.

This module contains the nodes that are created by
`tensorflow_transform.beam.analysis_graph_builder.build`.  These nodes define
the parts of the beam graph that run a TensorFlow graph in a `beam.ParDo`,
extract `PCollections` containing tuples of tensors required by analyzers,
run the analyzers, and then create a new (deferred) TensorFlow graph where
the results of analyzers are replaced by constant tensors.  This happens in a
number of phases, since an analyzer might depend on a tensor that in turn
depends on the result of another analyzer.

The `OperationDef` subclasses defined here are implemented in
`tensorflow_transform.beam.impl`.
"""

# TODO(https://issues.apache.org/jira/browse/SPARK-22674): Switch to
# `collections.namedtuple` or `typing.NamedTuple` once the Spark issue is
# resolved.


class CreateTensorBinding(
    tfx_namedtuple.namedtuple(
        'CreateTensorBinding',
        ['tensor_name', 'dtype_enum', 'is_asset_filepath', 'label']),

    nodes.OperationDef):