# Path: ebu_tt_live/carriage/interface.py
# class IProducerCarriage(ICarriageMechanism):
#     """
#     Carriage mechanism interface for producer nodes.
#     """
# 
#     _expects = AbstractStaticMember(validate_types_only)
# 
#     @classmethod
#     def expects(cls):
#         """
#         Data type expected
# 
#         :return:
#         """
#         if isinstance(cls._expects, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_expects\'')
#         return cls._expects
# 
#     @abstractmethod
#     def register_producer_node(self, node):
#         """
#         Register the producer node in the carriage mechanism
# 
#         :param node: The node to connect to.
# 
#         """
# 
#     @abstractproperty
#     def producer_node(self):
#         """
#         Node accessor
# 
#         :return:
#         """
# 
#     @abstractmethod
#     def emit_data(self, data, **kwargs):
#         """
#         Implement protocol specific postprocessing here.
# 
#         :param kwargs: Extra parameters to send down
#         :param data:
#         :return:
#         """
# 
#     @abstractmethod
#     def resume_producing(self):
#         """
#         This makes sure that the producers can be pulled. This is good for timer or manual triggering
# 
#         :return:
#         """
# 
# class IConsumerCarriage(ICarriageMechanism):
#     """
#     Carriage mechanism interface for consumer nodes.
#     """
# 
#     _provides = AbstractStaticMember(validate_types_only)
# 
#     @classmethod
#     def provides(cls):
#         """
#         Data type provided
# 
#         :return:
#         """
#         if isinstance(cls._provides, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_provides\'')
#         return cls._provides
# 
#     @abstractmethod
#     def register_consumer_node(self, node):
#         """
#         Register the consumer node in the carriage mechanism
# 
#         :param node:
#         :return:
#         """
# 
#     @abstractproperty
#     def consumer_node(self):
#         """
#         Node accessor
# 
#         :return:
#         """
# 
#     @abstractmethod
#     def on_new_data(self, data, **kwargs):
#         """
#         Implement protocol specific preprocessing here.
# 
#         :param kwargs: Extra parameters to send down
# 
#         """
# 
# Path: ebu_tt_live/node/interface.py
# class IProducerNode(INode):
# 
#     _provides = AbstractStaticMember(validate_types_only)
# 
#     @abstractmethod
#     def resume_producing(self):
#         """
#         This allows the node to be triggered by events, such as a timer.
#         """
# 
#     @classmethod
#     def provides(cls):
#         """
#         Data type provided
#         :return:
#         """
#         if isinstance(cls._provides, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_provides\'')
#         return cls._provides
# 
#     @abstractproperty
#     def producer_carriage(self):
#         """
#         Carriage mechanism accessor
#         :return:
#         """
# 
#     @abstractmethod
#     def register_producer_carriage(self, producer_carriage):
#         """
#         Output carriage mechanism registration
#         :param producer_carriage:
#         """
# 
# class IConsumerNode(INode):
# 
#     _expects = AbstractStaticMember(validate_types_only)
# 
#     @classmethod
#     def expects(cls):
#         """
#         Data type expected
#         :return:
#         """
#         if isinstance(cls._expects, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_expects\'')
#         return cls._expects
# 
#     @abstractproperty
#     def consumer_carriage(self):
#         """
#         Carriage mechanism accessor
#         :return:
#         """
# 
#     @abstractmethod
#     def register_consumer_carriage(self, consumer_carriage):
#         """
#         Input carriage mechanism registration
#         :param consumer_carriage:
#         """
# 
# Path: ebu_tt_live/documents/base.py
# class SubtitleDocument(ComparableMixin):
# 
#     def __init__(self):
#         raise NotImplementedError('This is an abstract class')
# 
#     def validate(self):
#         raise NotImplementedError()
# 
# Path: ebu_tt_live/errors.py
# class ComponentCompatError(TypeError):
#     pass
# 
# class DataCompatError(TypeError):
#     pass
# 
# Path: ebu_tt_live/strings.py
# ERR_INCOMPATIBLE_COMPONENT = gettext('Incompatible component: {component} Expected interface: {expected_interface}')
# 
# ERR_INCOMPATIBLE_DATA_EXPECTED = gettext('{component} expects incompatible data type: {expects} Provided type: {provides}')
# 
# ERR_INCOMPATIBLE_DATA_PROVIDED = gettext('{component} provides incompatible data type: {provides} Expected type: {expects}')


from .interface import IProducerCarriage, IConsumerCarriage
from ebu_tt_live.node.interface import IProducerNode, IConsumerNode
from ebu_tt_live.documents import SubtitleDocument
from ebu_tt_live.errors import ComponentCompatError, DataCompatError
from ebu_tt_live.strings import ERR_INCOMPATIBLE_COMPONENT, ERR_INCOMPATIBLE_DATA_EXPECTED, \
    ERR_INCOMPATIBLE_DATA_PROVIDED
                ERR_INCOMPATIBLE_COMPONENT.format(
                    component=node,
                    expected_interface=IProducerNode
                )
            )
        if self.expects() != node.provides():
            raise DataCompatError(
                ERR_INCOMPATIBLE_DATA_EXPECTED.format(
                    component=node,
                    expects=self.expects(),
                    provides=node.provides()
                )
            )
        self._producer_node = node

    @property
    def producer_node(self):
        return self._producer_node

    def resume_producing(self):
        self.producer_node.resume_producing()


