docstr: failures: A list with elements of the form {"line": full test name, "trace": error trace}
docstr_tok: ["failures",":","A","list","with","elements","of","the","form","{","``","line","''",":","full","test","name",",","``","trace","''",":","error","trace","}"]
code: def get_reply_blocks(
      self, job_name, job_result, failures, device, text
  ):
      """
      failures: A list with elements of the form {"line": full test name, "trace": error trace}
      """
      # `text` must be less than 3001 characters in Slack SDK
      # keep some room for adding "[Truncated]" when necessary
      MAX_ERROR_TEXT = 3000 - len("[Truncated]")
  
      failure_text = ""
      for idx, error in enumerate(failures):
          new_text = (
              failure_text
              + f'*{error["line"]}*\n_{error["trace"]}_\n\n'
          )
          if len(new_text) > MAX_ERROR_TEXT:
              # `failure_text` here has length <= 3000
              failure_text = failure_text + "[Truncated]"
              break
          # `failure_text` here has length <= MAX_ERROR_TEXT
          failure_text = new_text
  
      title = job_name
      if device is not None:
          title += f" ({device}-gpu)"
  
      content = {
          "type": "section",
          "text": {"type": "mrkdwn", "text": text},
      }
  
      # TODO: Make sure we always have a valid job link (or at least a way not to break the report sending)
      # Currently we get the device from a job's artifact name.
      # If a device is found, the job name should contain the device type, for example, `XXX (single-gpu)`.
      # This could be done by adding `machine_type` in a job's `strategy`.
      # (If `job_result["job_link"][device]` is `None`, we get an error: `... [ERROR] must provide a string ...`)
      if (
          job_result["job_link"] is not None
          and job_result["job_link"][device] is not None
      ):
          content["accessory"] = {
              "type": "button",
              "text": {
                  "type": "plain_text",
                  "text": "GitHub Action job",
                  "emoji": True,
              },
              "url": job_result["job_link"][device],
          }
  
      return [
          {
              "type": "header",
              "text": {
                  "type": "plain_text",
                  "text": title.upper(),
                  "emoji": True,
              },
          },
          content,
          {
              "type": "section",
              "text": {"type": "mrkdwn", "text": failure_text},
          },
      ]
  
imports: import ast
  import collections
  import functools
  import json
  import math
  import operator
  import os
  import re
  import sys
  import time
  from typing import Dict, List, Optional, Union
  import requests
  from slack_sdk import WebClient
label_desc: Use image node_id 14 for calling the Message obj's underlying member method code with example usage: obj.get_reply_blocks(job_name, job_result, failures, device, text) and returns: list