code: def test_custom_handler():
      class CustomStopHandler(
          event_handler.TrainBegin,
          event_handler.BatchEnd,
          event_handler.EpochEnd,
      ):
          def __init__(self, batch_stop=None, epoch_stop=None):
              self.batch_stop = batch_stop
              self.epoch_stop = epoch_stop
              self.num_batch = 0
              self.num_epoch = 0
              self.stop_training = False
  
          def train_begin(self, estimator, *args, **kwargs):
              self.num_batch = 0
              self.num_epoch = 0
  
          def batch_end(self, estimator, *args, **kwargs):
              self.num_batch += 1
              if self.num_batch == self.batch_stop:
                  self.stop_training = True
              return self.stop_training
  
          def epoch_end(self, estimator, *args, **kwargs):
              self.num_epoch += 1
              if self.num_epoch == self.epoch_stop:
                  self.stop_training = True
              return self.stop_training
  
      # total data size is 32, batch size is 8
      # 4 batch per epoch
      test_data = _get_test_data()
      net = _get_test_network()
      ce_loss = loss.SoftmaxCrossEntropyLoss()
      acc = mx.gluon.metric.Accuracy()
      est = estimator.Estimator(net, loss=ce_loss, train_metrics=acc)
      custom_handler = CustomStopHandler(3, 2)
      est.fit(test_data, event_handlers=[custom_handler], epochs=3)
      assert custom_handler.num_batch == 3
      assert custom_handler.num_epoch == 1
      custom_handler = CustomStopHandler(100, 5)
      est.fit(test_data, event_handlers=[custom_handler], epochs=10)
      assert custom_handler.num_batch == 5 * 4
      assert custom_handler.num_epoch == 5
  
imports: import os
  import logging
  import sys
  import re
  import mxnet
  from common import TemporaryDirectory
  from mxnet import np
  from mxnet.gluon import nn, loss
  from mxnet.gluon.contrib.estimator import estimator, event_handler
  from mxnet.gluon.contrib.estimator.event_handler import LoggingHandler
  from mxnet.gluon.contrib.estimator.event_handler import ValidationHandler
  from mxnet.gluon.contrib.estimator import EpochEnd
  from mxnet.gluon.data.dataset import Dataset
label_desc: Use image node_id 8 for calling a global function with example usage: test_custom_handler() and returns: self, self