class AbstractConsumerCarriage(IConsumerCarriage, AbstractCarriage):

    _consumer_node = None

    def register_consumer_node(self, node):
        if not isinstance(node, IConsumerNode):
            raise ComponentCompatError(

# Path: ebu_tt_live/carriage/interface.py
# class IProducerCarriage(ICarriageMechanism):
#     """
#     Carriage mechanism interface for producer nodes.
#     """
# 
#     _expects = AbstractStaticMember(validate_types_only)
# 
#     @classmethod
#     def expects(cls):
#         """
#         Data type expected
# 
#         :return:
#         """
#         if isinstance(cls._expects, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_expects\'')
#         return cls._expects
# 
#     @abstractmethod
#     def register_producer_node(self, node):
#         """
#         Register the producer node in the carriage mechanism
# 
#         :param node: The node to connect to.
# 
#         """
# 
#     @abstractproperty
#     def producer_node(self):
#         """
#         Node accessor
# 
#         :return:
#         """
# 
#     @abstractmethod
#     def emit_data(self, data, **kwargs):
#         """
#         Implement protocol specific postprocessing here.
# 
#         :param kwargs: Extra parameters to send down
#         :param data:
#         :return:
#         """
# 
#     @abstractmethod
#     def resume_producing(self):
#         """
#         This makes sure that the producers can be pulled. This is good for timer or manual triggering
# 
#         :return:
#         """
# 
# class IConsumerCarriage(ICarriageMechanism):
#     """
#     Carriage mechanism interface for consumer nodes.
#     """
# 
#     _provides = AbstractStaticMember(validate_types_only)
# 
#     @classmethod
#     def provides(cls):
#         """
#         Data type provided
# 
#         :return:
#         """
#         if isinstance(cls._provides, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_provides\'')
#         return cls._provides
# 
#     @abstractmethod
#     def register_consumer_node(self, node):
#         """
#         Register the consumer node in the carriage mechanism
# 
#         :param node:
#         :return:
#         """
# 
#     @abstractproperty
#     def consumer_node(self):
#         """
#         Node accessor
# 
#         :return:
#         """
# 
#     @abstractmethod
#     def on_new_data(self, data, **kwargs):
#         """
#         Implement protocol specific preprocessing here.
# 
#         :param kwargs: Extra parameters to send down
# 
#         """
# 
# Path: ebu_tt_live/node/interface.py
# class IProducerNode(INode):
# 
#     _provides = AbstractStaticMember(validate_types_only)
# 
#     @abstractmethod
#     def resume_producing(self):
#         """
#         This allows the node to be triggered by events, such as a timer.
#         """
# 
#     @classmethod
#     def provides(cls):
#         """
#         Data type provided
#         :return:
#         """
#         if isinstance(cls._provides, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_provides\'')
#         return cls._provides
# 
#     @abstractproperty
#     def producer_carriage(self):
#         """
#         Carriage mechanism accessor
#         :return:
#         """
# 
#     @abstractmethod
#     def register_producer_carriage(self, producer_carriage):
#         """
#         Output carriage mechanism registration
#         :param producer_carriage:
#         """
# 
# class IConsumerNode(INode):
# 
#     _expects = AbstractStaticMember(validate_types_only)
# 
#     @classmethod
#     def expects(cls):
#         """
#         Data type expected
#         :return:
#         """
#         if isinstance(cls._expects, AbstractStaticMember):
#             raise TypeError('Classmethod relies on abstract property: \'_expects\'')
#         return cls._expects
# 
#     @abstractproperty
#     def consumer_carriage(self):
#         """
#         Carriage mechanism accessor
#         :return:
#         """
# 
#     @abstractmethod
#     def register_consumer_carriage(self, consumer_carriage):
#         """
#         Input carriage mechanism registration
#         :param consumer_carriage:
#         """
# 
# Path: ebu_tt_live/documents/base.py
# class SubtitleDocument(ComparableMixin):
# 
#     def __init__(self):
#         raise NotImplementedError('This is an abstract class')
# 
#     def validate(self):
#         raise NotImplementedError()
# 
# Path: ebu_tt_live/errors.py
# class ComponentCompatError(TypeError):
#     pass
# 
# class DataCompatError(TypeError):
#     pass
# 
# Path: ebu_tt_live/strings.py
# ERR_INCOMPATIBLE_COMPONENT = gettext('Incompatible component: {component} Expected interface: {expected_interface}')
# 
# ERR_INCOMPATIBLE_DATA_EXPECTED = gettext('{component} expects incompatible data type: {expects} Provided type: {provides}')
# 
# ERR_INCOMPATIBLE_DATA_PROVIDED = gettext('{component} provides incompatible data type: {provides} Expected type: {expects}')


# Path: ebu_tt_live/carriage/base.py
from .interface import IProducerCarriage, IConsumerCarriage
from ebu_tt_live.node.interface import IProducerNode, IConsumerNode
from ebu_tt_live.documents import SubtitleDocument
from ebu_tt_live.errors import ComponentCompatError, DataCompatError
from ebu_tt_live.strings import ERR_INCOMPATIBLE_COMPONENT, ERR_INCOMPATIBLE_DATA_EXPECTED, \
    ERR_INCOMPATIBLE_DATA_PROVIDED

                ERR_INCOMPATIBLE_COMPONENT.format(
                    component=node,
                    expected_interface=IProducerNode
                )
            )
        if self.expects() != node.provides():
            raise DataCompatError(
                ERR_INCOMPATIBLE_DATA_EXPECTED.format(
                    component=node,
                    expects=self.expects(),
                    provides=node.provides()
                )
            )
        self._producer_node = node

    @property
    def producer_node(self):
        return self._producer_node

    def resume_producing(self):
        self.producer_node.resume_producing()


class AbstractConsumerCarriage(IConsumerCarriage, AbstractCarriage):

    _consumer_node = None

    def register_consumer_node(self, node):
        if not isinstance(node, IConsumerNode):
            raise ComponentCompatError(

                ERR_INCOMPATIBLE_COMPONENT.format(