code: def upload_artifact(
      self,
      name,  # type: str
      artifact_object=None,  # type: Optional[object]
      metadata=None,  # type: Optional[dict]
      preview=None,  # type: Optional[str]
      delete_after_upload=False,  # type: bool
      auto_pickle=True,  # type: bool
      wait_on_upload=False,  # type: bool
      extension_name=None,  # type: Optional[str]
      serialization_function=None,  # type: Optional[Callable[[Any], Union[bytes, bytearray]]]
  ):
      # type: (...) -> bool
      if not Session.check_min_api_version("2.3"):
          LoggerRoot.get_base_logger().warning(
              "Artifacts not supported by your ClearML-server version,"
              " please upgrade to the latest server version"
          )
          return False
  
      if name in self._artifacts_container:
          raise ValueError(
              "Artifact by the name of {} is already registered, use register_artifact".format(
                  name
              )
          )
  
      # cast preview to string
      if preview is not None and not (
          isinstance(preview, bool) and preview is False
      ):
          preview = str(preview)
  
      # evaluate lazy proxy object
      if isinstance(artifact_object, LazyEvalWrapper):
          # noinspection PyProtectedMember
          artifact_object = LazyEvalWrapper._load_object(
              artifact_object
          )
  
      pathlib_types = (
          (
              Path,
              pathlib_Path,
          )
          if pathlib_Path is not None
          else (Path,)
      )
      local_filename = None
  
      # try to convert string Path object (it might reference a file/folder)
      # dont not try to serialize long texts.
      if (
          isinstance(artifact_object, six.string_types)
          and artifact_object
          and len(artifact_object) < 2048
      ):
          # noinspection PyBroadException
          try:
              artifact_path = Path(artifact_object)
              if artifact_path.exists():
                  artifact_object = artifact_path
              elif "*" in artifact_object or "?" in artifact_object:
                  # hackish, detect wildcard in tr files
                  folder = Path("").joinpath(*artifact_path.parts[:-1])
                  if folder.is_dir() and folder.parts:
                      wildcard = artifact_path.parts[-1]
                      if list(Path(folder).rglob(wildcard)):
                          artifact_object = artifact_path
          except Exception:
              pass
  
      store_as_pickle = False
      artifact_type_data = tasks.ArtifactTypeData()
      artifact_type_data.preview = ""
      override_filename_in_uri = None
      override_filename_ext_in_uri = None
      uri = None
  
      def get_extension(
          extension_name_,
          valid_extensions,
          default_extension,
          artifact_type_,
      ):
          if not extension_name_:
              return default_extension
          if extension_name_ in valid_extensions:
              return extension_name_
          LoggerRoot.get_base_logger().warning(
              "{} artifact can not be uploaded with extension {}. Valid extensions are: {}. Defaulting to {}.".format(
                  artifact_type_,
                  extension_name_,
                  ", ".join(valid_extensions),
                  default_extension,
              )
          )
          return default_extension
  
      if serialization_function:
          artifact_type = "custom"
          # noinspection PyBroadException
          try:
              artifact_type_data.preview = (
                  preview
                  or str(artifact_object.__repr__())[
                      : self.max_preview_size_bytes
                  ]
              )
          except Exception:
              artifact_type_data.preview = ""
          override_filename_ext_in_uri = extension_name or ""
          override_filename_in_uri = name + override_filename_ext_in_uri
          local_filename = self._push_temp_file(
              prefix=quote(name, safe="") + ".",
              suffix=override_filename_ext_in_uri,
          )
          # noinspection PyBroadException
          try:
              with open(local_filename, "wb") as f:
                  f.write(serialization_function(artifact_object))
          except Exception:
              # cleanup and raise exception
              self._delete_temp_file(local_filename)
              raise
          artifact_type_data.content_type = mimetypes.guess_type(
              local_filename
          )[0]
      elif extension_name == ".pkl":
          store_as_pickle = True
      elif np and isinstance(artifact_object, np.ndarray):
          artifact_type = "numpy"
          artifact_type_data.preview = preview or str(
              artifact_object.__repr__()
          )
          override_filename_ext_in_uri = get_extension(
              extension_name, [".npz", ".csv.gz"], ".npz", artifact_type
          )
          override_filename_in_uri = name + override_filename_ext_in_uri
          local_filename = self._push_temp_file(
              prefix=quote(name, safe="") + ".",
              suffix=override_filename_ext_in_uri,
          )
          if override_filename_ext_in_uri == ".npz":
              artifact_type_data.content_type = "application/numpy"
              np.savez_compressed(
                  local_filename, **{name: artifact_object}
              )
          elif override_filename_ext_in_uri == ".csv.gz":
              artifact_type_data.content_type = "text/csv"
              np.savetxt(local_filename, artifact_object, delimiter=",")
          delete_after_upload = True
      elif pd and isinstance(artifact_object, pd.DataFrame):
          artifact_type = "pandas"
          artifact_type_data.preview = preview or str(
              artifact_object.__repr__()
          )
          override_filename_ext_in_uri = get_extension(
              extension_name,
              [".csv.gz", ".parquet", ".feather", ".pickle"],
              ".csv.gz",
              artifact_type,
          )
          override_filename_in_uri = name
          local_filename = self._push_temp_file(
              prefix=quote(name, safe="") + ".",
              suffix=override_filename_ext_in_uri,
          )
          if override_filename_ext_in_uri == ".csv.gz":
              artifact_type_data.content_type = "text/csv"
              self._store_compressed_pd_csv(
                  artifact_object, local_filename
              )
          elif override_filename_ext_in_uri == ".parquet":
              try:
                  artifact_type_data.content_type = (
                      "application/parquet"
                  )
                  artifact_object.to_parquet(local_filename)
              except Exception as e:
                  LoggerRoot.get_base_logger().warning(
                      "Exception '{}' encountered when uploading artifact as .parquet. Defaulting to .csv.gz".format(
                          e
                      )
                  )
                  artifact_type_data.content_type = "text/csv"
                  self._store_compressed_pd_csv(
                      artifact_object, local_filename
                  )
          elif override_filename_ext_in_uri == ".feather":
              try:
                  artifact_type_data.content_type = (
                      "application/feather"
                  )
                  artifact_object.to_feather(local_filename)
              except Exception as e:
                  LoggerRoot.get_base_logger().warning(
                      "Exception '{}' encountered when uploading artifact as .feather. Defaulting to .csv.gz".format(
                          e
                      )
                  )
                  artifact_type_data.content_type = "text/csv"
                  self._store_compressed_pd_csv(
                      artifact_object, local_filename
                  )
          elif override_filename_ext_in_uri == ".pickle":
              artifact_type_data.content_type = "application/pickle"
              artifact_object.to_pickle(local_filename)
          delete_after_upload = True
      elif isinstance(artifact_object, Image.Image):
          artifact_type = "image"
          artifact_type_data.content_type = "image/png"
          desc = str(artifact_object.__repr__())
          artifact_type_data.preview = (
              preview or desc[1 : desc.find(" at ")]
          )
  
          # noinspection PyBroadException
          try:
              if not Image.EXTENSION:
                  Image.init()
                  if not Image.EXTENSION:
                      raise Exception()
              override_filename_ext_in_uri = get_extension(
                  extension_name,
                  Image.EXTENSION.keys(),
                  ".png",
                  artifact_type,
              )
          except Exception:
              override_filename_ext_in_uri = ".png"
              if extension_name and extension_name != ".png":
                  LoggerRoot.get_base_logger().warning(
                      "image artifact can not be uploaded with extension {}. Defaulting to .png.".format(
                          extension_name
                      )
                  )
  
          override_filename_in_uri = name + override_filename_ext_in_uri
          artifact_type_data.content_type = "image/unknown-type"
          guessed_type = mimetypes.guess_type(override_filename_in_uri)[
              0
          ]
          if guessed_type:
              artifact_type_data.content_type = guessed_type
  
          local_filename = self._push_temp_file(
              prefix=quote(name, safe="") + ".",
              suffix=override_filename_ext_in_uri,
          )
          artifact_object.save(local_filename)
          delete_after_upload = True
      elif isinstance(artifact_object, dict):
          artifact_type = "dict"
          override_filename_ext_in_uri = get_extension(
              extension_name, [".json", ".yaml"], ".json", artifact_type
          )
          if override_filename_ext_in_uri == ".json":
              artifact_type_data.content_type = "application/json"
              # noinspection PyBroadException
              try:
                  serialized_text = json.dumps(
                      artifact_object, sort_keys=True, indent=4
                  )
              except Exception:
                  if not auto_pickle:
                      raise
                  LoggerRoot.get_base_logger().warning(
                      "JSON serialization of artifact '{}' failed, reverting to pickle".format(
                          name
                      )
                  )
                  store_as_pickle = True
                  serialized_text = None
          else:
              artifact_type_data.content_type = "application/yaml"
              # noinspection PyBroadException
              try:
                  serialized_text = yaml.dump(
                      artifact_object, sort_keys=True, indent=4
                  )
              except Exception:
                  if not auto_pickle:
                      raise
                  LoggerRoot.get_base_logger().warning(
                      "YAML serialization of artifact '{}' failed, reverting to pickle".format(
                          name
                      )
                  )
                  store_as_pickle = True
                  serialized_text = None
  
          if serialized_text is not None:
              override_filename_in_uri = (
                  name + override_filename_ext_in_uri
              )
              local_filename = self._push_temp_file(
                  prefix=quote(name, safe="") + ".",
                  suffix=override_filename_ext_in_uri,
              )
              with open(local_filename, "w") as f:
                  f.write(serialized_text)
              preview = preview or serialized_text
              if len(preview) < self.max_preview_size_bytes:
                  artifact_type_data.preview = preview
              else:
                  artifact_type_data.preview = "# full serialized dict too large to store, storing first {}kb\n{}".format(
                      self.max_preview_size_bytes // 1024,
                      preview[: self.max_preview_size_bytes],
                  )
              delete_after_upload = True
      elif isinstance(artifact_object, pathlib_types):
          # check if single file
          artifact_object = Path(artifact_object)
  
          artifact_object.expanduser().absolute()
          # noinspection PyBroadException
          try:
              create_zip_file = not artifact_object.is_file()
          except (
              Exception
          ):  # Hack for windows pathlib2 bug, is_file isn't valid.
              create_zip_file = True
          else:  # We assume that this is not Windows os
              if artifact_object.is_dir():
                  # change to wildcard
                  artifact_object /= "*"
  
          if create_zip_file:
              folder = Path("").joinpath(*artifact_object.parts[:-1])
              if not folder.is_dir() or not folder.parts:
                  raise ValueError(
                      "Artifact file/folder '{}' could not be found".format(
                          artifact_object.as_posix()
                      )
                  )
  
              wildcard = artifact_object.parts[-1]
              files = list(Path(folder).rglob(wildcard))
              override_filename_ext_in_uri = ".zip"
              override_filename_in_uri = (
                  folder.parts[-1] + override_filename_ext_in_uri
              )
              zip_file = self._push_temp_file(
                  prefix=quote(folder.parts[-1], safe="") + ".",
                  suffix=override_filename_ext_in_uri,
              )
              try:
                  artifact_type_data.content_type = "application/zip"
                  archive_preview = "Archive content {}:\n".format(
                      artifact_object.as_posix()
                  )
  
                  with ZipFile(
                      zip_file,
                      "w",
                      allowZip64=True,
                      compression=ZIP_DEFLATED,
                  ) as zf:
                      for filename in sorted(files):
                          if filename.is_file():
                              relative_file_name = filename.relative_to(
                                  folder
                              ).as_posix()
                              archive_preview += "{} - {}\n".format(
                                  relative_file_name,
                                  format_size(filename.stat().st_size),
                              )
                              zf.write(
                                  filename.as_posix(),
                                  arcname=relative_file_name,
                              )
              except Exception as e:
                  # failed uploading folder:
                  LoggerRoot.get_base_logger().warning(
                      "Exception {}\nFailed zipping artifact folder {}".format(
                          folder, e
                      )
                  )
                  return False
  
              artifact_type_data.preview = preview or archive_preview
              artifact_object = zip_file
              artifact_type = "archive"
              artifact_type_data.content_type = mimetypes.guess_type(
                  artifact_object
              )[0]
              local_filename = artifact_object
              delete_after_upload = True
          else:
              if not artifact_object.is_file():
                  raise ValueError(
                      "Artifact file '{}' could not be found".format(
                          artifact_object.as_posix()
                      )
                  )
  
              override_filename_in_uri = artifact_object.parts[-1]
              artifact_type_data.preview = (
                  preview
                  or "{} - {}\n".format(
                      artifact_object.name,
                      format_size(artifact_object.stat().st_size),
                  )
              )
              artifact_object = artifact_object.as_posix()
              artifact_type = "custom"
              artifact_type_data.content_type = mimetypes.guess_type(
                  artifact_object
              )[0]
              local_filename = artifact_object
      elif (
          isinstance(artifact_object, (list, tuple))
          and artifact_object
          and all(isinstance(p, pathlib_types) for p in artifact_object)
      ):
          # find common path if exists
          list_files = [Path(p) for p in artifact_object]
          override_filename_ext_in_uri = ".zip"
          override_filename_in_uri = (
              quote(name, safe="") + override_filename_ext_in_uri
          )
          common_path = get_common_path(list_files)
          zip_file = self._push_temp_file(
              prefix="artifact_folder.",
              suffix=override_filename_ext_in_uri,
          )
          try:
              artifact_type_data.content_type = "application/zip"
              archive_preview = "Archive content:\n"
  
              with ZipFile(
                  zip_file,
                  "w",
                  allowZip64=True,
                  compression=ZIP_DEFLATED,
              ) as zf:
                  for filename in sorted(list_files):
                      if filename.is_file():
                          relative_file_name = (
                              filename.relative_to(
                                  Path(common_path)
                              ).as_posix()
                              if common_path
                              else filename.as_posix()
                          )
                          archive_preview += "{} - {}\n".format(
                              relative_file_name,
                              format_size(filename.stat().st_size),
                          )
                          zf.write(
                              filename.as_posix(),
                              arcname=relative_file_name,
                          )
                      else:
                          LoggerRoot.get_base_logger().warning(
                              "Failed zipping artifact file '{}', file not found!".format(
                                  filename.as_posix()
                              )
                          )
          except Exception as e:
              # failed uploading folder:
              LoggerRoot.get_base_logger().warning(
                  "Exception {}\nFailed zipping artifact files {}".format(
                      artifact_object, e
                  )
              )
              return False
  
          artifact_type_data.preview = preview or archive_preview
          artifact_object = zip_file
          artifact_type = "archive"
          artifact_type_data.content_type = mimetypes.guess_type(
              artifact_object
          )[0]
          local_filename = artifact_object
          delete_after_upload = True
      elif (
          isinstance(artifact_object, six.string_types)
          and len(artifact_object) < 4096
          and urlparse(artifact_object).scheme in remote_driver_schemes
      ):
          # we should not upload this, just register
          local_filename = None
          uri = artifact_object
          artifact_type = "custom"
          artifact_type_data.content_type = mimetypes.guess_type(
              artifact_object
          )[0]
          if preview:
              artifact_type_data.preview = preview
      elif (
          isinstance(artifact_object, six.string_types)
          and artifact_object
      ):
          # if we got here, we should store it as text file.
          artifact_type = "string"
          artifact_type_data.content_type = "text/plain"
          if preview:
              artifact_type_data.preview = preview
          elif len(artifact_object) < self.max_preview_size_bytes:
              artifact_type_data.preview = artifact_object
          else:
              artifact_type_data.preview = "# full text too large to store, storing first {}kb\n{}".format(
                  self.max_preview_size_bytes // 1024,
                  artifact_object[: self.max_preview_size_bytes],
              )
          delete_after_upload = True
          override_filename_ext_in_uri = ".txt"
          override_filename_in_uri = name + override_filename_ext_in_uri
          local_filename = self._push_temp_file(
              prefix=quote(name, safe="") + ".",
              suffix=override_filename_ext_in_uri,
          )
          # noinspection PyBroadException
          try:
              with open(local_filename, "wt") as f:
                  f.write(artifact_object)
          except Exception:
              # cleanup and raise exception
              self._delete_temp_file(local_filename)
              raise
      elif artifact_object is None or (
          isinstance(artifact_object, str) and artifact_object == ""
      ):
          artifact_type = ""
          store_as_pickle = True
      elif auto_pickle:
          # revert to pickling the object
          store_as_pickle = True
      else:
          raise ValueError(
              "Artifact type {} not supported".format(
                  type(artifact_object)
              )
          )
  
      # revert to serializing the object with pickle
      if store_as_pickle:
          # if we are here it means we do not know what to do with the object, so we serialize it with pickle.
          artifact_type = "pickle"
          artifact_type_data.content_type = "application/pickle"
          # noinspection PyBroadException
          try:
              artifact_type_data.preview = (
                  preview
                  or str(artifact_object.__repr__())[
                      : self.max_preview_size_bytes
                  ]
              )
          except Exception:
              artifact_type_data.preview = preview or ""
          delete_after_upload = True
          override_filename_ext_in_uri = ".pkl"
          override_filename_in_uri = name + override_filename_ext_in_uri
          local_filename = self._push_temp_file(
              prefix=quote(name, safe="") + ".",
              suffix=override_filename_ext_in_uri,
          )
          # noinspection PyBroadException
          try:
              with open(local_filename, "wb") as f:
                  pickle.dump(artifact_object, f)
          except Exception:
              # cleanup and raise exception
              self._delete_temp_file(local_filename)
              raise
  
      # verify preview not out of scope:
      if artifact_type_data.preview and len(
          artifact_type_data.preview
      ) > (self.max_preview_size_bytes + 1024):
          artifact_type_data.preview = "# full preview too large to store, storing first {}kb\n{}".format(
              self.max_preview_size_bytes // 1024,
              artifact_type_data.preview[: self.max_preview_size_bytes],
          )
  
      # remove from existing list, if exists
      for artifact in self._task_artifact_list:
          if artifact.key == name:
              if artifact.type == self._pd_artifact_type:
                  raise ValueError(
                      "Artifact of name {} already registered, "
                      "use register_artifact instead".format(name)
                  )
  
              self._task_artifact_list.remove(artifact)
              break
  
      if not local_filename:
          file_size = None
          file_hash = None
      else:
          # check that the file to upload exists
          local_filename = Path(local_filename).absolute()
          if (
              not local_filename.exists()
              or not local_filename.is_file()
          ):
              LoggerRoot.get_base_logger().warning(
                  "Artifact upload failed, cannot find file {}".format(
                      local_filename.as_posix()
                  )
              )
              return False
  
          file_hash, _ = sha256sum(
              local_filename.as_posix(),
              block_size=Artifacts._hash_block_size,
          )
          file_size = local_filename.stat().st_size
  
          uri = self._upload_local_file(
              local_filename,
              name,
              delete_after_upload=delete_after_upload,
              override_filename=override_filename_in_uri,
              override_filename_ext=override_filename_ext_in_uri,
              wait_on_upload=wait_on_upload,
          )
  
      timestamp = int(time())
  
      artifact = tasks.Artifact(
          key=name,
          type=artifact_type,
          uri=uri,
          content_size=file_size,
          hash=file_hash,
          timestamp=timestamp,
          type_data=artifact_type_data,
          display_data=[(str(k), str(v)) for k, v in metadata.items()]
          if metadata
          else None,
      )
  
      # update task artifacts
      self._add_artifact(artifact)
  
      return True
  
