class_docstr: Decorator for turning a function into a profiler. Inspects the function's signature and
  builds a dataclass representing its configurations (for integrating with ``Hydra``). Adds two
  attributes ``is_pseries`` and ``is_pframe`` to distinguish whether it targets Series or
  DataFrames. This is inferred based on the type annotation of the first parameter. Captures the
  start and end timestamps, the return value, as well as any warnings or exceptions raised during
  the execution.
  
  Args:
      fn (Callable): Profiler function to decorate.
class_docstr_tok: ["Decorator","for","turning","a","function","into","a","profiler",".","Inspects","the","function","'s","signature","and","builds","a","dataclass","representing","its","configurations","(","for","integrating","with","``","Hydra","``",")",".","Adds","two","attributes","``","is_pseries","``","and","``","is_pframe","``","to","distinguish","whether","it","targets","Series","or","DataFrames",".","This","is","inferred","based","on","the","type","annotation","of","the","first","parameter",".","Captures","the","start","and","end","timestamps",",","the","return","value",",","as","well","as","any","warnings","or","exceptions","raised","during","the","execution",".","Args",":","fn","(","Callable",")",":","Profiler","function","to","decorate","."]
code: def __init__(self, fn: Callable) -> None:
      update_wrapper(self, fn)
      p_configs = []
      self.sig = signature(fn)
      assert (
          len(self.sig.parameters) >= 1
      ), "Profiling function requires at least 1 argument, the timeseries"
      for i, (name, par) in enumerate(self.sig.parameters.items()):
          assert par.annotation, f"Parameter {name} must be annotated"
          if i == 0:
              self._par_data = par.name
              if is_union_type(par.annotation):
                  data_types = get_args(par.annotation)
              else:
                  data_types = [par.annotation]
              self.is_pseries = pd.Series in data_types
              self.is_pframe = pd.DataFrame in data_types
              assert (
                  self.is_pseries or self.is_pframe
              ), f"First argument '{name}' must be a Series or DataFrame"
          else:
              p_configs.append(
                  (name, par.annotation, field(default=par.default))
              )
      self.config = make_dataclass("Config", p_configs)
      self.fn = fn
  
imports: from typing import Any, Optional, Union, Dict, List, Callable, Tuple, KeysView, ValuesView, ItemsView
  from dataclasses import dataclass, make_dataclass, field, asdict, is_dataclass
  from functools import update_wrapper
  from inspect import signature, Signature
  from datetime import datetime
  import warnings
  from typing_inspect import is_union_type, get_args
  import pandas
  from tslumen.scheduling import Scheduler
  from tslumen.misc import repr_html
label_desc: Use image node_id 1 to create a new ProfilingFunction object  with example: obj = ProfilingFunction(fn)