code: def render(
      markup: str,
      style: Union[str, Style] = "",
      emoji: bool = True,
      emoji_variant: Optional[EmojiVariant] = None,
  ) -> Text:
      """Render console markup in to a Text instance.
  
      Args:
          markup (str): A string containing console markup.
          style: (Union[str, Style]): The style to use.
          emoji (bool, optional): Also render emoji code. Defaults to True.
          emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None.
  
  
      Raises:
          MarkupError: If there is a syntax error in the markup.
  
      Returns:
          Text: A test instance.
      """
      emoji_replace = _emoji_replace
      if "[" not in markup:
          return Text(
              emoji_replace(markup, default_variant=emoji_variant)
              if emoji
              else markup,
              style=style,
          )
      text = Text(style=style)
      append = text.append
      normalize = Style.normalize
  
      style_stack: List[Tuple[int, Tag]] = []
      pop = style_stack.pop
  
      spans: List[Span] = []
      append_span = spans.append
  
      _Span = Span
      _Tag = Tag
  
      def pop_style(style_name: str) -> Tuple[int, Tag]:
          """Pop tag matching given style name."""
          for index, (_, tag) in enumerate(reversed(style_stack), 1):
              if tag.name == style_name:
                  return pop(-index)
          raise KeyError(style_name)
  
      for position, plain_text, tag in _parse(markup):
          if plain_text is not None:
              # Handle open brace escapes, where the brace is not part of a tag.
              plain_text = plain_text.replace("\\[", "[")
              append(emoji_replace(plain_text) if emoji else plain_text)
          elif tag is not None:
              if tag.name.startswith("/"):  # Closing tag
                  style_name = tag.name[1:].strip()
  
                  if style_name:  # explicit close
                      style_name = normalize(style_name)
                      try:
                          start, open_tag = pop_style(style_name)
                      except KeyError:
                          raise MarkupError(
                              f"closing tag '{tag.markup}' at position {position} doesn't match any open tag"
                          ) from None
                  else:  # implicit close
                      try:
                          start, open_tag = pop()
                      except IndexError:
                          raise MarkupError(
                              f"closing tag '[/]' at position {position} has nothing to close"
                          ) from None
  
                  if open_tag.name.startswith("@"):
                      if open_tag.parameters:
                          handler_name = ""
                          parameters = open_tag.parameters.strip()
                          handler_match = RE_HANDLER.match(parameters)
                          if handler_match is not None:
                              (
                                  handler_name,
                                  match_parameters,
                              ) = handler_match.groups()
                              parameters = (
                                  "()"
                                  if match_parameters is None
                                  else match_parameters
                              )
  
                          try:
                              meta_params = literal_eval(parameters)
                          except SyntaxError as error:
                              raise MarkupError(
                                  f"error parsing {parameters!r} in {open_tag.parameters!r}; {error.msg}"
                              )
                          except Exception as error:
                              raise MarkupError(
                                  f"error parsing {open_tag.parameters!r}; {error}"
                              ) from None
  
                          if handler_name:
                              meta_params = (
                                  handler_name,
                                  meta_params
                                  if isinstance(meta_params, tuple)
                                  else (meta_params,),
                              )
  
                      else:
                          meta_params = ()
  
                      append_span(
                          _Span(
                              start,
                              len(text),
                              Style(meta={open_tag.name: meta_params}),
                          )
                      )
                  else:
                      append_span(
                          _Span(start, len(text), str(open_tag))
                      )
  
              else:  # Opening tag
                  normalized_tag = _Tag(
                      normalize(tag.name), tag.parameters
                  )
                  style_stack.append((len(text), normalized_tag))
  
      text_length = len(text)
      while style_stack:
          start, tag = style_stack.pop()
          style = str(tag)
          if style:
              append_span(_Span(start, text_length, style))
  
      text.spans = sorted(spans[::-1], key=attrgetter("start"))
      return text
  
file_path: rich/rich/markup.py
imports: import re
  from ast import literal_eval
  from operator import attrgetter
  from typing import Callable, Iterable, List, Match, NamedTuple, Optional, Tuple, Union
  from ._emoji_replace import _emoji_replace
  from .emoji import EmojiVariant
  from .errors import MarkupError
  from .style import Style
  from .text import Span, Text
label_desc: Use image node_id 3 for calling a global function with example usage: render(markup, style, emoji, emoji_variant) and returns: text, Text, pop