

import contextlib
from multiprocessing import Pool, RLock

from tqdm.auto import tqdm

from ..utils import experimental, logging


UpperCAmelCase__ :     Optional[Any]				    =    logging.get_logger(__name__)







class        a__       :







  """simple docstring"""




  UpperCAmelCase__      : Optional[Any]			       =None






@experimental
def 					__lowercase      (     _A						,    _A						,    _A						,    _A						,    _A						,    _A						,    _A			)     ->						int:
      if ParallelBackendConfig.backend_name is None:
            return _map_with_multiprocessing_pool(
                _A						,    _A						,    _A						,    _A						,    _A						,    _A						,    _A			)

      return _map_with_joblib(_A						,    _A						,    _A						,    _A						,    _A						,    _A						,    _A			)






def 					__lowercase      (     _A						,    _A						,    _A						,    _A						,    _A						,    _A						,    _A			)     ->						Union[str, Any]:
      SCREAMING_SNAKE_CASE :      Optional[Any]       =   num_proc if num_proc <= len(_A			) else len(_A			)
      SCREAMING_SNAKE_CASE :      Union[str, Any]       =   []  # We organize the splits ourselve (contiguous splits)
      for index in range(_A			):
            SCREAMING_SNAKE_CASE :      str       =   len(_A			) // num_proc
            SCREAMING_SNAKE_CASE :      List[Any]       =   len(_A			) % num_proc
            SCREAMING_SNAKE_CASE :      Optional[int]       =   div * index + min(_A						,    _A			)
            SCREAMING_SNAKE_CASE :      List[str]       =   start + div + (1 if index < mod else 0)
            split_kwds.append((function, iterable[start:end], types, index, disable_tqdm, desc)			)

      if len(_A			) != sum(len(i[1]			) for i in split_kwds			):
            raise ValueError(
                F"Error dividing inputs iterable among processes. "
                F"Total number of objects {len(_A			)}, "
                F"length: {sum(len(i[1]			) for i in split_kwds			)}"			)

      logger.info(
          F"Spawning {num_proc} processes for {len(_A			)} objects in slices of {[len(i[1]			) for i in split_kwds]}"			)
      SCREAMING_SNAKE_CASE     ,	SCREAMING_SNAKE_CASE :      Union[str, Any]       =   None, None
      if not disable_tqdm:
            SCREAMING_SNAKE_CASE     ,	SCREAMING_SNAKE_CASE :      Optional[int]       =   (RLock(),), tqdm.set_lock
      with Pool(_A						,    initargs=_A						,    initializer=_A			) as pool:
            SCREAMING_SNAKE_CASE :      Optional[int]       =   pool.map(_A						,    _A			)
      logger.info(F"Finished {num_proc} processes"			)
      SCREAMING_SNAKE_CASE :      Tuple       =   [obj for proc_res in mapped for obj in proc_res]
      logger.info(F"Unpacked {len(_A			)} objects"			)

      return mapped






def 					__lowercase      (     _A						,    _A						,    _A						,    _A						,    _A						,    _A						,    _A			)     ->						List[str]:
      # progress bar is not yet supported for _map_with_joblib, because tqdm couldn't accurately be applied to joblib,
      # and it requires monkey-patching joblib internal classes which is subject to change
      import joblib

      with joblib.parallel_backend(ParallelBackendConfig.backend_name						,    n_jobs=_A			):
            return joblib.Parallel()(
                joblib.delayed(_A			)((function, obj, types, None, True, None)			) for obj in iterable			)







@experimental
@contextlib.contextmanager
def 					__lowercase      (     _A			)     ->						Dict:
      SCREAMING_SNAKE_CASE :      List[str]       =   backend_name

      if backend_name == "spark":
            from joblibspark import register_spark

            register_spark()

            # TODO: call create_cache_and_write_probe if "download" in steps
            # TODO: raise NotImplementedError when Dataset.map etc is called

      try:
            yield
      finally:
            SCREAMING_SNAKE_CASE :      Tuple       =   None







def 					__lowercase      (     _A			)     ->						list[int]:
      SCREAMING_SNAKE_CASE :      int       =   [0 for i in range(len(_A			)			)]

      # initialize interval's left pointer and right pointer
      SCREAMING_SNAKE_CASE     ,	SCREAMING_SNAKE_CASE :      Dict       =   0, 0

      for i in range(1						,    len(_A			)			):
            # case when current index is inside the interval
            if i <= right_pointer:
                  SCREAMING_SNAKE_CASE :      Any       =   min(right_pointer - i + 1						,    z_result[i - left_pointer]			)
                  SCREAMING_SNAKE_CASE :      Optional[Any]       =   min_edge

            while go_next(_A						,    _A						,    _A			):
                  z_result[i] += 1

            # if new index's result gives us more right interval,
            # we've to update left_pointer and right_pointer
            if i + z_result[i] - 1 > right_pointer:
                  SCREAMING_SNAKE_CASE     ,	SCREAMING_SNAKE_CASE :      List[Any]       =   i, i + z_result[i] - 1

      return z_result






def 					__lowercase      (     _A						,    _A						,    _A			)     ->						bool:
      return i + z_result[i] < len(_A			) and s[z_result[i]] == s[i + z_result[i]]






def 					__lowercase      (     _A						,    _A			)     ->						int:
      SCREAMING_SNAKE_CASE :      Any       =   0
      # concatenate 'pattern' and 'input_str' and call z_function
      # with concatenated string
      SCREAMING_SNAKE_CASE :      List[Any]       =   z_function(pattern + input_str			)

      for val in z_result:
            # if value is greater then length of the pattern string
            # that means this index is starting position of substring
            # which is equal to pattern string
            if val >= len(_A			):
                  answer += 1

      return answer


if __name__ == "__main__":
  import doctest

  doctest.testmod()




