code: def observable(cls=None, **kwargs):  # noqa: C901
      """
      Decorator to mark a class as producing observable values. The names of the
      observable values are the names of keyword arguments. The values of keyword
      arguments are the types of the value. The type is currently not used for
      anything.
      """
      assert kwargs
      observable_value_types = kwargs
  
      def wrap(cls):
          assert not hasattr(cls, "add_observer")
          assert not hasattr(cls, "notify_observers")
  
          original_init = cls.__init__
  
          @functools.wraps(original_init)
          def new_init(self, *args, **kwargs):
              original_init(self, *args, **kwargs)
              assert not hasattr(self, "_observable_value_types")
              assert not hasattr(self, "_observers")
              self._observable_value_types = observable_value_types
              self._observers = {v: [] for v in observable_value_types}
  
          cls.__init__ = new_init
  
          cls.add_observer = ObservableMixin.add_observer
  
          cls.add_observers = ObservableMixin.add_observers
  
          cls.notify_observers = ObservableMixin.notify_observers
  
          return cls
  
      if cls is None:
          return wrap
  
      return wrap(cls)
  
file_path: ReAgent/reagent/core/tracker.py
imports: import functools
  import logging
  from typing import Dict, List, Type
  import torch
label_desc: Use image node_id 1 for calling a global function with example usage: observable(cls) and returns: wrap, cls, wrap