docs: def upload_sequence(
      files,
      session,
      samples_resource,
      metadata=None,
      tags=None,
      project=None,
      coerce_ascii=False,
      progressbar=None,
  ):
      """Uploads a sequence file (or pair of files) to the One Codex server via either our proxy or directly to S3.
  
      Parameters
      ----------
      files : `list`
          A list of paths to files on the system, or tuples containing pairs of paths. Tuples will be
          interleaved as paired-end reads and both files should contain the same number of records.
          Paths to single files will be uploaded as-is.
      session : `requests.Session`
          Connection to One Codex API.
      samples_resource : `onecodex.models.Samples`
          Wrapped potion-client object exposing `init_upload` and `confirm_upload` methods.
      metadata : `dict`, optional
      tags : `list`, optional
      project : `string`, optional
          UUID of project to associate this sample with.
      coerce_ascii : `bool`, optional
          If true, rename unicode filenames to ASCII and issue warning.
      progressbar : `click.progressbar`, optional
          If passed, display a progress bar using Click.
  
      Returns
      -------
      A Sample object for the completed upload.
      """
      filename, file_size, file_format = _file_stats(files)
  
      # if filename cannot be represented as ascii, raise and suggest renaming
      try:
          # python2
          ascii_fname = unidecode(unicode(filename))
      except NameError:
          ascii_fname = unidecode(filename)
  
      if filename != ascii_fname:
          if coerce_ascii:
              # TODO: Consider warnings.warn here instead
              logging.warn(
                  "Renaming {} to {}, must be ASCII\n".format(filename.encode("utf-8"), ascii_fname)
              )
              filename = ascii_fname
          else:
              raise OneCodexException("Filenames must be ascii. Try using --coerce-ascii")
  
      # disable progressbar while keeping context manager
      if not progressbar:
          progressbar = FakeProgressBar()
  
      # file_path is the path to the file on this disk. file_name is what we'll call the file in the
      # mainline database. file_size is the sum of both files in a pair, or the size of an unpaired
      # file. if paired, file_size is the uncompressed size. if unpaired, file_size is the actual
      # size on disk. unpaired files are uploaded as-is. paired files are decompressed, interleaved,
      # and uploaded as uncompressed data.
      with progressbar as bar:
          if isinstance(files, tuple):
              fobj = FASTXInterleave(files, file_size, file_format, bar)
          else:
              fobj = FilePassthru(files, file_size, bar)
  
          # must call init_upload in this loop in order to get a sample uuid we can call
          # cancel_upload on later if user hits ctrl+c
          fields = _call_init_upload(filename, file_size, metadata, tags, project, samples_resource)
  
          def cancel_atexit():
              bar.canceled = True
              bar.update(1)
              logging.info("Canceled upload for sample: {}".format(fields["sample_id"]))
              samples_resource.cancel_upload({"sample_id": fields["sample_id"]})
  
          atexit_register(cancel_atexit)
  
          # if the upload via init_upload fails, upload_sequence_fileobj will call
          # init_multipart_upload, which accepts metadata to be integrated into a newly-created
          # Sample model. if the s3 intermediate route is used, two Sample models will ultimately
          # exist on mainline: the failed fastx-proxy upload and the successful s3 intermediate.
          retry_fields = _make_retry_fields(filename, metadata, tags, project)
  
          try:
              sample_id = upload_sequence_fileobj(
                  fobj, filename, fields, retry_fields, session, samples_resource
              )
              atexit_unregister(cancel_atexit)
              return sample_id
          except KeyboardInterrupt:
              cancel_atexit()
              atexit_unregister(cancel_atexit)
              raise