imports: import gzip
  import io
  import json
  import yaml
  import mimetypes
  import os
  import pickle
  from six.moves.urllib.parse import quote
  from copy import deepcopy
  from datetime import datetime
  from multiprocessing.pool import ThreadPool
  from tempfile import mkdtemp, mkstemp
  from threading import Thread
  from time import time
  from zipfile import ZipFile, ZIP_DEFLATED
  import six
  from PIL import Image
  from pathlib2 import Path
  from six.moves.urllib.parse import urlparse
  from typing import Dict, Union, Optional, Any, Sequence, Callable
  from ..backend_api import Session
  from ..backend_api.services import tasks
  from ..backend_interface.metrics.events import UploadEvent
  from ..debugging.log import LoggerRoot
  from ..storage.helper import remote_driver_schemes
  from ..storage.util import sha256sum, format_size, get_common_path
  from ..utilities.process.mp import SafeEvent, ForkSafeRLock
  from ..utilities.proxy_object import LazyEvalWrapper
label_desc: Use image node_id 6 for calling the Artifacts obj's underlying member method code with example usage: obj.upload_artifact(name, artifact_object, metadata, preview, delete_after_upload, auto_pickle, wait_on_upload, extension_name, serialization_function) and returns: True, False, default_extension, default_extension, extension_name_, False, False, False