code: def _find_path_from_directory(
      base_dir_path: str | os.PathLike[str],
      ignore_file_name: str,
      ignore_rule_type: type[_IgnoreRule],
  ) -> Generator[str, None, None]:
      """Recursively search the base path and return the list of file paths that should not be ignored.
  
      :param base_dir_path: the base path to be searched
      :param ignore_file_name: the file name containing regular expressions for files that should be ignored.
      :param ignore_rule_type: the concrete class for ignore rules, which implements the _IgnoreRule interface.
  
      :return: a generator of file paths which should not be ignored.
      """
      # A Dict of patterns, keyed using resolved, absolute paths
      patterns_by_dir: dict[Path, list[_IgnoreRule]] = {}
  
      for root, dirs, files in os.walk(base_dir_path, followlinks=True):
          patterns: list[_IgnoreRule] = patterns_by_dir.get(
              Path(root).resolve(), []
          )
  
          ignore_file_path = Path(root) / ignore_file_name
          if ignore_file_path.is_file():
              with open(ignore_file_path) as ifile:
                  lines_no_comments = [
                      re2.sub(r"\s*#.*", "", line)
                      for line in ifile.read().split("\n")
                  ]
                  # append new patterns and filter out "None" objects, which are invalid patterns
                  patterns += [
                      p
                      for p in [
                          ignore_rule_type.compile(
                              line,
                              Path(base_dir_path),
                              ignore_file_path,
                          )
                          for line in lines_no_comments
                          if line
                      ]
                      if p is not None
                  ]
                  # evaluation order of patterns is important with negation
                  # so that later patterns can override earlier patterns
                  patterns = list(dict.fromkeys(patterns))
  
          dirs[:] = [
              subdir
              for subdir in dirs
              if not ignore_rule_type.match(
                  Path(root) / subdir, patterns
              )
          ]
  
          # explicit loop for infinite recursion detection since we are following symlinks in this walk
          for sd in dirs:
              dirpath = (Path(root) / sd).resolve()
              if dirpath in patterns_by_dir:
                  raise RuntimeError(
                      "Detected recursive loop when walking DAG directory "
                      f"{base_dir_path}: {dirpath} has appeared more than once."
                  )
              patterns_by_dir.update({dirpath: patterns.copy()})
  
          for file in files:
              if file != ignore_file_name:
                  abs_file_path = Path(root) / file
                  if not ignore_rule_type.match(
                      abs_file_path, patterns
                  ):
                      yield str(abs_file_path)
  
imports: from __future__ import annotations
  import ast
  import logging
  import os
  import zipfile
  from io import TextIOWrapper
  from pathlib import Path
  from typing import Generator, NamedTuple, Pattern, Protocol, overload
  import re2
  from pathspec.patterns import GitWildMatchPattern
  from airflow.configuration import conf
  from airflow.exceptions import RemovedInAirflow3Warning
label_desc: Use image node_id 7 for calling a global function with example usage: _find_path_from_directory(base_dir_path, ignore_file_name, ignore_rule_type) without return types