code: def deprecated_params(**specs: Tuple[str, str]) -> Callable[[_F], _F]:
      """Decorates a function to warn on use of certain parameters.
  
      e.g. ::
  
          @deprecated_params(
              weak_identity_map=(
                  "0.7",
                  "the :paramref:`.Session.weak_identity_map parameter "
                  "is deprecated."
              )
  
          )
  
      """
  
      messages: Dict[str, str] = {}
      versions: Dict[str, str] = {}
      version_warnings: Dict[str, Type[exc.SADeprecationWarning]] = {}
  
      for param, (version, message) in specs.items():
          versions[param] = version
          messages[param] = _sanitize_restructured_text(message)
          version_warnings[param] = exc.SADeprecationWarning
  
      def decorate(fn: _F) -> _F:
          spec = compat.inspect_getfullargspec(fn)
  
          check_defaults: Union[Set[str], Tuple[()]]
          if spec.defaults is not None:
              defaults = dict(
                  zip(
                      spec.args[
                          (len(spec.args) - len(spec.defaults)) :
                      ],
                      spec.defaults,
                  )
              )
              check_defaults = set(defaults).intersection(messages)
              check_kw = set(messages).difference(defaults)
          elif spec.kwonlydefaults is not None:
              defaults = spec.kwonlydefaults
              check_defaults = set(defaults).intersection(messages)
              check_kw = set(messages).difference(defaults)
          else:
              check_defaults = ()
              check_kw = set(messages)
  
          check_any_kw = spec.varkw
  
          # latest mypy has opinions here, not sure if they implemented
          # Concatenate or something
          @decorator
          def warned(fn: _F, *args: Any, **kwargs: Any) -> _F:
              for m in check_defaults:
                  if (
                      defaults[m] is None and kwargs[m] is not None
                  ) or (
                      defaults[m] is not None
                      and kwargs[m] != defaults[m]
                  ):
                      _warn_with_version(
                          messages[m],
                          versions[m],
                          version_warnings[m],
                          stacklevel=3,
                      )
  
              if check_any_kw in messages and set(kwargs).difference(
                  check_defaults
              ):
                  assert check_any_kw is not None
                  _warn_with_version(
                      messages[check_any_kw],
                      versions[check_any_kw],
                      version_warnings[check_any_kw],
                      stacklevel=3,
                  )
  
              for m in check_kw:
                  if m in kwargs:
                      _warn_with_version(
                          messages[m],
                          versions[m],
                          version_warnings[m],
                          stacklevel=3,
                      )
              return fn(*args, **kwargs)  # type: ignore[no-any-return]
  
          doc = fn.__doc__ is not None and fn.__doc__ or ""
          if doc:
              doc = inject_param_text(
                  doc,
                  {
                      param: ".. deprecated:: %s %s"
                      % (
                          "1.4" if version == "2.0" else version,
                          (message or ""),
                      )
                      for param, (version, message) in specs.items()
                  },
              )
          decorated = warned(fn)
          decorated.__doc__ = doc
          return decorated
  
      return decorate
  
imports: from __future__ import annotations
  import re
  from typing import Any
  from typing import Callable
  from typing import Dict
  from typing import Match
  from typing import Optional
  from typing import Sequence
  from typing import Set
  from typing import Tuple
  from typing import Type
  from typing import TypeVar
  from typing import Union
  from .None import compat
  from .langhelpers import _hash_limit_string
  from .langhelpers import _warnings_warn
  from .langhelpers import decorator
  from .langhelpers import inject_docstring_text
  from .langhelpers import inject_param_text
  from ..None import exc
label_desc: Use image node_id 8 for calling a global function with example usage: deprecated_params() and returns: decorate, decorated, fn