class_docstr: SnapshotController inherits from BaseController and manages business logic related to snapshots
  
  Attributes
  ----------
  code : datmo.core.controller.code.code.CodeController
  file_collection : datmo.core.controller.file.file_collection.FileCollectionController
  environment : datmo.core.controller.environment.environment.EnvironmentController
  
  Methods
  -------
  create(dictionary)
      Create a snapshot within the project
  checkout(id)
      Checkout to a specific snapshot within the project
  list(visible=None, sort_key=None, sort_order=None)
      List all snapshots present within the project based on given filters
  delete(id)
      Delete the snapshot specified from the project
docstr: Create snapshot from a completed task.
  # TODO: enable create from task DURING a run
  
  Parameters
  ----------
  message : str
      long description of snapshot
  task_id : str
      task object to use to create snapshot
  label: str, optional
      short description of snapshot
  config : dict, optional
      key, value pairs of configurations
  stats : dict, optional
      key, value pairs of metrics and statistics
  
  Returns
  -------
  datmo.core.entity.snapshot.Snapshot
      snapshot object with all relevant parameters
  
  Raises
  ------
  TaskNotComplete
      if task specified has not been completed
docstr_tok: ["Create","snapshot","from","a","completed","task",".","#","TODO",":","enable","create","from","task","DURING","a","run","Parameters","--","--","--","--","--","message",":","str","long","description","of","snapshot","task_id",":","str","task","object","to","use","to","create","snapshot","label",":","str",",","optional","short","description","of","snapshot","config",":","dict",",","optional","key",",","value","pairs","of","configurations","stats",":","dict",",","optional","key",",","value","pairs","of","metrics","and","statistics","Returns","--","--","--","-","datmo.core.entity.snapshot.Snapshot","snapshot","object","with","all","relevant","parameters","Raises","--","--","--","TaskNotComplete","if","task","specified","has","not","been","completed"]
code: def create_from_task(
      self, message, task_id, label=None, config=None, stats=None
  ):
      """Create snapshot from a completed task.
      # TODO: enable create from task DURING a run
  
      Parameters
      ----------
      message : str
          long description of snapshot
      task_id : str
          task object to use to create snapshot
      label: str, optional
          short description of snapshot
      config : dict, optional
          key, value pairs of configurations
      stats : dict, optional
          key, value pairs of metrics and statistics
  
      Returns
      -------
      datmo.core.entity.snapshot.Snapshot
          snapshot object with all relevant parameters
  
      Raises
      ------
      TaskNotComplete
          if task specified has not been completed
      """
  
      validate(
          "create_snapshot_from_task",
          {
              "message": message,
              "task_id": task_id,
              "label": label,
              "config": config,
              "stats": stats,
          },
      )
  
      task_obj = self.dal.task.get_by_id(task_id)
  
      if not task_obj.status and not task_obj.after_snapshot_id:
          raise TaskNotComplete(
              __(
                  "error",
                  "controller.snapshot.create_from_task",
                  str(task_obj.id),
              )
          )
  
      after_snapshot_obj = self.dal.snapshot.get_by_id(
          task_obj.after_snapshot_id
      )
  
      snapshot_update_dict = {
          "id": task_obj.after_snapshot_id,
          "message": message,
          "visible": True,
      }
  
      if label:
          snapshot_update_dict["label"] = label
  
      if config:
          snapshot_update_dict["config"] = config
  
      if stats:
          snapshot_update_dict["stats"] = stats
      else:
          # Append to any existing stats already present
          snapshot_update_dict["stats"] = {}
          if after_snapshot_obj.stats is not None:
              snapshot_update_dict["stats"].update(
                  after_snapshot_obj.stats
              )
          if task_obj.results is not None:
              snapshot_update_dict["stats"].update(task_obj.results)
          if snapshot_update_dict["stats"] == {}:
              snapshot_update_dict["stats"] = None
  
      return self.dal.snapshot.update(snapshot_update_dict)
  
imports: import os
  from datmo.core.controller.base import BaseController
  from datmo.core.controller.code.code import CodeController
  from datmo.core.controller.file.file_collection import FileCollectionController
  from datmo.core.controller.environment.environment import EnvironmentController
  from datmo.core.entity.snapshot import Snapshot
  from datmo.core.util.i18n import get
  from datmo.core.util.validation import validate
  from datmo.core.util.json_store import JSONStore
  from datmo.core.util.exceptions import FileIOError, RequiredArgumentMissing, ProjectNotInitialized, EntityNotFound, TaskNotComplete, DoesNotExist, UnstagedChanges
label_desc: Use image node_id 4 for calling the SnapshotController obj's underlying member method code with example usage: obj.create_from_task(message, task_id, label, config, stats) and returns: self