code: def test_put_files(
      tempdir,
      inject_failure_rate,
      s3root,
      blobs,
      expected,
      s3_server_side_encryption,
  ):
      def _files(blobs):
          for blob in blobs:
              key = getattr(blob, "key", blob[0])
              data = getattr(blob, "value", blob[1])
              content_type = getattr(blob, "content_type", None)
              metadata = getattr(blob, "metadata", None)
              encryption = getattr(blob, "encryption", None)
              path = os.path.join(tempdir, key)
              with open(path, "wb") as f:
                  f.write(data)
              yield S3PutObject(
                  key=key,
                  value=path,
                  content_type=content_type,
                  metadata=metadata,
                  encryption=encryption,
              )
  
      encryption_settings = [None, s3_server_side_encryption]
      for setting in encryption_settings:
          with S3(
              s3root=s3root,
              inject_failure_rate=inject_failure_rate,
              encryption=setting,
          ) as s3:
              s3urls = s3.put_files(_files(blobs))
              assert list(dict(s3urls)) == list(dict(blobs))
  
          with S3(
              inject_failure_rate=inject_failure_rate,
              encryption=setting,
          ) as s3:
              # get urls
              s3objs = s3.get_many(dict(s3urls).values())
              assert_results(s3objs, expected, encryption=setting)
  
          with S3(
              s3root=s3root,
              inject_failure_rate=inject_failure_rate,
              encryption=setting,
          ) as s3:
              # get keys
              s3objs = s3.get_many(key for key, blob in blobs)
              assert {s3obj.key for s3obj in s3objs} == {
                  key for key, _ in blobs
              }
  
          # upload shuffled blobs with overwrite disabled
          shuffled_blobs = blobs[:]
          shuffle(shuffled_blobs)
          with S3(
              s3root=s3root,
              inject_failure_rate=inject_failure_rate,
              encryption=setting,
          ) as s3:
              overwrite_disabled_s3urls = s3.put_files(
                  _files(shuffled_blobs), overwrite=False
              )
              assert len(overwrite_disabled_s3urls) == 0
  
          with S3(
              inject_failure_rate=inject_failure_rate,
              encryption=setting,
          ) as s3:
              s3objs = s3.get_many(dict(s3urls).values())
              assert_results(s3objs, expected, encryption=setting)
          with S3(
              s3root=s3root,
              inject_failure_rate=inject_failure_rate,
              encryption=setting,
          ) as s3:
              s3objs = s3.get_many(key for key, blob in shuffled_blobs)
              assert {s3obj.key for s3obj in s3objs} == {
                  key for key, _ in shuffled_blobs
              }
  
imports: import os
  from re import I
  import shutil
  from hashlib import sha1
  from tempfile import mkdtemp
  from itertools import groupby, starmap
  import random
  from uuid import uuid4
  from metaflow.plugins.datatools import s3
  import pytest
  from metaflow import current, namespace, Run
  from metaflow.plugins.datatools.s3 import S3, MetaflowS3AccessDenied, MetaflowS3NotFound, MetaflowS3URLException, MetaflowS3InvalidObject, S3PutObject, S3GetObject
  from metaflow.util import to_bytes, unicode_type
  from .None import s3_data
  from ..None import FakeFlow, DO_TEST_RUN
label_desc: Use image node_id 28 for calling a global function with example usage: test_put_files(tempdir, inject_failure_rate, s3root, blobs, expected, s3_server_side_encryption) without return types