code: def get(
      prefixes,
      recursive=None,
      num_workers=None,
      inputs=None,
      verify=None,
      info=None,
      allow_missing=None,
      verbose=None,
      listing=None,
      s3role=None,
      s3sessionvars=None,
      s3clientparams=None,
      inject_failure=0,
  ):
      s3config = S3Config(
          s3role,
          json.loads(s3sessionvars) if s3sessionvars else None,
          json.loads(s3clientparams) if s3clientparams else None,
      )
  
      # Construct a list of URL (prefix) objects
      urllist = []
      to_iterate, is_transient_retry = _populate_prefixes(
          prefixes, inputs
      )
      for idx, prefix, url, r in to_iterate:
          src = urlparse(url)
          url = S3Url(
              url=url,
              bucket=src.netloc,
              path=src.path.lstrip("/"),
              local=generate_local_path(url, range=r),
              prefix=prefix,
              range=r,
              idx=idx,
          )
          if src.scheme != "s3":
              exit(ERROR_INVALID_URL, url)
          if not recursive and not src.path:
              exit(ERROR_NOT_FULL_PATH, url)
          urllist.append(url)
      # Construct a URL->size mapping and get content-type and metadata if needed
      op = None
      dl_op = "download"
      if recursive:
          op = partial(op_list_prefix, s3config)
      if verify or verbose or info:
          dl_op = "info_download"
      if op:
          if is_transient_retry:
              raise RuntimeError(
                  "--recursive not allowed for transient retries"
              )
          urls = []
          # NOTE - we must retain the order of prefixes requested
          # and the listing order returned by S3
          for success, prefix_url, ret in parallel_op(
              op, urllist, num_workers
          ):
              if success:
                  urls.extend(ret)
              elif ret == ERROR_URL_NOT_FOUND and allow_missing:
                  urls.append((prefix_url, None))
              else:
                  exit(ret, prefix_url)
          # We re-index here since we may have pulled in a bunch more stuff. On a transient
          # retry, we never have recursive so we would not re-index
          for idx, (url, _) in enumerate(urls):
              url.idx = idx
      else:
          # pretend zero size since we don't need it for anything.
          # it can't be None though, to make sure the listing below
          # works correctly (None denotes a missing file)
          urls = [(prefix_url, 0) for prefix_url in urllist]
  
      # exclude the non-existent files from loading
      to_load = [url for url, size in urls if size is not None]
      sz_results = process_urls(
          dl_op, to_load, verbose, inject_failure, num_workers, s3config
      )
      # We check if there is any access denied
      retry_lines = []
      out_lines = []
      denied_url = None
      missing_url = None
      verify_info = []
      idx_in_sz = 0
      for url, _ in urls:
          sz = None
          # to_load contains an ordered subset of urls
          if (
              idx_in_sz != len(to_load)
              and url.url == to_load[idx_in_sz].url
          ):
              sz = sz_results[idx_in_sz]
              idx_in_sz += 1
          if listing and sz is None:
              out_lines.append(
                  format_result_line(url.idx, url.url) + "\n"
              )
          elif listing and sz >= 0:
              out_lines.append(
                  format_result_line(
                      url.idx, url.prefix, url.url, url.local
                  )
                  + "\n"
              )
              if verify:
                  verify_info.append((url, sz))
          elif sz == -ERROR_URL_ACCESS_DENIED:
              denied_url = url
              break
          elif sz == -ERROR_URL_NOT_FOUND:
              if missing_url is None:
                  missing_url = url
              if not allow_missing:
                  break
              out_lines.append(
                  format_result_line(url.idx, url.url) + "\n"
              )
          elif sz == -ERROR_TRANSIENT:
              retry_lines.append(
                  " ".join(
                      [
                          str(url.idx),
                          url_quote(url.prefix).decode(
                              encoding="utf-8"
                          ),
                          url_quote(url.url).decode(encoding="utf-8"),
                          url_quote(url.range).decode(encoding="utf-8")
                          if url.range
                          else "<norange>",
                      ]
                  )
                  + "\n"
              )
              # First time around, we output something to indicate the total length
              if not is_transient_retry:
                  out_lines.append(
                      "%d %s\n"
                      % (url.idx, TRANSIENT_RETRY_LINE_CONTENT)
                  )
  
      if denied_url is not None:
          exit(ERROR_URL_ACCESS_DENIED, denied_url)
  
      if not allow_missing and missing_url is not None:
          exit(ERROR_URL_NOT_FOUND, missing_url)
  
      # Postprocess
      if verify:
          verify_results(verify_info, verbose=verbose)
  
      if out_lines:
          sys.stdout.writelines(out_lines)
          sys.stdout.flush()
  
      if retry_lines:
          sys.stderr.write("%s\n" % TRANSIENT_RETRY_START_LINE)
          sys.stderr.writelines(retry_lines)
          sys.stderr.flush()
          sys.exit(ERROR_TRANSIENT)
  
imports: from __future__ import print_function
  import json
  import time
  import math
  import random
  import re
  import sys
  import os
  import traceback
  from collections import namedtuple
  from functools import partial, wraps
  from hashlib import sha1
  from tempfile import NamedTemporaryFile
  from multiprocessing import Process, Queue
  from itertools import starmap, chain, islice
  from boto3.s3.transfer import TransferConfig
  from metaflow._vendor import click
  from metaflow.util import TempDir, url_quote, url_unquote
  from metaflow.multicore_utils import parallel_map
  from metaflow.plugins.datatools.s3.s3util import aws_retry, read_in_chunks, get_timestamp, TRANSIENT_RETRY_LINE_CONTENT, TRANSIENT_RETRY_START_LINE
  import metaflow.tracing
label_desc: Use image node_id 20 for calling a global function with example usage: get(prefixes, recursive, num_workers, inputs, verify, info, allow_missing, verbose, listing, s3role, s3sessionvars, s3clientparams, inject_failure) without return types