class_docstr: This class redacts sensitive data similar to SecretsMasker in Airflow logs.
  
  The difference is that our default max recursion depth is way higher - due to
  the structure of OL events we need more depth.
  Additionally, we allow data structures to specify data that needs not to be
  redacted by specifying _skip_redact list by deriving RedactMixin.
code: def _redact(
      self,
      item: Redactable,
      name: str | None,
      depth: int,
      max_depth: int,
  ) -> Redacted:
      if depth > max_depth:
          return item
      try:
          # It's impossible to check the type of variable in a dict without accessing it, and
          # this already causes warning - so suppress it
          with suppress(AirflowContextDeprecationWarning):
              if type(item).__name__ == "Proxy":
                  # Those are deprecated values in _DEPRECATION_REPLACEMENTS
                  # in airflow.utils.context.Context
                  return "<<non-redactable: Proxy>>"
              if name and should_hide_value_for_key(name):
                  return self._redact_all(item, depth, max_depth)
              if attrs.has(type(item)):
                  # TODO: FIXME when mypy gets compatible with new attrs
                  for dict_key, subval in attrs.asdict(
                      item,  # type: ignore[arg-type]
                      recurse=False,
                  ).items():
                      if _is_name_redactable(dict_key, item):
                          setattr(
                              item,
                              dict_key,
                              self._redact(
                                  subval,
                                  name=dict_key,
                                  depth=(depth + 1),
                                  max_depth=max_depth,
                              ),
                          )
                  return item
              elif is_json_serializable(item) and hasattr(
                  item, "__dict__"
              ):
                  for dict_key, subval in item.__dict__.items():
                      if type(subval).__name__ == "Proxy":
                          return "<<non-redactable: Proxy>>"
                      if _is_name_redactable(dict_key, item):
                          setattr(
                              item,
                              dict_key,
                              self._redact(
                                  subval,
                                  name=dict_key,
                                  depth=(depth + 1),
                                  max_depth=max_depth,
                              ),
                          )
                  return item
              else:
                  return super()._redact(item, name, depth, max_depth)
      except Exception as exc:
          log.warning(
              "Unable to redact %r. Error was: %s: %s",
              item,
              type(exc).__name__,
              exc,
          )
      return item
  
imports: from __future__ import annotations
  import datetime
  import json
  import logging
  import os
  from contextlib import suppress
  from functools import wraps
  from typing import TYPE_CHECKING, Any, Iterable
  from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse
  import attrs
  from attrs import asdict
  from openlineage.client.utils import RedactMixin
  from airflow.compat.functools import cache
  from airflow.configuration import conf
  from airflow.providers.openlineage.plugins.facets import AirflowMappedTaskRunFacet, AirflowRunFacet
  from airflow.utils.context import AirflowContextDeprecationWarning
  from airflow.utils.log.secrets_masker import Redactable, Redacted, SecretsMasker, should_hide_value_for_key
label_desc: Use image node_id 2 for calling the OpenLineageRedactor obj's underlying member method code with example usage: obj._redact(item, name, depth, max_depth) and returns: item, item, str, self, item, item, super, str