class_docstr: The :class:`GitWildMatchPattern` class represents a compiled Git wildmatch
  pattern.
class_docstr_tok: ["The",":","class",":","`","GitWildMatchPattern","`","class","represents","a","compiled","Git","wildmatch","pattern","."]
docstr: Convert the pattern into a regular expression.
  
  *pattern* (:class:`str` or :class:`bytes`) is the pattern to convert into a
  regular expression.
  
  Returns the uncompiled regular expression (:class:`str`, :class:`bytes`, or
  :data:`None`); and whether matched files should be included (:data:`True`),
  excluded (:data:`False`), or if it is a null-operation (:data:`None`).
docstr_tok: ["Convert","the","pattern","into","a","regular","expression",".","*","pattern","*","(",":","class",":","`","str","`","or",":","class",":","`","bytes","`",")","is","the","pattern","to","convert","into","a","regular","expression",".","Returns","the","uncompiled","regular","expression","(",":","class",":","`","str","`",",",":","class",":","`","bytes","`",",","or",":","data",":","`","None","`",")",";","and","whether","matched","files","should","be","included","(",":","data",":","`","True","`",")",",","excluded","(",":","data",":","`","False","`",")",",","or","if","it","is","a","null-operation","(",":","data",":","`","None","`",")","."]
code: def pattern_to_regex(
      cls,
      pattern: AnyStr,
  ) -> Tuple[Optional[AnyStr], Optional[bool]]:
      """
      Convert the pattern into a regular expression.
  
      *pattern* (:class:`str` or :class:`bytes`) is the pattern to convert into a
      regular expression.
  
      Returns the uncompiled regular expression (:class:`str`, :class:`bytes`, or
      :data:`None`); and whether matched files should be included (:data:`True`),
      excluded (:data:`False`), or if it is a null-operation (:data:`None`).
      """
      if isinstance(pattern, str):
          return_type = str
      elif isinstance(pattern, bytes):
          return_type = bytes
          pattern = pattern.decode(_BYTES_ENCODING)
      else:
          raise TypeError(
              f"pattern:{pattern!r} is not a unicode or byte string."
          )
  
      original_pattern = pattern
  
      if pattern.endswith("\\ "):
          # EDGE CASE: Spaces can be escaped with backslash. If a pattern that ends
          # with backslash followed by a space, only strip from left.
          pattern = pattern.lstrip()
      else:
          pattern = pattern.strip()
  
      if pattern.startswith("#"):
          # A pattern starting with a hash ('#') serves as a comment (neither
          # includes nor excludes files). Escape the hash with a back-slash to match
          # a literal hash (i.e., '\#').
          regex = None
          include = None
  
      elif pattern == "/":
          # EDGE CASE: According to `git check-ignore` (v2.4.1), a single '/' does
          # not match any file.
          regex = None
          include = None
  
      elif pattern:
          if pattern.startswith("!"):
              # A pattern starting with an exclamation mark ('!') negates the pattern
              # (exclude instead of include). Escape the exclamation mark with a
              # back-slash to match a literal exclamation mark (i.e., '\!').
              include = False
              # Remove leading exclamation mark.
              pattern = pattern[1:]
          else:
              include = True
  
          # Allow a regex override for edge cases that cannot be handled through
          # normalization.
          override_regex = None
  
          # Split pattern into segments.
          pattern_segs = pattern.split("/")
  
          # Check whether the pattern is specifically a directory pattern before
          # normalization.
          is_dir_pattern = not pattern_segs[-1]
  
          # Normalize pattern to make processing easier.
  
          # EDGE CASE: Deal with duplicate double-asterisk sequences. Collapse each
          # sequence down to one double-asterisk. Iterate over the segments in
          # reverse and remove the duplicate double asterisks as we go.
          for i in range(len(pattern_segs) - 1, 0, -1):
              prev = pattern_segs[i - 1]
              seg = pattern_segs[i]
              if prev == "**" and seg == "**":
                  del pattern_segs[i]
  
          if (
              len(pattern_segs) == 2
              and pattern_segs[0] == "**"
              and not pattern_segs[1]
          ):
              # EDGE CASE: The '**/' pattern should match everything except individual
              # files in the root directory. This case cannot be adequately handled
              # through normalization. Use the override.
              override_regex = f"^.+(?P<{_DIR_MARK}>/).*$"
  
          if not pattern_segs[0]:
              # A pattern beginning with a slash ('/') will only match paths directly
              # on the root directory instead of any descendant paths. So, remove
              # empty first segment to make pattern relative to root.
              del pattern_segs[0]
  
          elif len(pattern_segs) == 1 or (
              len(pattern_segs) == 2 and not pattern_segs[1]
          ):
              # A single pattern without a beginning slash ('/') will match any
              # descendant path. This is equivalent to "**/{pattern}". So, prepend
              # with double-asterisks to make pattern relative to root.
              # - EDGE CASE: This also holds for a single pattern with a trailing
              #   slash (e.g. dir/).
              if pattern_segs[0] != "**":
                  pattern_segs.insert(0, "**")
  
          else:
              # EDGE CASE: A pattern without a beginning slash ('/') but contains at
              # least one prepended directory (e.g. "dir/{pattern}") should not match
              # "**/dir/{pattern}", according to `git check-ignore` (v2.4.1).
              pass
  
          if not pattern_segs:
              # After resolving the edge cases, we end up with no pattern at all. This
              # must be because the pattern is invalid.
              raise GitWildMatchPatternError(
                  f"Invalid git pattern: {original_pattern!r}"
              )
  
          if not pattern_segs[-1] and len(pattern_segs) > 1:
              # A pattern ending with a slash ('/') will match all descendant paths if
              # it is a directory but not if it is a regular file. This is equivalent
              # to "{pattern}/**". So, set last segment to a double-asterisk to
              # include all descendants.
              pattern_segs[-1] = "**"
  
          if override_regex is None:
              # Build regular expression from pattern.
              output = ["^"]
              need_slash = False
              end = len(pattern_segs) - 1
              for i, seg in enumerate(pattern_segs):
                  if seg == "**":
                      if i == 0 and i == end:
                          # A pattern consisting solely of double-asterisks ('**') will
                          # match every path.
                          output.append(f"[^/]+(?:/.*)?")
  
                      elif i == 0:
                          # A normalized pattern beginning with double-asterisks
                          # ('**') will match any leading path segments.
                          output.append("(?:.+/)?")
                          need_slash = False
  
                      elif i == end:
                          # A normalized pattern ending with double-asterisks ('**') will
                          # match any trailing path segments.
                          if is_dir_pattern:
                              output.append(f"(?P<{_DIR_MARK}>/).*")
                          else:
                              output.append(f"/.*")
  
                      else:
                          # A pattern with inner double-asterisks ('**') will match multiple
                          # (or zero) inner path segments.
                          output.append("(?:/.+)?")
                          need_slash = True
  
                  elif seg == "*":
                      # Match single path segment.
                      if need_slash:
                          output.append("/")
  
                      output.append("[^/]+")
  
                      if i == end:
                          # A pattern ending without a slash ('/') will match a file or a
                          # directory (with paths underneath it). E.g., "foo" matches "foo",
                          # "foo/bar", "foo/bar/baz", etc.
                          output.append(f"(?:(?P<{_DIR_MARK}>/).*)?")
  
                      need_slash = True
  
                  else:
                      # Match segment glob pattern.
                      if need_slash:
                          output.append("/")
  
                      try:
                          output.append(
                              cls._translate_segment_glob(seg)
                          )
                      except ValueError as e:
                          raise GitWildMatchPatternError(
                              f"Invalid git pattern: {original_pattern!r}"
                          ) from e
  
                      if i == end:
                          # A pattern ending without a slash ('/') will match a file or a
                          # directory (with paths underneath it). E.g., "foo" matches "foo",
                          # "foo/bar", "foo/bar/baz", etc.
                          output.append(f"(?:(?P<{_DIR_MARK}>/).*)?")
  
                      need_slash = True
  
              output.append("$")
              regex = "".join(output)
  
          else:
              # Use regex override.
              regex = override_regex
  
      else:
          # A blank pattern is a null-operation (neither includes nor excludes
          # files).
          regex = None
          include = None
  
      if regex is not None and return_type is bytes:
          regex = regex.encode(_BYTES_ENCODING)
  
      return regex, include
  
file_path: catboost/contrib/python/pathspec/pathspec/patterns/gitwildmatch.py
imports: import re
  import warnings
  from typing import AnyStr, Optional, Tuple
  from ..None import util
  from ..pattern import RegexPattern
label_desc: Use image node_id 1 for calling the GitWildMatchPattern obj's underlying member method code with example usage: obj.pattern_to_regex(cls, pattern) and returns: regex,  include