class_docstr: Store and load checkpoints from S3.
code: def upload(
      self,
      src: Union[str, os.PathLike],
      dst: str,
      paths: Optional[storage.Paths] = None,
  ) -> None:
      src = os.fspath(src)
      prefix = self.get_storage_prefix(dst)
      logger.info(f"Uploading to s3: prefix={prefix}")
      upload_paths = (
          paths if paths is not None else self._list_directory(src)
      )
      for rel_path in sorted(upload_paths):
          key_name = f"{prefix}/{rel_path}"
          logger.debug(
              f"Uploading {rel_path} to s3://{self.bucket_name}/{key_name}"
          )
  
          if rel_path.endswith("/"):
              # Create empty S3 keys for each subdirectory to mimic what the S3 console does to
              # represent empty directories.
              if not self._use_minio_workaround:
                  self.bucket.put_object(Key=key_name, Body=b"")
              else:
                  # boto3 will puke on the following MinIO response if you ever create a
                  # directory by uploading an empty blob.  Uploading a normal file in the
                  # directory and then deleting it seems to cause MinIO to prune the empty
                  # directory.  The AWS authentication scheme is complex and not worth the
                  # effort for supporting empty directories, so... just ignore empty directories.
                  pass
          else:
              abs_path = os.path.join(src, rel_path)
              self.bucket.upload_file(abs_path, key_name)
  
file_path: determined/harness/determined/common/storage/s3.py
imports: import logging
  import os
  import re
  import tempfile
  from typing import Dict, List, Optional, Union
  import requests
  from determined import errors
  from determined.common import storage, util
label_desc: Use image node_id 3 for calling the S3StorageManager obj's underlying member method code with example usage: obj.upload(src, dst, paths) without return types