class_docstr: Creates a human-readable report, a Metaflow Card, after this step completes.
  
  Note that you may add multiple `@card` decorators in a step with different parameters.
  
  Parameters
  ----------
  type : str, default: 'default'
      Card type.
  id : str, optional, default: None
      If multiple cards are present, use this id to identify this card.
  options : Dict[str, Any], default: {}
      Options passed to the card. The contents depend on the card type.
  timeout : int, default: 45
      Interrupt reporting if it takes more than this many seconds.
class_docstr_tok: ["Creates","a","human-readable","report",",","a","Metaflow","Card",",","after","this","step","completes",".","Note","that","you","may","add","multiple","`","@","card","`","decorators","in","a","step","with","different","parameters",".","Parameters","--","--","--","--","--","type",":","str",",","default",":","'default'","Card","type",".","id",":","str",",","optional",",","default",":","None","If","multiple","cards","are","present",",","use","this","id","to","identify","this","card",".","options",":","Dict","[","str",",","Any","]",",","default",":","{","}","Options","passed","to","the","card",".","The","contents","depend","on","the","card","type",".","timeout",":","int",",","default",":","45","Interrupt","reporting","if","it","takes","more","than","this","many","seconds","."]
code: def task_pre_step(
      self,
      step_name,
      task_datastore,
      metadata,
      run_id,
      task_id,
      flow,
      graph,
      retry_count,
      max_user_code_retries,
      ubf_context,
      inputs,
  ):
      self._task_datastore = task_datastore
      self._metadata = metadata
  
      card_type = self.attributes["type"]
      card_class = get_card_class(card_type)
  
      self._is_runtime_card = False
      if card_class is not None:  # Card type was not found
          if card_class.ALLOW_USER_COMPONENTS:
              self._is_editable = True
          self._is_runtime_card = card_class.RUNTIME_UPDATABLE
  
      # We have a step counter to ensure that on calling the final card decorator's `task_pre_step`
      # we call a `finalize` function in the `CardComponentCollector`.
      # This can help ensure the behaviour of the `current.card` object is according to specification.
      self._increment_step_counter()
      self._user_set_card_id = self.attributes["id"]
      if (
          self.attributes["id"] is not None
          and re.match(CARD_ID_PATTERN, self.attributes["id"]) is None
      ):
          # There should be a warning issued to the user that `id` doesn't match regex pattern
          # Since it is doesn't match pattern, we need to ensure that `id` is not accepted by `current`
          # and warn users that they cannot use id for their arguments.
          wrn_msg = (
              "@card with id '%s' doesn't match REGEX pattern. "
              "Adding custom components to cards will not be accessible via `current.card['%s']`. "
              "Please create `id` of pattern %s. "
          ) % (
              self.attributes["id"],
              self.attributes["id"],
              TYPE_CHECK_REGEX,
          )
          warning_message(wrn_msg, self._logger)
          self._user_set_card_id = None
  
      # As we have multiple decorators,
      # we need to ensure that `current.card` has `CardComponentCollector` instantiated only once.
      if not self._is_event_registered("pre-step"):
          self._register_event("pre-step")
          self._set_card_creator(
              CardCreator(self._create_top_level_args())
          )
  
          current._update_env(
              {
                  "card": CardComponentCollector(
                      self._logger, self.card_creator
                  )
              }
          )
  
      # this line happens because of decospecs parsing.
      customize = False
      if str(self.attributes["customize"]) == "True":
          customize = True
  
      card_metadata = current.card._add_card(
          self.attributes["type"],
          self._user_set_card_id,
          self.attributes,
          self.card_options,
          editable=self._is_editable,
          customize=customize,
          runtime_card=self._is_runtime_card,
          refresh_interval=self.attributes["refresh_interval"],
      )
      self._card_uuid = card_metadata["uuid"]
  
      # This means that we are calling `task_pre_step` on the last card decorator.
      # We can now `finalize` method in the CardComponentCollector object.
      # This will set up the `current.card` object for usage inside `@step` code.
      if self.step_counter == self.total_decos_on_step[step_name]:
          current.card._finalize()
  
imports: from metaflow.decorators import StepDecorator
  from metaflow.current import current
  from metaflow.util import to_unicode
  from .component_serializer import CardComponentCollector, get_card_class
  from .card_creator import CardCreator
  import re
  from .exception import CARD_ID_PATTERN, TYPE_CHECK_REGEX
label_desc: Use image node_id 8 for calling the CardDecorator obj's underlying member method code with example usage: obj.task_pre_step(step_name, task_datastore, metadata, run_id, task_id, flow, graph, retry_count, max_user_code_retries, ubf_context, inputs) without return types