code: def test_custom_module_class(self):
      class CustomModule(torch.nn.Module):
          def __init__(self):
              super().__init__()
              self.conv = torch.nn.Conv2d(1, 1, 1)
  
          def forward(self, x):
              return self.conv(x)
  
      class ObservedCustomModule(torch.nn.Module):
          def __init__(self, conv):
              super().__init__()
              self.conv = conv
  
          def forward(self, x):
              return self.conv(x)
  
          @classmethod
          def from_float(cls, float_module):
              assert hasattr(float_module, "qconfig")
              observed = cls(float_module.conv)
              observed.qconfig = float_module.qconfig
              return observed
  
      class QuantizedCustomModule(torch.nn.Module):
          def __init__(self, conv):
              super().__init__()
              self.conv = conv
  
          def forward(self, x):
              return self.conv(x)
  
          @classmethod
          def from_observed(cls, observed_module):
              assert hasattr(observed_module, "qconfig")
              assert hasattr(observed_module, "activation_post_process")
              observed_module.conv.activation_post_process = (
                  observed_module.activation_post_process
              )
              quantized = cls(
                  nnq.Conv2d.from_float(observed_module.conv)
              )
              return quantized
  
      class Sub(torch.nn.Module):
          def __init__(self):
              super().__init__()
              self.custom = CustomModule()
  
          def forward(self, x):
              return self.custom(x)
  
      class M(torch.nn.Module):
          def __init__(self):
              super().__init__()
              self.quant = QuantStub()
              self.conv = torch.nn.Conv2d(1, 1, 1)
              self.sub = Sub()
              self.dequant = DeQuantStub()
  
          def forward(self, x):
              x = self.quant(x)
              x = self.conv(x)
              x = self.sub(x)
              x = self.dequant(x)
              return x
  
      class RefM(torch.nn.Module):
          def __init__(self):
              super().__init__()
              self.quant = QuantStub()
              self.conv1 = torch.nn.Conv2d(1, 1, 1)
              self.conv2 = torch.nn.Conv2d(1, 1, 1)
              self.dequant = DeQuantStub()
  
          def forward(self, x):
              x = self.quant(x)
              x = self.conv1(x)
              x = self.conv2(x)
              x = self.dequant(x)
              return x
  
      data = torch.randn(1, 1, 1, 1)
      # instantiate M and RefM and align the parameters
      original_m = M()
      original_ref_m = RefM()
      original_ref_m.conv1.weight = torch.nn.Parameter(
          original_m.conv.weight.detach()
      )
      original_ref_m.conv1.bias = torch.nn.Parameter(
          original_m.conv.bias.detach()
      )
      original_ref_m.conv2.weight = torch.nn.Parameter(
          original_m.sub.custom.conv.weight.detach()
      )
      original_ref_m.conv2.bias = torch.nn.Parameter(
          original_m.sub.custom.conv.bias.detach()
      )
  
      original_m.qconfig = default_qconfig
      prepare_custom_config_dict = {
          "float_to_observed_custom_module_class": {
              CustomModule: ObservedCustomModule
          }
      }
      convert_custom_config_dict = {
          "observed_to_quantized_custom_module_class": {
              ObservedCustomModule: QuantizedCustomModule
          }
      }
      m = prepare(
          original_m,
          prepare_custom_config_dict=prepare_custom_config_dict,
      )
      self.checkObservers(m, None, prepare_custom_config_dict)
      # calibration
      m(data)
      # all activation observers are inserted in the top level module
  
      # check converted/quantized model
      m = convert(
          m, convert_custom_config_dict=convert_custom_config_dict
      )
      # check if the module is properly quantized
      self.assertEqual(type(m.quant), nnq.Quantize)
      self.assertEqual(type(m.conv), nnq.Conv2d)
      self.assertEqual(type(m.sub), Sub)
      self.assertEqual(type(m.sub.custom), QuantizedCustomModule)
      self.assertEqual(type(m.sub.custom.conv), nnq.Conv2d)
      self.assertEqual(type(m.dequant), nnq.DeQuantize)
      res = m(data)
  
      # quantize the reference model
      original_ref_m.eval()
      original_ref_m.qconfig = default_qconfig
      ref_m = prepare(original_ref_m)
      ref_m(data)
      ref_m = convert(ref_m)
      ref_res = ref_m(data)
      self.assertEqual(res, ref_res)
  
imports: import torch
  import torch.nn
  import torch.ao.nn.quantized
  from torch.nn.utils.rnn import PackedSequence
  from torch.ao.quantization import quantize, prepare, convert, prepare_qat, quantize_dynamic, QuantWrapper, QuantStub, DeQuantStub, default_qconfig, default_dynamic_qconfig, per_channel_dynamic_qconfig, float16_dynamic_qconfig, float_qparams_weight_only_qconfig, float_qparams_weight_only_qconfig_4bit, FixedQParamsObserver, PerChannelMinMaxObserver, default_dynamic_quant_observer, default_weight_observer, QConfig
  from torch.testing._internal.common_quantization import QuantizationTestCase, AnnotatedSingleLayerLinearModel, QuantStubModel, ModelWithFunctionals, SingleLayerLinearDynamicModel, TwoLayerLinearModel, NestedModel, ResNetBase, RNNDynamicModel, RNNCellDynamicModel, ActivationsTestModel, NormalizationTestModel, test_only_eval_fn, prepare_dynamic, convert_dynamic, skipIfNoFBGEMM, EmbeddingBagModule, EmbeddingModule, EmbeddingWithStaticLinear, LinearReluLinearModel
  from torch.testing._internal.common_quantization import AnnotatedTwoLayerLinearModel, AnnotatedNestedModel, AnnotatedSubNestedModel, AnnotatedCustomConfigNestedModel, AnnotatedSkipQuantModel
  from torch.testing._internal.common_quantized import override_quantized_engine, supported_qengines, override_qengines
  from hypothesis import given
  from hypothesis import strategies
  import torch.testing._internal.hypothesis_utils
  from typing import Tuple
  import numpy
label_desc: Use image node_id 16 for calling the TestQuantizeEagerPTQStatic obj's underlying member method code with example usage: obj.test_custom_module_class() and returns: self, self, observed, self, quantized, self, x, x