code: def download_and_parse_artifacts(
      repo: str,
      branch: str,
      events: list[str],
      max_days: int,
      max_runs: int,
  ) -> Iterator[pandas.DataFrame]:
      print("Getting list of workflow runs...")
      runs = []
      with get_session() as session:
          for event in events:
              runs += get_workflow_run_listing(
                  repo=repo,
                  branch=branch,
                  event=event,
                  days=max_days,
                  session=session,
              )
  
          # Filter the workflow runs listing to be in the retention period,
          # and only be test runs (i.e., no linting) that completed.
          runs = [
              r
              for r in runs
              if (
                  pandas.to_datetime(r["created_at"])
                  > pandas.Timestamp.now(tz="UTC")
                  - pandas.Timedelta(days=max_days)
                  and r["conclusion"] != "cancelled"
                  and r["name"].lower() == "tests"
              )
          ]
          print(f"Found {len(runs)} workflow runs")
          # Each workflow run processed takes ~10-15 API requests. To avoid being
          # rate limited by GitHub (1000 requests per hour) we choose just the
          # most recent N runs. This also keeps the viz size from blowing up.
          runs = sorted(runs, key=lambda r: r["created_at"])[-max_runs:]
          print(
              f"Fetching artifact listing for the {len(runs)} most recent workflow runs"
          )
  
          for r in runs:
              artifacts = get_artifacts_for_workflow_run(
                  r["id"], repo=repo, session=session
              )
              # We also upload timeout reports as artifacts, but we don't want them here.
              r["artifacts"] = [
                  a
                  for a in artifacts
                  if "timeouts" not in a["name"]
                  and "cluster_dumps" not in a["name"]
              ]
  
          nartifacts = sum(len(r["artifacts"]) for r in runs)
          ndownloaded = 0
          print(f"Downloading and parsing {nartifacts} artifacts...")
  
          for r in runs:
              jobs_df = get_jobs(r, session=session, repo=repo)
              r["dfs"] = []
              for a in r["artifacts"]:
                  url = a["archive_download_url"]
                  df: pandas.DataFrame | None
                  xml = download_and_parse_artifact(
                      url, session=session
                  )
                  if xml is None:
                      continue
                  df = dataframe_from_jxml(cast(Iterable, xml))
  
                  # Needed until *-*-mindeps-numpy shows up in TEST_ID
                  a["name"] = a["name"].replace("--", "-numpy-")
  
                  # TODO: Some artifacts created w/ wrong name in dask
                  # This can be removed after ~90 days.
                  # Between time https://github.com/dask/dask/pull/10769 was merged and
                  # then https://github.com/dask/dask/pull/10781 which changed the name
                  if a["name"].startswith(
                      "test-results"
                  ) and repo.endswith("/dask"):
                      continue
  
                  # NOTE: Temporarily ignore reporting dask-expr related test cases
                  if "dask-expr" in a["name"]:
                      continue
  
                  # Note: we assign a column with the workflow run timestamp rather
                  # than the artifact timestamp so that artifacts triggered under
                  # the same workflow run can be aligned according to the same trigger
                  # time.
                  html_url = jobs_df[
                      jobs_df["suite_name"] == a["name"]
                  ].html_url.unique()
                  assert (
                      len(html_url) == 1
                  ), f"Artifact suite name {a['name']} did not match any jobs dataframe:\n{jobs_df['suite_name'].unique()}"
                  html_url = html_url[0]
                  assert html_url is not None
                  df2 = df.assign(
                      name=a["name"],
                      suite=suite_from_name(
                          a["name"],
                          None if repo.endswith("/dask") else 4,
                      ),
                      date=r["created_at"],
                      html_url=html_url,
                  )
  
                  if df2 is not None:
                      yield df2
  
                  ndownloaded += 1
                  if ndownloaded and not ndownloaded % 20:
                      print(f"{ndownloaded}... ", end="")
  
imports: from __future__ import annotations
  import argparse
  import contextlib
  import html
  import io
  import os
  import re
  import shelve
  import sys
  import zipfile
  from collections.abc import Iterable, Iterator
  from concurrent.futures import ProcessPoolExecutor
  from typing import Any, cast
  import altair
  import altair_saver
  import junitparser
  import pandas
  import requests
  from requests.adapters import HTTPAdapter
  from urllib3.util.retry import Retry
label_desc: Use image node_id 11 for calling a global function with example usage: download_and_parse_artifacts(repo, branch, events, max_days, max_runs) without return types