code: def _strategy(codes, context, is_unicode, *, alphabet):
      """Convert SRE regex parse tree to strategy that generates strings matching
      that regex represented by that parse tree.
  
      `codes` is either a list of SRE regex elements representations or a
      particular element representation. Each element is a tuple of element code
      (as string) and parameters. E.g. regex 'ab[0-9]+' compiles to following
      elements:
  
          [
              (LITERAL, 97),
              (LITERAL, 98),
              (MAX_REPEAT, (1, 4294967295, [
                  (IN, [
                      (RANGE, (48, 57))
                  ])
              ]))
          ]
  
      The function recursively traverses regex element tree and converts each
      element to strategy that generates strings that match that element.
  
      Context stores
      1. List of groups (for backreferences)
      2. Active regex flags (e.g. IGNORECASE, DOTALL, UNICODE, they affect
         behavior of various inner strategies)
      """
  
      def recurse(codes):
          return _strategy(
              codes, context, is_unicode, alphabet=alphabet
          )
  
      if is_unicode:
          empty = ""
          to_char = chr
      else:
          empty = b""
          to_char = int_to_byte
          binary_char = st.binary(min_size=1, max_size=1)
  
      if not isinstance(codes, tuple):
          # List of codes
          strategies = []
  
          i = 0
          while i < len(codes):
              if (
                  codes[i][0] == sre.LITERAL
                  and not context.flags & re.IGNORECASE
              ):
                  # Merge subsequent "literals" into one `just()` strategy
                  # that generates corresponding text if no IGNORECASE
                  j = i + 1
                  while j < len(codes) and codes[j][0] == sre.LITERAL:
                      j += 1
  
                  if i + 1 < j:
                      chars = empty.join(
                          to_char(charcode)
                          for _, charcode in codes[i:j]
                      )
                      if invalid := chars_not_in_alphabet(
                          alphabet, chars
                      ):
                          raise InvalidArgument(
                              f"Literal {chars!r} contains characters {invalid!r} "
                              f"which are not in the specified alphabet"
                          )
                      strategies.append(st.just(chars))
                      i = j
                      continue
  
              strategies.append(recurse(codes[i]))
              i += 1
  
          # We handle this separately at the top level, but some regex can
          # contain empty lists internally, so we need to handle this here too.
          if not strategies:
              return st.just(empty)
  
          if len(strategies) == 1:
              return strategies[0]
          return st.tuples(*strategies).map(empty.join)
      else:
          # Single code
          code, value = codes
          if code == sre.LITERAL:
              # Regex 'a' (single char)
              c = to_char(value)
              if chars_not_in_alphabet(alphabet, c):
                  raise InvalidArgument(
                      f"Literal {c!r} is not in the specified alphabet"
                  )
              if (
                  context.flags & re.IGNORECASE
                  and c != c.swapcase()
                  and re.match(
                      re.escape(c), c.swapcase(), re.IGNORECASE
                  )
                  is not None
                  and not chars_not_in_alphabet(alphabet, c.swapcase())
              ):
                  # We do the explicit check for swapped-case matching because
                  # eg 'ß'.upper() == 'SS' and ignorecase doesn't match it.
                  return st.sampled_from([c, c.swapcase()])
              return st.just(c)
  
          elif code == sre.NOT_LITERAL:
              # Regex '[^a]' (negation of a single char)
              c = to_char(value)
              blacklist = {c}
              if (
                  context.flags & re.IGNORECASE
                  and re.match(
                      re.escape(c), c.swapcase(), re.IGNORECASE
                  )
                  is not None
              ):
                  # There are a few cases where .swapcase() returns two characters,
                  # but is still a case-insensitive match.  In such cases we add *both*
                  # characters to our blacklist, to avoid doing the wrong thing for
                  # patterns such as r"[^\u0130]+" where "i\u0307" matches.
                  #
                  # (that's respectively 'Latin letter capital I with dot above' and
                  # 'latin latter i' + 'combining dot above'; see issue #2657)
                  #
                  # As a final additional wrinkle, "latin letter capital I" *also*
                  # case-insensitive-matches, with or without combining dot character.
                  # We therefore have to chain .swapcase() calls until a fixpoint.
                  stack = [c.swapcase()]
                  while stack:
                      for char in stack.pop():
                          blacklist.add(char)
                          stack.extend(set(char.swapcase()) - blacklist)
  
              if is_unicode:
                  return OneCharStringStrategy(
                      unwrap_strategies(alphabet).intervals
                      & charmap.query(exclude_characters=blacklist)
                  )
              else:
                  return binary_char.filter(
                      lambda c: c not in blacklist
                  )
  
          elif code == sre.IN:
              # Regex '[abc0-9]' (set of characters)
              negate = value[0][0] == sre.NEGATE
              if is_unicode:
                  builder = CharactersBuilder(
                      flags=context.flags,
                      negate=negate,
                      alphabet=alphabet,
                  )
              else:
                  builder = BytesBuilder(
                      flags=context.flags, negate=negate
                  )
  
              for charset_code, charset_value in value:
                  if charset_code == sre.NEGATE:
                      # Regex '[^...]' (negation)
                      # handled by builder = CharactersBuilder(...) above
                      pass
                  elif charset_code == sre.LITERAL:
                      # Regex '[a]' (single char)
                      builder.add_char(charset_value)
                  elif charset_code == sre.RANGE:
                      # Regex '[a-z]' (char range)
                      low, high = charset_value
                      for char_code in range(low, high + 1):
                          builder.add_char(
                              char_code, check=char_code in (low, high)
                          )
                  elif charset_code == sre.CATEGORY:
                      # Regex '[\w]' (char category)
                      builder.add_category(charset_value)
                  else:
                      # Currently there are no known code points other than
                      # handled here. This code is just future proofing
                      raise NotImplementedError(
                          f"Unknown charset code: {charset_code}"
                      )
              return builder.strategy
  
          elif code == sre.ANY:
              # Regex '.' (any char)
              if is_unicode:
                  assert alphabet is not None
                  if context.flags & re.DOTALL:
                      return alphabet
                  return OneCharStringStrategy(
                      unwrap_strategies(alphabet).intervals
                      & charmap.query(exclude_characters="\n")
                  )
              else:
                  if context.flags & re.DOTALL:
                      return binary_char
                  return binary_char.filter(lambda c: c != b"\n")
  
          elif code == sre.AT:
              # Regexes like '^...', '...$', '\bfoo', '\Bfoo'
              # An empty string (or newline) will match the token itself, but
              # we don't and can't check the position (eg '%' at the end)
              return st.just(empty)
  
          elif code == sre.SUBPATTERN:
              # Various groups: '(...)', '(:...)' or '(?P<name>...)'
              old_flags = context.flags
              context.flags = (context.flags | value[1]) & ~value[2]
  
              strat = _strategy(
                  value[-1], context, is_unicode, alphabet=alphabet
              )
  
              context.flags = old_flags
  
              if value[0]:
                  strat = update_group(value[0], strat)
  
              return strat
  
          elif code == sre.GROUPREF:
              # Regex '\\1' or '(?P=name)' (group reference)
              return reuse_group(value)
  
          elif code == sre.ASSERT:
              # Regex '(?=...)' or '(?<=...)' (positive lookahead/lookbehind)
              return recurse(value[1])
  
          elif code == sre.ASSERT_NOT:
              # Regex '(?!...)' or '(?<!...)' (negative lookahead/lookbehind)
              return st.just(empty)
  
          elif code == sre.BRANCH:
              # Regex 'a|b|c' (branch)
              return st.one_of([recurse(branch) for branch in value[1]])
  
          elif code in [
              sre.MIN_REPEAT,
              sre.MAX_REPEAT,
              POSSESSIVE_REPEAT,
          ]:
              # Regexes 'a?', 'a*', 'a+' and their non-greedy variants
              # (repeaters)
              at_least, at_most, subregex = value
              if at_most == sre.MAXREPEAT:
                  at_most = None
              if at_least == 0 and at_most == 1:
                  return st.just(empty) | recurse(subregex)
              return st.lists(
                  recurse(subregex), min_size=at_least, max_size=at_most
              ).map(empty.join)
  
          elif code == sre.GROUPREF_EXISTS:
              # Regex '(?(id/name)yes-pattern|no-pattern)'
              # (if group exists choice)
              return group_conditional(
                  value[0],
                  recurse(value[1]),
                  recurse(value[2]) if value[2] else st.just(empty),
              )
          elif (
              code == ATOMIC_GROUP
          ):  # pragma: no cover  # new in Python 3.11
              return _strategy(
                  value, context, is_unicode, alphabet=alphabet
              )
  
          else:
              # Currently there are no known code points other than handled here.
              # This code is just future proofing
              raise NotImplementedError(
                  f"Unknown code point: {code!r}.  Please open an issue."
              )
  
imports: import operator
  import re
  from hypothesis.errors import InvalidArgument
  from hypothesis.internal import charmap
  from hypothesis.strategies._internal.lazy import unwrap_strategies
  from hypothesis.strategies._internal.strings import OneCharStringStrategy
  from hypothesis import reject, strategies
  from hypothesis.internal.charmap import as_general_categories, categories
  from hypothesis.internal.compat import add_note, int_to_byte
label_desc: Use image node_id 9 for calling a global function with example usage: _strategy(codes, context, is_unicode) and returns: _strategy, st, st, strategies, st, st, OneCharStringStrategy, binary_char, builder, OneCharStringStrategy, binary_char, st, alphabet, binary_char, strat, reuse_group, recurse, st, st, st, unknown, group_conditional, _strategy