code: def make_config_class(
      func,
      allowlist: Optional[List[str]] = None,
      blocklist: Optional[List[str]] = None,
      blocklist_types: List[Type] = BLOCKLIST_TYPES,
  ):
      """
      Create a decorator to create dataclass with the arguments of `func` as fields.
      Only annotated arguments are converted to fields. If the default value is mutable,
      you must use `dataclass.field(default_factory=default_factory)` as default.
      In that case, the func has to be wrapped with @resolve_defaults below.
  
      `allowlist` & `blocklist` are mutually exclusive.
      """
  
      parameters = signature(func).parameters
  
      assert (
          allowlist is None or blocklist is None
      ), "allowlist & blocklist are mutually exclusive"
  
      blocklist_set = set(blocklist or [])
  
      def _is_type_blocklisted(t):
          if getattr(t, "__origin__", None) is Union:
              assert len(t.__args__) == 2 and t.__args__[1] == type(
                  None
              ), "Only Unions of [X, None] (a.k.a. Optional[X]) are supported"
              t = t.__args__[0]
          if hasattr(t, "__origin__"):
              t = t.__origin__
          assert isclass(t), f"{t} is not a class."
          return any(
              issubclass(t, blocklist_type)
              for blocklist_type in blocklist_types
          )
  
      def _is_valid_param(p):
          if p.name in blocklist_set:
              return False
          if (
              p.annotation == Parameter.empty
              and p.default == Parameter.empty
          ):
              return False
          ptype = _get_param_annotation(p)
          if _is_type_blocklisted(ptype):
              return False
          return True
  
      allowlist = allowlist or [
          p.name for p in parameters.values() if _is_valid_param(p)
      ]
  
      def wrapper(config_cls):
          # Add __annotations__ for dataclass
          config_cls.__annotations__ = {
              field_name: _get_param_annotation(parameters[field_name])
              for field_name in allowlist
          }
          # Set default values
          for field_name in allowlist:
              default = parameters[field_name].default
              if default != Parameter.empty:
                  setattr(config_cls, field_name, default)
  
          # Add hashing to support hashing list and dict
          config_cls.__hash__ = param_hash
  
          # Add non-recursive asdict(). dataclasses.asdict() is recursive
          def asdict(self):
              return {
                  field.name: getattr(self, field.name)
                  for field in fields(self)
              }
  
          config_cls.asdict = asdict
  
          return dataclass(frozen=True)(config_cls)
  
      return wrapper
  
file_path: ReAgent/reagent/core/configuration.py
imports: import functools
  from dataclasses import Field, fields, MISSING
  from inspect import isclass, Parameter, signature
  from typing import List, Optional, Type, Union
  from reagent.core.dataclasses import dataclass
  from torch import nn
label_desc: Use image node_id 2 for calling a global function with example usage: make_config_class(func, allowlist, blocklist, blocklist_types) and returns: wrapper, any, True, dataclass, False, False, False, unknown